Check-in [7e48f725c8]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge wip-midlevel into trunk, yay!
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7e48f725c8aba2dc5b267a6925bbc47521542606
User & Date: stephanie.gawroriski 2020-06-30 22:23:47
Context
2020-07-01
07:02
Backup developer notes. check-in: 134c2ad82a user: squirreljme tags: trunk, x-date-202007
2020-06-30
22:28
Create new branch named "wip-midlcdui" check-in: 5ddea90a4e user: stephanie.gawroriski tags: wip-midlcdui
22:23
Merge wip-midlevel into trunk, yay! check-in: 7e48f725c8 user: stephanie.gawroriski tags: trunk
22:14
Removal of ObjectAccess. Closed-Leaf check-in: 84d1b6e583 user: stephanie.gawroriski tags: wip-midlevel
07:02
Backup developer notes. check-in: 174e69a68a user: squirreljme tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to .circleci/config.yml.

89
90
91
92
93
94
95






















96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
































128
129
130
131
132
133
134
135



136
137
138
139
140

            mkdir -p ~/test-results/junit/
            find . -type f -regex '.*/build/test-results/.*xml' -exec cp {} ~/test-results/junit/ \;
          when: always
      - store_test_results:
          path: ~/test-results
      - store_artifacts:
          path: ~/test-results/junit






















  test_springcoat:
    executor: buildenv
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: SpringCoat Tests
          command: |
            if ! ./gradlew testSpringCoat --continue --parallel
            then
              echo "SpringCoat testing failed, ignoring..." 1>&2
            fi
          no_output_timeout: 2m
      - run:
          name: Save test results
          command: |
            mkdir -p ~/test-results/junit/
            find . -type f -regex '.*/springcoat/junit-reports/.*xml' -exec cp {} ~/test-results/junit/ \;
          when: always
      - run:
          name: Save snapshots
          command: |
            mkdir -p ~/test-results/nps/
            find . -type f -regex '.*/springcoat/nps/.*nps' -exec cp {} ~/test-results/nps/ \;
          when: always
      - store_test_results:
          path: ~/test-results
      - store_artifacts:
          path: ~/test-results/junit
      - store_artifacts:
          path: ~/test-results/nps

































workflows:
  version: 2
  tests:
    jobs:
      - build_windows
      - build_linux
      - build_macosx



      - test_springcoat:
          requires:
            - build_windows
            - build_linux
            - build_macosx








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








<
|
<
<
<
|


















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








>
>
>


|
|
|
>
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
            mkdir -p ~/test-results/junit/
            find . -type f -regex '.*/build/test-results/.*xml' -exec cp {} ~/test-results/junit/ \;
          when: always
      - store_test_results:
          path: ~/test-results
      - store_artifacts:
          path: ~/test-results/junit
  construct_testjars:
    executor: buildenv
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: Constuct Test JARs
          command: ./gradlew testJar --continue --parallel
      - persist_to_workspace:
          root: .
          paths:
            - '.gradle/*'
            - 'build/*'
            - 'buildSrc/.gradle/*'
            - 'buildSrc/build/*'
            - 'emulators/build/*'
            - 'emulators/*/build/*'
            - 'modules/build/*'
            - 'modules/*/build/*'
            - 'tools/build/*'
            - 'tools/*/build/*'
  test_springcoat:
    executor: buildenv
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: SpringCoat Tests

          command: timeout --foreground 15m ./gradlew testSpringCoat --console plain --continue --parallel



          no_output_timeout: 15m
      - run:
          name: Save test results
          command: |
            mkdir -p ~/test-results/junit/
            find . -type f -regex '.*/springcoat/junit-reports/.*xml' -exec cp {} ~/test-results/junit/ \;
          when: always
      - run:
          name: Save snapshots
          command: |
            mkdir -p ~/test-results/nps/
            find . -type f -regex '.*/springcoat/nps/.*nps' -exec cp {} ~/test-results/nps/ \;
          when: always
      - store_test_results:
          path: ~/test-results
      - store_artifacts:
          path: ~/test-results/junit
      - store_artifacts:
          path: ~/test-results/nps
  test_summercoat:
    executor: buildenv
    steps:
      - checkout
      - attach_workspace:
          at: .
      - run:
          name: SummerCoat Tests
          command: |
            if ! timeout --foreground 1s ./gradlew testSummerCoat --console plain --continue --parallel
            then
              echo "SummerCoat testing failed, ignoring..." 1>&2
            fi
          no_output_timeout: 1m
      - run:
          name: Save test results
          command: |
            mkdir -p ~/test-results/junit/
            find . -type f -regex '.*/summercoat/junit-reports/.*xml' -exec cp {} ~/test-results/junit/ \;
          when: always
      - run:
          name: Save snapshots
          command: |
            mkdir -p ~/test-results/nps/
            find . -type f -regex '.*/summercoat/nps/.*nps' -exec cp {} ~/test-results/nps/ \;
          when: always
      - store_test_results:
          path: ~/test-results
      - store_artifacts:
          path: ~/test-results/junit
      - store_artifacts:
          path: ~/test-results/nps

workflows:
  version: 2
  tests:
    jobs:
      - build_windows
      - build_linux
      - build_macosx
      - construct_testjars:
          requires:
            - build_linux
      - test_springcoat:
          requires:
            - construct_testjars
      - test_summercoat:
          requires:
            - construct_testjars

Changes to .gitignore.

24
25
26
27
28
29
30


*.diff
*.gdiff
*.patch
*.rej
*.bun
*.bundle










>
>
24
25
26
27
28
29
30
31
32
*.diff
*.gdiff
*.patch
*.rej
*.bun
*.bundle

# Crash logs
*.log

Changes to .idea/codeStyles/Project.xml.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
<component name="ProjectCodeStyleConfiguration">
  <code_scheme name="Project" version="173">
    <option name="OTHER_INDENT_OPTIONS">
      <value>
        <option name="USE_TAB_CHARACTER" value="true" />
      </value>
    </option>
    <option name="LINE_SEPARATOR" value="&#10;" />
    <option name="RIGHT_MARGIN" value="79" />

    <DBN-PSQL>
      <case-options enabled="true">
        <option name="KEYWORD_CASE" value="lower" />
        <option name="FUNCTION_CASE" value="lower" />
        <option name="PARAMETER_CASE" value="lower" />
        <option name="DATATYPE_CASE" value="lower" />
        <option name="OBJECT_CASE" value="preserve" />









>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<component name="ProjectCodeStyleConfiguration">
  <code_scheme name="Project" version="173">
    <option name="OTHER_INDENT_OPTIONS">
      <value>
        <option name="USE_TAB_CHARACTER" value="true" />
      </value>
    </option>
    <option name="LINE_SEPARATOR" value="&#10;" />
    <option name="RIGHT_MARGIN" value="79" />
    <option name="SOFT_MARGINS" value="79" />
    <DBN-PSQL>
      <case-options enabled="true">
        <option name="KEYWORD_CASE" value="lower" />
        <option name="FUNCTION_CASE" value="lower" />
        <option name="PARAMETER_CASE" value="lower" />
        <option name="DATATYPE_CASE" value="lower" />
        <option name="OBJECT_CASE" value="preserve" />

Changes to .idea/dictionaries/xer.xml.

1
2
3
4
5

6
7






8
9
10
11
12
13
14
<component name="ProjectDictionaryState">
  <dictionary name="xer">
    <words>
      <w>accel</w>
      <w>backlight</w>

      <w>bootram</w>
      <w>cldc</w>






      <w>endianess</w>
      <w>fprintf</w>
      <w>gawroriski</w>
      <w>ioob</w>
      <w>jarray</w>
      <w>jboolean</w>
      <w>jbyte</w>





>


>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<component name="ProjectDictionaryState">
  <dictionary name="xer">
    <words>
      <w>accel</w>
      <w>backlight</w>
      <w>baos</w>
      <w>bootram</w>
      <w>cldc</w>
      <w>compactified</w>
      <w>cpibm</w>
      <w>csascii</w>
      <w>csibm</w>
      <w>csisolatin</w>
      <w>ebcdic</w>
      <w>endianess</w>
      <w>fprintf</w>
      <w>gawroriski</w>
      <w>ioob</w>
      <w>jarray</w>
      <w>jboolean</w>
      <w>jbyte</w>
25
26
27
28
29
30
31


32
33


34

35
36
37
38
39
40

41
42

43

44
45
46
47
      <w>jniexport</w>
      <w>jobject</w>
      <w>jshort</w>
      <w>jstring</w>
      <w>jthrowable</w>
      <w>jvalue</w>
      <w>jweak</w>


      <w>multiphasicapps</w>
      <w>narg</w>


      <w>phasic</w>

      <w>siii</w>
      <w>siiii</w>
      <w>siiiii</w>
      <w>siiiiii</w>
      <w>siiiiiii</w>
      <w>siiiiiiii</w>

      <w>squirreljme</w>
      <w>stdint</w>

      <w>targetting</w>

      <w>vtable</w>
    </words>
  </dictionary>
</component>







>
>


>
>

>






>


>

>




32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
      <w>jniexport</w>
      <w>jobject</w>
      <w>jshort</w>
      <w>jstring</w>
      <w>jthrowable</w>
      <w>jvalue</w>
      <w>jweak</w>
      <w>ljava</w>
      <w>microedition</w>
      <w>multiphasicapps</w>
      <w>narg</w>
      <w>noassert</w>
      <w>nsee</w>
      <w>phasic</w>
      <w>roro</w>
      <w>siii</w>
      <w>siiii</w>
      <w>siiiii</w>
      <w>siiiiii</w>
      <w>siiiiiii</w>
      <w>siiiiiiii</w>
      <w>springcoat</w>
      <w>squirreljme</w>
      <w>stdint</w>
      <w>summercoat</w>
      <w>targetting</w>
      <w>vmtypes</w>
      <w>vtable</w>
    </words>
  </dictionary>
</component>

Changes to .idea/fileTemplates/H File.h.

1
2
3
4
5
6
#parse("CPP Header.h")

#ifndef __HEADER_H__
#define __HEADER_H__

#endif /*__HEADER_H__ */



|

|
1
2
3
4
5
6
#parse("CPP Header.h")

#ifndef __HEADER_H__
\#define __HEADER_H__

#endif /* __HEADER_H__ */

Changes to .idea/gradle.xml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="GradleMigrationSettings" migrationVersion="1" />
  <component name="GradleSettings">
    <option name="linkedExternalProjectsSettings">
      <GradleProjectSettings>
        <option name="delegatedBuild" value="true" />
        <option name="testRunner" value="GRADLE" />
        <option name="disableWrapperSourceDistributionNotification" value="true" />
        <option name="distributionType" value="DEFAULT_WRAPPED" />
        <option name="externalProjectPath" value="$PROJECT_DIR$" />
        <option name="gradleJvm" value="1.8" />
        <option name="modules">
          <set>
            <option value="$PROJECT_DIR$" />
            <option value="$PROJECT_DIR$/buildSrc" />








<







1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="GradleMigrationSettings" migrationVersion="1" />
  <component name="GradleSettings">
    <option name="linkedExternalProjectsSettings">
      <GradleProjectSettings>
        <option name="delegatedBuild" value="true" />
        <option name="testRunner" value="GRADLE" />

        <option name="distributionType" value="DEFAULT_WRAPPED" />
        <option name="externalProjectPath" value="$PROJECT_DIR$" />
        <option name="gradleJvm" value="1.8" />
        <option name="modules">
          <set>
            <option value="$PROJECT_DIR$" />
            <option value="$PROJECT_DIR$/buildSrc" />

Changes to .idea/inspectionProfiles/Project_Default.xml.

13
14
15
16
17
18
19
20


21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
      <option name="m_limit" value="1" />
    </inspection_tool>
    <inspection_tool class="AnonymousHasLambdaAlternative" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="AnonymousInnerClass" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="ArrayLengthInLoopCondition" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="AssertEqualsBetweenInconvertibleTypes" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="AssignmentUsedAsCondition" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true" />


    <inspection_tool class="BeforeClassOrAfterClassIsPublicStaticVoidNoArg" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="BeforeOrAfterIsPublicVoidNoArg" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="BooleanMethodNameMustStartWithQuestion" enabled="false" level="WEAK WARNING" enabled_by_default="false">
      <option name="ignoreBooleanMethods" value="false" />
      <option name="ignoreInAnnotationInterface" value="true" />
      <option name="onlyWarnOnBaseMethods" value="true" />
      <option name="questionString" value="add,are,can,check,contains,could,endsWith,equals,has,is,matches,must,put,remove,shall,should,startsWith,was,were,will,would" />
    </inspection_tool>

    <inspection_tool class="CheckForOutOfMemoryOnLargeArrayAllocation" enabled="true" level="WARNING" enabled_by_default="true">
      <option name="m_limit" value="64" />
    </inspection_tool>
    <inspection_tool class="ClassComplexity" enabled="true" level="WARNING" enabled_by_default="true">
      <option name="m_limit" value="80" />
    </inspection_tool>
    <inspection_tool class="ClassCoupling" enabled="true" level="WARNING" enabled_by_default="true">







|
>
>








>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
      <option name="m_limit" value="1" />
    </inspection_tool>
    <inspection_tool class="AnonymousHasLambdaAlternative" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="AnonymousInnerClass" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="ArrayLengthInLoopCondition" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="AssertEqualsBetweenInconvertibleTypes" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="AssignmentUsedAsCondition" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
      <option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,cc.squirreljme.vm.springcoat.NativeHLEHandler,__fdOutput" />
    </inspection_tool>
    <inspection_tool class="BeforeClassOrAfterClassIsPublicStaticVoidNoArg" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="BeforeOrAfterIsPublicVoidNoArg" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="BooleanMethodNameMustStartWithQuestion" enabled="false" level="WEAK WARNING" enabled_by_default="false">
      <option name="ignoreBooleanMethods" value="false" />
      <option name="ignoreInAnnotationInterface" value="true" />
      <option name="onlyWarnOnBaseMethods" value="true" />
      <option name="questionString" value="add,are,can,check,contains,could,endsWith,equals,has,is,matches,must,put,remove,shall,should,startsWith,was,were,will,would" />
    </inspection_tool>
    <inspection_tool class="CharsetObjectCanBeUsed" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="CheckForOutOfMemoryOnLargeArrayAllocation" enabled="true" level="WARNING" enabled_by_default="true">
      <option name="m_limit" value="64" />
    </inspection_tool>
    <inspection_tool class="ClassComplexity" enabled="true" level="WARNING" enabled_by_default="true">
      <option name="m_limit" value="80" />
    </inspection_tool>
    <inspection_tool class="ClassCoupling" enabled="true" level="WARNING" enabled_by_default="true">
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
      <option name="commentsAreContent" value="true" />
    </inspection_tool>
    <inspection_tool class="EnhancedSwitchBackwardMigration" enabled="false" level="INFORMATION" enabled_by_default="false" />
    <inspection_tool class="EnhancedSwitchMigration" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="ExceptionNameDoesntEndWithException" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
    <inspection_tool class="ExplicitArgumentCanBeLambda" enabled="false" level="INFORMATION" enabled_by_default="false" />
    <inspection_tool class="ExtendsUtilityClass" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="FeatureEnvy" enabled="true" level="WARNING" enabled_by_default="true">
      <option name="ignoreTestCases" value="false" />
    </inspection_tool>
    <inspection_tool class="FieldNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true">
      <extension name="ConstantNamingConvention" enabled="true">
        <option name="m_regex" value="_?[a-zA-Z][A-Z_\d]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="32" />
      </extension>
      <extension name="ConstantWithMutableFieldTypeNamingConvention" enabled="true">
        <option name="m_regex" value="_?[a-z][a-zA-z_]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="32" />
      </extension>
      <extension name="EnumeratedConstantNamingConvention" enabled="true">
        <option name="m_regex" value="[A-Z][A-Z_\d]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="40" />
      </extension>
      <extension name="InstanceVariableNamingConvention" enabled="true">
        <option name="m_regex" value="_?[a-z][a-zA-z_]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="32" />
      </extension>
      <extension name="StaticVariableNamingConvention" enabled="true">
        <option name="m_regex" value="_?[A-Z][A-Z_\d]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="32" />
      </extension>
    </inspection_tool>
    <inspection_tool class="Finalize" enabled="true" level="ERROR" enabled_by_default="true">
      <option name="ignoreTrivialFinalizers" value="false" />
    </inspection_tool>







<
<
<


|




|














|







74
75
76
77
78
79
80



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
      <option name="commentsAreContent" value="true" />
    </inspection_tool>
    <inspection_tool class="EnhancedSwitchBackwardMigration" enabled="false" level="INFORMATION" enabled_by_default="false" />
    <inspection_tool class="EnhancedSwitchMigration" enabled="false" level="WARNING" enabled_by_default="false" />
    <inspection_tool class="ExceptionNameDoesntEndWithException" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
    <inspection_tool class="ExplicitArgumentCanBeLambda" enabled="false" level="INFORMATION" enabled_by_default="false" />
    <inspection_tool class="ExtendsUtilityClass" enabled="true" level="WARNING" enabled_by_default="true" />



    <inspection_tool class="FieldNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true">
      <extension name="ConstantNamingConvention" enabled="true">
        <option name="m_regex" value="_?[a-zA-Z][A-Za-z_\d]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="32" />
      </extension>
      <extension name="ConstantWithMutableFieldTypeNamingConvention" enabled="true">
        <option name="m_regex" value="_?[a-zA-Z][A-Za-z_\d]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="32" />
      </extension>
      <extension name="EnumeratedConstantNamingConvention" enabled="true">
        <option name="m_regex" value="[A-Z][A-Z_\d]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="40" />
      </extension>
      <extension name="InstanceVariableNamingConvention" enabled="true">
        <option name="m_regex" value="_?[a-z][a-zA-z_]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="32" />
      </extension>
      <extension name="StaticVariableNamingConvention" enabled="true">
        <option name="m_regex" value="_?[a-zA-Z][A-Za-z_\d]*" />
        <option name="m_minLength" value="2" />
        <option name="m_maxLength" value="32" />
      </extension>
    </inspection_tool>
    <inspection_tool class="Finalize" enabled="true" level="ERROR" enabled_by_default="true">
      <option name="ignoreTrivialFinalizers" value="false" />
    </inspection_tool>
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197
      <option name="m_ignoreForLoopParameters" value="true" />
      <option name="m_ignoreCatchParameters" value="true" />
      <option name="m_regex" value="(__)?[a-z][A-Za-z\d]*" />
      <option name="m_minLength" value="1" />
      <option name="m_maxLength" value="20" />
    </inspection_tool>
    <inspection_tool class="LongLine" enabled="true" level="TYPO" enabled_by_default="true" />
    <inspection_tool class="MagicNumber" enabled="true" level="WEAK WARNING" enabled_by_default="true" />

    <inspection_tool class="MethodCallInLoopCondition" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="MethodNameSameAsClassName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
    <inspection_tool class="MethodNameSameAsParentName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
    <inspection_tool class="MethodRefCanBeReplacedWithLambda" enabled="false" level="INFORMATION" enabled_by_default="false" />
    <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
      <option name="ignoreObjectMethods" value="false" />
      <option name="ignoreAnonymousClassMethods" value="false" />
    </inspection_tool>







|
>
|







182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
      <option name="m_ignoreForLoopParameters" value="true" />
      <option name="m_ignoreCatchParameters" value="true" />
      <option name="m_regex" value="(__)?[a-z][A-Za-z\d]*" />
      <option name="m_minLength" value="1" />
      <option name="m_maxLength" value="20" />
    </inspection_tool>
    <inspection_tool class="LongLine" enabled="true" level="TYPO" enabled_by_default="true" />
    <inspection_tool class="MagicNumber" enabled="true" level="WEAK WARNING" enabled_by_default="true">
      <scope name="Tests" level="WEAK WARNING" enabled="false" />
    </inspection_tool>
    <inspection_tool class="MethodNameSameAsClassName" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
    <inspection_tool class="MethodNameSameAsParentName" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
    <inspection_tool class="MethodRefCanBeReplacedWithLambda" enabled="false" level="INFORMATION" enabled_by_default="false" />
    <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
      <option name="ignoreObjectMethods" value="false" />
      <option name="ignoreAnonymousClassMethods" value="false" />
    </inspection_tool>
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
      <option name="ignoreInconvertibleTypes" value="true" />
    </inspection_tool>
    <inspection_tool class="OverloadedVarargsMethod" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
    <inspection_tool class="OverlyLargePrimitiveArrayInitializer" enabled="true" level="WARNING" enabled_by_default="true">
      <option name="m_limit" value="64" />
    </inspection_tool>
    <inspection_tool class="PackageInfoWithoutPackage" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="PackageNamingConvention" enabled="true" level="WEAK WARNING" enabled_by_default="true">
      <option name="m_regex" value="[a-z]*" />
      <option name="m_minLength" value="2" />
      <option name="m_maxLength" value="16" />
    </inspection_tool>
    <inspection_tool class="ParameterNameDiffersFromOverriddenParameter" enabled="false" level="WEAK WARNING" enabled_by_default="false">
      <option name="m_ignoreSingleCharacterNames" value="false" />
      <option name="m_ignoreOverridesOfLibraryMethods" value="false" />







|







282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
      <option name="ignoreInconvertibleTypes" value="true" />
    </inspection_tool>
    <inspection_tool class="OverloadedVarargsMethod" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
    <inspection_tool class="OverlyLargePrimitiveArrayInitializer" enabled="true" level="WARNING" enabled_by_default="true">
      <option name="m_limit" value="64" />
    </inspection_tool>
    <inspection_tool class="PackageInfoWithoutPackage" enabled="true" level="WARNING" enabled_by_default="true" />
    <inspection_tool class="PackageNamingConvention" enabled="false" level="WEAK WARNING" enabled_by_default="false">
      <option name="m_regex" value="[a-z]*" />
      <option name="m_minLength" value="2" />
      <option name="m_maxLength" value="16" />
    </inspection_tool>
    <inspection_tool class="ParameterNameDiffersFromOverriddenParameter" enabled="false" level="WEAK WARNING" enabled_by_default="false">
      <option name="m_ignoreSingleCharacterNames" value="false" />
      <option name="m_ignoreOverridesOfLibraryMethods" value="false" />

Changes to .idea/misc.xml.

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ExternalStorageConfigurationManager" enabled="true" />
  <component name="JavaScriptSettings">
    <option name="languageLevel" value="ES6" />
  </component>
  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project>






|

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ExternalStorageConfigurationManager" enabled="true" />
  <component name="JavaScriptSettings">
    <option name="languageLevel" value="ES6" />
  </component>
  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project>

Changes to buildSrc/src/main/java/cc/squirreljme/plugin/ErrorListManager.java.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * This is used to get the error lists from a project.
 *
 * @since 2020/02/22
 */
public final class ErrorListManager
{
	
	/** The project to manage the list for. */
	protected final Project project;
	
	/** The listed errors. */
	private final Map<Integer, SourceError> _errors =
		new TreeMap<>();
	







<







18
19
20
21
22
23
24

25
26
27
28
29
30
31
/**
 * This is used to get the error lists from a project.
 *
 * @since 2020/02/22
 */
public final class ErrorListManager
{

	/** The project to manage the list for. */
	protected final Project project;
	
	/** The listed errors. */
	private final Map<Integer, SourceError> _errors =
		new TreeMap<>();
	

Changes to buildSrc/src/main/java/cc/squirreljme/plugin/SourceError.java.

88
89
90
91
92
93
94



95
96
97
98
99
100
101
		// Store body in
		this.body = body.toString();
		
		// Parameter list?
		List<String> parameters = new ArrayList<String>();
		if ("(".equals(queue.peekFirst()))
		{



			// Process queue
			StringBuilder buffer = new StringBuilder();
			while (!queue.isEmpty())
			{
				String item = queue.peekFirst();
				
				// End parameter or next?







>
>
>







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
		// Store body in
		this.body = body.toString();
		
		// Parameter list?
		List<String> parameters = new ArrayList<String>();
		if ("(".equals(queue.peekFirst()))
		{
			// Remove the starting parenthesis so it is not added
			queue.removeFirst();
			
			// Process queue
			StringBuilder buffer = new StringBuilder();
			while (!queue.isEmpty())
			{
				String item = queue.peekFirst();
				
				// End parameter or next?
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
	 * @return The translated string to index.
	 * @since 2020/02/22
	 */
	public static String indexToString(int __index)
	{
		StringBuilder sb = new StringBuilder();
		
		sb.append(Character.toUpperCase(Character.forDigit(
			__index / Character.MAX_RADIX, Character.MAX_RADIX)));
		sb.append(Character.toUpperCase(Character.forDigit(
			__index % Character.MAX_RADIX, Character.MAX_RADIX)));
		
		return sb.toString();
	}
	
	/**
	 * Returns the index for the given string.







|

|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
	 * @return The translated string to index.
	 * @since 2020/02/22
	 */
	public static String indexToString(int __index)
	{
		StringBuilder sb = new StringBuilder();
		
		sb.append(Character.toLowerCase(Character.forDigit(
			__index / Character.MAX_RADIX, Character.MAX_RADIX)));
		sb.append(Character.toLowerCase(Character.forDigit(
			__index % Character.MAX_RADIX, Character.MAX_RADIX)));
		
		return sb.toString();
	}
	
	/**
	 * Returns the index for the given string.

Changes to buildSrc/src/main/java/cc/squirreljme/plugin/SquirrelJMEPlugin.java.

37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
	 * {@inheritDoc}
	 * @since 2020/02/15
	 */
	@Override
	public void apply(Project __project)
	{
		// Add configuration for SquirrelJME

		__project.getExtensions().<SquirrelJMEPluginConfiguration>create(
			"squirreljme", SquirrelJMEPluginConfiguration.class,
			this, __project);
		
		// Build task
		__project.getTasks().getByName("build");
		
		// Class generation







>
|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
	 * {@inheritDoc}
	 * @since 2020/02/15
	 */
	@Override
	public void apply(Project __project)
	{
		// Add configuration for SquirrelJME
		SquirrelJMEPluginConfiguration config = __project
			.getExtensions().<SquirrelJMEPluginConfiguration>create(
			"squirreljme", SquirrelJMEPluginConfiguration.class,
			this, __project);
		
		// Build task
		__project.getTasks().getByName("build");
		
		// Class generation

Added buildSrc/src/main/java/cc/squirreljme/plugin/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This contains the base plugin code to support SquirrelJME.
 *
 * @since 2020/06/13
 */

package cc.squirreljme.plugin;

Changes to buildSrc/src/main/java/cc/squirreljme/plugin/tasks/AbstractEmulatedTask.java.

12
13
14
15
16
17
18

19
20
21
22
23

24
25
26
27
28
29
30
import cc.squirreljme.plugin.SquirrelJMEPluginConfiguration;
import cc.squirreljme.plugin.swm.JavaMEMidlet;
import cc.squirreljme.plugin.swm.JavaMEMidletType;
import cc.squirreljme.plugin.tasks.test.EmulatedTestUtilities;
import java.io.File;
import java.nio.file.Path;
import java.util.Collection;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Set;

import java.util.concurrent.Callable;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;







>





>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import cc.squirreljme.plugin.SquirrelJMEPluginConfiguration;
import cc.squirreljme.plugin.swm.JavaMEMidlet;
import cc.squirreljme.plugin.swm.JavaMEMidletType;
import cc.squirreljme.plugin.tasks.test.EmulatedTestUtilities;
import java.io.File;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
160
161
162
163
164
165
166
167
168
169
170



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
	
	/**
	 * Returns the run class path.
	 *
	 * @return The run class path.
	 * @since 2020/02/29
	 */
	@Deprecated
	Iterable<Path> __runClassPath()
	{
		Collection<Path> result = new LinkedHashSet<>();



		
		this.__recursiveDependencies(result, this.getProject());
		
		return result;
	}
	
	/**
	 * Recursively scans and obtains dependencies.
	 *
	 * @param __out The output collection.
	 * @param __at The current project currently at.
	 * @since 2020/02/29
	 */
	@Deprecated
	final void __recursiveDependencies(Collection<Path> __out, Project __at)
	{
		this.__recursiveDependencies(__out, __at, new HashSet<>());
	}
	
	/**
	 * Recursively scans and obtains dependencies.
	 *







<



>
>
>














|







162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	
	/**
	 * Returns the run class path.
	 *
	 * @return The run class path.
	 * @since 2020/02/29
	 */

	Iterable<Path> __runClassPath()
	{
		Collection<Path> result = new LinkedHashSet<>();
		
		Deque<Project> projects = new LinkedList<>();
		Set<Project> didProjects = new TreeSet<>();
		
		this.__recursiveDependencies(result, this.getProject());
		
		return result;
	}
	
	/**
	 * Recursively scans and obtains dependencies.
	 *
	 * @param __out The output collection.
	 * @param __at The current project currently at.
	 * @since 2020/02/29
	 */
	@Deprecated
	private void __recursiveDependencies(Collection<Path> __out, Project __at)
	{
		this.__recursiveDependencies(__out, __at, new HashSet<>());
	}
	
	/**
	 * Recursively scans and obtains dependencies.
	 *

Changes to buildSrc/src/main/java/cc/squirreljme/plugin/tasks/TestInVMTask.java.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44

package cc.squirreljme.plugin.tasks;

import cc.squirreljme.plugin.tasks.test.EmulatedTestExecutionSpec;
import cc.squirreljme.plugin.tasks.test.EmulatedTestExecutor;
import java.io.File;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.Callable;
import javax.inject.Inject;
import org.gradle.api.internal.provider.AbstractMinimalProvider;
import org.gradle.api.tasks.testing.AbstractTestTask;
import org.gradle.api.tasks.testing.Test;
import org.gradle.jvm.tasks.Jar;

/**
 * Tests in virtual machine, this uses an abstract test tasks which implement
 * all of the needed classes for test.
 *
 * Required properties:
 *  - binaryResultsDirectory
 *  - reports.enabledReports.html.outputLocation
 *  - reports.enabledReports.junitXml.outputLocation
 *
 * Gradle Test task {@link Test}.
 *
 * @since 2020/03/06
 */

public class TestInVMTask
	extends AbstractTestTask
{
	/** The binary results directory. */
	private static final String _BINARY_RESULTS_DIRECTORY =
		"binaryResultsDirectory";
	







<



|

















>







9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

package cc.squirreljme.plugin.tasks;

import cc.squirreljme.plugin.tasks.test.EmulatedTestExecutionSpec;
import cc.squirreljme.plugin.tasks.test.EmulatedTestExecutor;
import java.io.File;
import java.nio.file.Path;

import java.util.Objects;
import java.util.concurrent.Callable;
import javax.inject.Inject;
import org.gradle.api.internal.provider.DefaultProvider;
import org.gradle.api.tasks.testing.AbstractTestTask;
import org.gradle.api.tasks.testing.Test;
import org.gradle.jvm.tasks.Jar;

/**
 * Tests in virtual machine, this uses an abstract test tasks which implement
 * all of the needed classes for test.
 *
 * Required properties:
 *  - binaryResultsDirectory
 *  - reports.enabledReports.html.outputLocation
 *  - reports.enabledReports.junitXml.outputLocation
 *
 * Gradle Test task {@link Test}.
 *
 * @since 2020/03/06
 */
@Deprecated
public class TestInVMTask
	extends AbstractTestTask
{
	/** The binary results directory. */
	private static final String _BINARY_RESULTS_DIRECTORY =
		"binaryResultsDirectory";
	
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	 * Initializes the task.
	 *
	 * @param __jar The JAR sources.
	 * @param __vm The virtual machine to run.
	 * @since 2020/03/06
	 */
	@Inject

	public TestInVMTask(Jar __jar, String __vm)
	{
		// We need these for tasks and such
		this.emulator = __vm;
		this.jar = __jar;
		
		// Set description
		this.setGroup("squirreljme");
		this.setDescription("Tests inside of " + __vm + ".");
		
		// Depend on the JAR task
		this.dependsOn(__jar);
		
		// The input file for our tests is the JAR we want to look at!
		this.getInputs().file(__jar.getArchiveFile());
		
		// Where binary results are going to be stored, these both have to
		// be set otherwise the test build will fail
		this.setProperty(TestInVMTask._BINARY_RESULTS_DIRECTORY,
			this.getProject().getObjects().directoryProperty()
			.dir(new __BinaryResultsDirectoryProvider__()));
		this.setBinResultsDir(
			new File(new __BinaryResultsDirectoryProvider__().get()));
		
		// Generate HTML reports because they are useful
		this.getReports().getHtml().setDestination(
			this.__tempRoot().resolve("html-reports").toFile());
		
		// Generate JUnit XML, these will be uploaded to CICD
		this.getReports().getJunitXml().setDestination(







>




















|
|
<







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
	 * Initializes the task.
	 *
	 * @param __jar The JAR sources.
	 * @param __vm The virtual machine to run.
	 * @since 2020/03/06
	 */
	@Inject
	@Deprecated
	public TestInVMTask(Jar __jar, String __vm)
	{
		// We need these for tasks and such
		this.emulator = __vm;
		this.jar = __jar;
		
		// Set description
		this.setGroup("squirreljme");
		this.setDescription("Tests inside of " + __vm + ".");
		
		// Depend on the JAR task
		this.dependsOn(__jar);
		
		// The input file for our tests is the JAR we want to look at!
		this.getInputs().file(__jar.getArchiveFile());
		
		// Where binary results are going to be stored, these both have to
		// be set otherwise the test build will fail
		this.setProperty(TestInVMTask._BINARY_RESULTS_DIRECTORY,
			this.getProject().getObjects().directoryProperty()
			.dir(new DefaultProvider<>(this::__binResultPath)));
		this.setBinResultsDir(new File(this.__binResultPath().toString()));

		
		// Generate HTML reports because they are useful
		this.getReports().getHtml().setDestination(
			this.__tempRoot().resolve("html-reports").toFile());
		
		// Generate JUnit XML, these will be uploaded to CICD
		this.getReports().getJunitXml().setDestination(
103
104
105
106
107
108
109







110
111
112
113
114
115
116

117
118
119
120
121
122
123
124
125
126

127
128
129
130













131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
		// have when running the VMs especially when not fully stable
		this.testLogging(__settings ->
			{
				__settings.setShowCauses(true);
				__settings.setShowStandardStreams(true);
				__settings.setShowStackTraces(true);
			});







	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/03/06
	 */
	@Override

	protected EmulatedTestExecutor createTestExecuter()
	{
		return new EmulatedTestExecutor(this);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/03/06
	 */
	@Override

	protected EmulatedTestExecutionSpec createTestExecutionSpec()
	{
		return new EmulatedTestExecutionSpec(this.emulator, this.jar);
	}













	
	/**
	 * Finds the emulator JAR task.
	 *
	 * @return The emulator JAR task.
	 * @since 2020/02/29
	 */

	Jar __findEmulatorBaseJarTask()
	{
		return (Jar)Objects.requireNonNull(this.getProject().getRootProject().
			findProject(":emulators:emulator-base"),
			"No emulator base?").getTasks().getByName("jar");
	}
	
	/**
	 * Locates the emulator package to base on.
	 *
	 * @return The emulator base.
	 * @since 2020/02/29
	 */

	Jar __findEmulatorJarTask()
	{
		return (Jar)Objects.requireNonNull(this.getProject().getRootProject().
			findProject(":emulators:" + this.emulator + "-vm"),
			"No emulator?").getTasks().getByName("jar");
	}
	
	/**
	 * Returns the temporary file root base.
	 *
	 * @return The temporary root.
	 * @since 2020/03/06
	 */

	public final Path __tempRoot()
	{
		return this.getProject().getBuildDir().toPath().resolve("vm-test").
			resolve(this.emulator);
	}
	
	/**
	 * Provider for directory.
	 *
	 * @since 2020/03/06
	 */
	class __BinaryResultsDirectoryProvider__
		extends AbstractMinimalProvider<String>
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/03/06
		 */
		@Override
		public String get()
			throws IllegalStateException
		{
			String rv = this.getOrNull();
			if (rv == null)
				throw new IllegalStateException("No directory!");
			return rv;
		}
		
		/**
		 * {@inheritDoc}
		 * @since 2020/03/06
		 */
		@Override
		public String getOrNull()
		{
			return TestInVMTask.this.__tempRoot().resolve("bin-results")
				.toAbsolutePath().toString();
		}
		
		/**
		 * {@inheritDoc}
		 * @since 2020/03/06
		 */
		@Override
		public Class<String> getType()
		{
			return String.class;
		}
	}
}







>
>
>
>
>
>
>







>










>




>
>
>
>
>
>
>
>
>
>
>
>
>







>













>













>





|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194












































		// have when running the VMs especially when not fully stable
		this.testLogging(__settings ->
			{
				__settings.setShowCauses(true);
				__settings.setShowStandardStreams(true);
				__settings.setShowStackTraces(true);
			});
		
		// Make sure that both report types are enabled!
		this.reports(__reports ->
			{
				__reports.getJunitXml().setEnabled(true);
				__reports.getHtml().setEnabled(true);
			});
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/03/06
	 */
	@Override
	@Deprecated
	protected EmulatedTestExecutor createTestExecuter()
	{
		return new EmulatedTestExecutor(this);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/03/06
	 */
	@Override
	@Deprecated
	protected EmulatedTestExecutionSpec createTestExecutionSpec()
	{
		return new EmulatedTestExecutionSpec(this.emulator, this.jar);
	}
	
	/**
	 * Returns the binary results path.
	 * 
	 * @return The binary results path.
	 * @since 2020/06/22
	 */
	@Deprecated
	CharSequence __binResultPath()
	{
		return this.__tempRoot().resolve("bin-results")
			.toAbsolutePath().toString();
	}
	
	/**
	 * Finds the emulator JAR task.
	 *
	 * @return The emulator JAR task.
	 * @since 2020/02/29
	 */
	@Deprecated
	Jar __findEmulatorBaseJarTask()
	{
		return (Jar)Objects.requireNonNull(this.getProject().getRootProject().
			findProject(":emulators:emulator-base"),
			"No emulator base?").getTasks().getByName("jar");
	}
	
	/**
	 * Locates the emulator package to base on.
	 *
	 * @return The emulator base.
	 * @since 2020/02/29
	 */
	@Deprecated
	Jar __findEmulatorJarTask()
	{
		return (Jar)Objects.requireNonNull(this.getProject().getRootProject().
			findProject(":emulators:" + this.emulator + "-vm"),
			"No emulator?").getTasks().getByName("jar");
	}
	
	/**
	 * Returns the temporary file root base.
	 *
	 * @return The temporary root.
	 * @since 2020/03/06
	 */
	@Deprecated
	public final Path __tempRoot()
	{
		return this.getProject().getBuildDir().toPath().resolve("vm-test").
			resolve(this.emulator);
	}
}












































Added buildSrc/src/main/java/cc/squirreljme/plugin/tasks/test/ConsoleLine.java.



















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.plugin.tasks.test;

import org.gradle.api.internal.tasks.testing.TestResultProcessor;
import org.gradle.api.tasks.testing.TestOutputEvent;

/**
 * This indicates a line that happened on the consoles.
 *
 * @since 2020/06/22
 */
public final class ConsoleLine
{
	/** Is this to standard error?. */
	public final boolean stdErr;
	
	/** When did this happen? */
	public final long timeMillis;
	
	/** The text that was printed to the console. */
	public final String text;
	
	/**
	 * Initializes the console line.
	 * 
	 * @param __stdErr Is this standard error?
	 * @param __timeMillis When this message appeared.
	 * @param __text The text for the message.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/22
	 */
	public ConsoleLine(boolean __stdErr, long __timeMillis, String __text)
		throws NullPointerException
	{
		if (__text == null)
			throw new NullPointerException("NARG");
		
		this.stdErr = __stdErr;
		this.timeMillis = __timeMillis;
		this.text = __text;
	}
	
	/**
	 * Reports the line.
	 * 
	 * @param __results The test results output.
	 * @param __method The method to report to.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/22
	 */
	public void report(TestResultProcessor __results,
		EmulatedTestMethodDescriptor __method)
		throws NullPointerException
	{
		// Where is this going?
		TestOutputEvent.Destination destination = (this.stdErr ?
				TestOutputEvent.Destination.StdErr :
				TestOutputEvent.Destination.StdOut);
		
		// Print output
		__results.output(__method.getId(),
			EmulatedTestUtilities.output(destination,
				this.text + System.getProperty("line.separator")));
	}
}

Changes to buildSrc/src/main/java/cc/squirreljme/plugin/tasks/test/EmulatedTestExecutor.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51




52
53
54
55
56
57
58
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.plugin.tasks.test;

import cc.squirreljme.plugin.tasks.TestInVMTask;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.channels.ClosedByInterruptException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Objects;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.gradle.api.Project;
import org.gradle.api.internal.tasks.testing.TestExecuter;
import org.gradle.api.internal.tasks.testing.TestResultProcessor;
import org.gradle.api.tasks.testing.TestOutputEvent;
import org.gradle.process.ExecResult;

/**
 * This is the executer for tests.
 *
 * @since 2020/03/06
 */
public final class EmulatedTestExecutor
	implements TestExecuter<EmulatedTestExecutionSpec>
{
	/** The number of permitted interrupts before failure. */
	private static final int _MAX_INTERRUPTS =
		8;
	
	/** The service resource file. */
	public static final String SERVICE_RESOURCE =
		"META-INF/services/net.multiphasicapps.tac.TestInterface";
	
	/** The test task. */
	private final TestInVMTask _testInVMTask;
	




	/** Should this test be stopped? */
	private volatile boolean _stopRunning =
		false;
	
	/**
	 * Initializes the task executor.
	 *












<
<
<

|
|
|
|
|
|
|
|
|
|
>



<



|






<
<
<
<







>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37




38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.plugin.tasks.test;

import cc.squirreljme.plugin.tasks.TestInVMTask;



import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
import org.gradle.api.Project;
import org.gradle.api.internal.tasks.testing.TestExecuter;
import org.gradle.api.internal.tasks.testing.TestResultProcessor;

import org.gradle.process.ExecResult;

/**
 * This is the executor for tests.
 *
 * @since 2020/03/06
 */
public final class EmulatedTestExecutor
	implements TestExecuter<EmulatedTestExecutionSpec>
{




	/** The service resource file. */
	public static final String SERVICE_RESOURCE =
		"META-INF/services/net.multiphasicapps.tac.TestInterface";
	
	/** The test task. */
	private final TestInVMTask _testInVMTask;
	
	/** Emulator classpath. */
	private final Map<String, Iterable<Object>> _emuClassPathCache =
		new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
	
	/** Should this test be stopped? */
	private volatile boolean _stopRunning =
		false;
	
	/**
	 * Initializes the task executor.
	 *
72
73
74
75
76
77
78





79
80
81
82
83
84
85
86
87
88
89











90
91

92
93
94
95
96


97
98

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116











































117
118
119
120
121
122
123
124

125
126
127
128




129
130
131
132
133


134
135
136




137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188























189
190
















191
192
193
194
195
196
197

198
199

200
201
202
203
204

205
206

207
208
209


210
211
212




213
214


215

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
	@Override
	public void execute(EmulatedTestExecutionSpec __spec,
		TestResultProcessor __results)
	{
		// We need the project to access details
		Project project = this._testInVMTask.getProject();
		





		// Run for this suite/project
		EmulatedTestSuiteDescriptor suite =
			new EmulatedTestSuiteDescriptor(project);
		
		// Indicate that the suite has started execution
		__results.started(suite, EmulatedTestUtilities.startNow());
		
		// Perform testing logic
		boolean allPassed = true;
		try
		{











			// Execute test classes (find them and run them)
			allPassed = this.executeClasses(__spec, __results, suite);

			
			// Did all tests pass?
			__results.completed(suite.getId(),
				EmulatedTestUtilities.passOrFailNow(allPassed));
		}


		catch (Throwable t)
		{

			// Report the thrown exception
			__results.failure(suite.getId(), t);
			__results.completed(suite.getId(),
				EmulatedTestUtilities.failNow());
		}
		
		// Did not pass, so cause the task to fail
		if (!allPassed)
		{
			// Throw a blank failure exception
			RuntimeException toss = new RuntimeException("Failed tests.");
			toss.setStackTrace(new StackTraceElement[0]);
			
			throw toss;
		}
	}
	
	/**











































	 * Goes through and executes the single test class.
	 *
	 * @param __spec The specification.
	 * @param __results The output results.
	 * @param __method The method to run.
	 * @return The exit value of the test.
	 * @since 2020/03/06
	 */

	private int executeClass(EmulatedTestExecutionSpec __spec,
		TestResultProcessor __results, EmulatedTestMethodDescriptor __method)
	{
		Project project = this._testInVMTask.getProject();




		
		// For some reason test reports do not run if there is no output for
		// them, so this for the most part forces console output to happen
		// which makes tests happen
		__results.output(__method.getId(),


			EmulatedTestUtilities.outputErr(String.format(
			"Running test %s...", __method.getDisplayName())));
		




		// Execute the test Java program
		System.err.printf("Executing Java Program...%n");
		ExecResult result = project.javaexec(__javaExecSpec ->
			{
				Collection<String> args = new LinkedList<>();
				
				// The class we are executing in
				String withinClass = Objects.requireNonNull(
					__method.getParent(),
					"No test class?").getClassName();
				
				// Add emulator
				args.add("-Xemulator:" + __spec.emulator);
				
				// Add snapshot path
				args.add("-Xsnapshot:" + EmulatedTestExecutor.this
					._testInVMTask.__tempRoot().resolve("nps")
					.resolve(withinClass + ".nps").toAbsolutePath());
				
				// Classpath of the target JAR
				args.add("-classpath");
				args.add(EmulatedTestUtilities.classpathString(project,
					true));
				
				// Only run a single test
				args.add("net.multiphasicapps.tac.MainSingleRunner");
				
				// Target this single test
				args.add(withinClass);
				
				// Configure the VM for execution
				__javaExecSpec.classpath(EmulatedTestUtilities
					.emulatorClassPath(project, __spec.emulator));
				__javaExecSpec.setMain("cc.squirreljme.emulator.vm.VMFactory");
				__javaExecSpec.setArgs(args);
				
				// Pipe outputs to the specified areas so the console can be
				// read properly!
				__javaExecSpec.setStandardOutput(new PipeOutputStream(
					__method.getId(), __results,
					TestOutputEvent.Destination.StdOut));
				__javaExecSpec.setErrorOutput(new PipeOutputStream(
					__method.getId(), __results,
					TestOutputEvent.Destination.StdErr));
				
				// Do not throw an exception on a non-zero exit value since
				// it is important to us
				__javaExecSpec.setIgnoreExitValue(true);
			});
		
		// Return the exit value here
		System.err.printf("Exited with value: %d%n", result.getExitValue());























		return result.getExitValue();
	}
















	
	/**
	 * Goes through and executes the test classes.
	 *
	 * @param __spec The specification.
	 * @param __results The output results.
	 * @param __suite The suite to run.

	 * @return Did all tests pass?
	 * @throws IOException On read errors.

	 * @since 2020/03/06
	 */
	@SuppressWarnings("FeatureEnvy")
	private boolean executeClasses(EmulatedTestExecutionSpec __spec,
		TestResultProcessor __results, EmulatedTestSuiteDescriptor __suite)

		throws IOException
	{

		// Extract all of the test classes to be executed
		Collection<String> testClasses = new TreeSet<>();
		for (int iCount = 0;;)


			try (ZipInputStream zip = new ZipInputStream(Files.newInputStream(
				__spec.jar.getArchiveFile().get().getAsFile().toPath(),
				StandardOpenOption.READ)))




			{
				EmulatedTestExecutor.__findTestClasses(zip, testClasses);


				

				break;
			}
			catch (ClosedByInterruptException e)
			{
				// Prevent dead-locking if interrupting just keeps happening
				if (++iCount >= EmulatedTestExecutor._MAX_INTERRUPTS)
					throw new RuntimeException(
						"Could not read JAR due to too many interrupts.", e);
				
				System.err.printf("Interrupt during JAR read, retrying...%n");
				
				// Clear interrupt flag
				Thread.interrupted();
			}
		
		// Used to flag if every test passed
		boolean allPassed = true;
		
		// Now go through the tests we discovered and execute them
		for (String testClass : testClasses)
		{
			// Stop executing? Note that if this is stopped in the middle of
			// a test we cannot make the tests pass
			if (this._stopRunning)
				return false;
			
			// In SquirrelJME all tests only have a single run method, so the
			// run is the actual class of execution
			EmulatedTestClassDescriptor classy =
				new EmulatedTestClassDescriptor(__suite, testClass);
			EmulatedTestMethodDescriptor method =
				new EmulatedTestMethodDescriptor(classy);
			
			// Start execution
			__results.started(classy,
				EmulatedTestUtilities.startNow(__suite));
			__results.started(method,
				EmulatedTestUtilities.startNow(classy));
			
			// Execute each class alone
			try
			{
				// Execute individual test
				int result = this.executeClass(__spec, __results, method);
				
				// Test did not pass
				if (result != ExitValueConstants.SUCCESS &&
					result != ExitValueConstants.SKIPPED)
				{
					// Clear out the stack trace because they are really
					// annoying
					Throwable empty = new Throwable("Test failed");
					empty.setStackTrace(new StackTraceElement[0]);
					
					// Use this thrown exception
					__results.failure(method.getId(), empty);
				}
				
				// End execution
				__results.completed(method.getId(),
					EmulatedTestUtilities.passSkipOrFailNow(result));
				__results.completed(classy.getId(),
					EmulatedTestUtilities.passSkipOrFailNow(result));
			}
			catch (Throwable t)
			{
				// Report the thrown exception
				__results.failure(method.getId(), t);
				__results.completed(method.getId(),
					EmulatedTestUtilities.failNow());
				
				// Fail the class as well
				__results.completed(classy.getId(),
					EmulatedTestUtilities.failNow());
			}
		}
		
		// Return how all the tests ran
		return allPassed;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/03/06
	 */
	@Override
	public void stopNow()
	{
		// Stop running and prevent the next test from stopping
		this._stopRunning = true;
	}
	
	/**
	 * Attempts to find the test classes.
	 *
	 * @param __zip The ZIP to read.
	 * @param __testClasses The target classes.
	 * @throws IOException On read failures.
	 * @since 2020/05/25
	 */
	private static void __findTestClasses(ZipInputStream __zip,
		Collection<String> __testClasses)
		throws IOException
	{
		for (;;)
		{
			// Stop at the end of the ZIP
			ZipEntry entry = __zip.getNextEntry();
			if (entry == null)
				break;
			
			// Only consider the services file
			if (!EmulatedTestExecutor.SERVICE_RESOURCE
				.equals(entry.getName()))
				continue;
			
			// We cannot close a stream, so we need to copy the data over
			// first
			ByteArrayOutputStream baos = new ByteArrayOutputStream(
				(int)Math.max(0, entry.getSize()));
			for (byte[] buf = new byte[4096];;)
			{
				int rc = __zip.read(buf);
				if (rc < 0)
					break;
				
				baos.write(buf, 0, rc);
			}
			
			// Read in all the test classes
			try (BufferedReader br = new BufferedReader(
				new InputStreamReader(new ByteArrayInputStream(
				baos.toByteArray()), "utf-8")))
			{
				for (;;)
				{
					// End of file?
					String ln = br.readLine();
					if (ln == null)
						break;
					
					// Add test class to possible tests to run
					if (!ln.isEmpty())
						__testClasses.add(ln.trim());
				}
			}
		}
	}
}







>
>
>
>
>




<
<
<

|


>
>
>
>
>
>
>
>
>
>
>

|
>





>
>


>
|
|
<
<














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
<



>
|
|


>
>
>
>




|
>
>
|
|
|
>
>
>
>

<




<
<
<
<
<




















|
|





|
<
<
|
<
<






|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>


>


|
|
|
>
|

>
|
|
|
>
>
|
|
<
>
>
>
>
|
<
>
>
|
>


<
|
<
|
<
<
|
<
|
<
<
|
|
<
<
|
<
<
|
<
<
|
<
|
<
<
<
<
<
<
|
<
<
<
<
<

|
|
<
<
<
|
<
<
<
|
<
<
|
|
|
<
<
<
|
|
<
<
<
<
|
<
<
<
<
<
<
|
|
<
|
<
















|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

203
204
205
206





207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234


235


236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

312
313
314
315
316

317
318
319
320
321
322

323

324


325

326


327
328


329


330


331

332






333





334
335
336



337



338


339
340
341



342
343




344






345
346

347

348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

























































	@Override
	public void execute(EmulatedTestExecutionSpec __spec,
		TestResultProcessor __results)
	{
		// We need the project to access details
		Project project = this._testInVMTask.getProject();
		
		// Initialize the classpath for our emulator!
		// Otherwise the Gradle build will fail since it tries to get the
		// classpath outside of this
		this.emulatorClassPath(project, __spec.emulator);
		
		// Run for this suite/project
		EmulatedTestSuiteDescriptor suite =
			new EmulatedTestSuiteDescriptor(project);
		



		// Perform testing logic
		boolean allPassed;
		try
		{
			// Load tests to run
			Collection<String> classes = EmulatedTestUtilities.readJarServices(
				__spec.jar.getArchiveFile().get().getAsFile().toPath());
			
			// Report on the found test size (debugging)
			project.getLogger().lifecycle(String.format(
				"Found %d tests...%n", classes.size()));
			
			// Indicate that the suite has started execution
			__results.started(suite, EmulatedTestUtilities.startNow());
			
			// Execute test classes (find them and run them)
			allPassed = this.__executeClasses(__spec, __results, suite,
				classes);
			
			// Did all tests pass?
			__results.completed(suite.getId(),
				EmulatedTestUtilities.passOrFailNow(allPassed));
		}
		
		// Something went wrong it seems
		catch (Throwable t)
		{
			project.getLogger().error("Throwable caught during testing.", t);
			
			throw new RuntimeException("Caught throwable during testing.", t);


		}
		
		// Did not pass, so cause the task to fail
		if (!allPassed)
		{
			// Throw a blank failure exception
			RuntimeException toss = new RuntimeException("Failed tests.");
			toss.setStackTrace(new StackTraceElement[0]);
			
			throw toss;
		}
	}
	
	/**
	 * Executes the test class.
	 * 
	 * @param __spec The specification.
	 * @param __suite The suite to run.
	 * @param __testClass The test class.
	 * @return If this test passed.
	 * @since 2020/06/21
	 */
	private EmulatedTestResult __executeClass(EmulatedTestExecutionSpec __spec,
		EmulatedTestSuiteDescriptor __suite, String __testClass)
	{
		// Setup result
		EmulatedTestResult result = new EmulatedTestResult(
			__suite, __testClass);
		
		// Signal as started
		result.testStart();
		
		// Execute each class alone
		try
		{
			// Execute individual test
			int exitCode = this.__executeClassVm(__spec, result);
			
			// Finish the test with the result code
			result.testFinish(exitCode, null);
		}
		catch (Throwable t)
		{
			// Just mark failure
			result.testFinish(ExitValueConstants.FAILURE, t);
			
			// Print the trace since this was outside of the VM
			synchronized (System.err)
			{
				t.printStackTrace(System.err);
			}
		}
		
		return result;
	}
	
	/**
	 * Goes through and executes the single test class.
	 *
	 * @param __spec The specification.
	 * @param __result The output result.

	 * @return The exit value of the test.
	 * @since 2020/03/06
	 */
	@SuppressWarnings("resource")
	private int __executeClassVm(EmulatedTestExecutionSpec __spec,
		EmulatedTestResult __result)
	{
		Project project = this._testInVMTask.getProject();
		
		// Setup test standard output and error streams
		OutputStream stdOut = __result.stdOut();
		OutputStream stdErr = __result.stdErr();
		
		// For some reason test reports do not run if there is no output for
		// them, so this for the most part forces console output to happen
		// which makes tests happen
		String withinClass = __result.className;
		try
		{
			stdErr.write(String.format("Starting VM for %s...", withinClass)
				.getBytes());
		}
		catch (IOException ignored)
		{
		}
		
		// Execute the test Java program

		ExecResult result = project.javaexec(__javaExecSpec ->
			{
				Collection<String> args = new LinkedList<>();
				





				// Add emulator
				args.add("-Xemulator:" + __spec.emulator);
				
				// Add snapshot path
				args.add("-Xsnapshot:" + EmulatedTestExecutor.this
					._testInVMTask.__tempRoot().resolve("nps")
					.resolve(withinClass + ".nps").toAbsolutePath());
				
				// Classpath of the target JAR
				args.add("-classpath");
				args.add(EmulatedTestUtilities.classpathString(project,
					true));
				
				// Only run a single test
				args.add("net.multiphasicapps.tac.MainSingleRunner");
				
				// Target this single test
				args.add(withinClass);
				
				// Configure the VM for execution
				__javaExecSpec.classpath(EmulatedTestExecutor.this
					.emulatorClassPath(null, __spec.emulator));
				__javaExecSpec.setMain("cc.squirreljme.emulator.vm.VMFactory");
				__javaExecSpec.setArgs(args);
				
				// Pipe outputs to the specified areas so the console can be
				// read properly!
				__javaExecSpec.setStandardOutput(stdOut);


				__javaExecSpec.setErrorOutput(stdErr);


				
				// Do not throw an exception on a non-zero exit value since
				// it is important to us
				__javaExecSpec.setIgnoreExitValue(true);
			});
		
		// The exit value is the test result
		return result.getExitValue();
	}
	
	/**
	 * Returns the classpath for the emulator.
	 * 
	 * @param __project The project to use.
	 * @param __emulator The emulator to use.
	 * @return The classpath for the emulator.
	 * @throws NullPointerException On null arguments, or if {@code __project}
	 * is null and this is not already cached.
	 * @since 2020/06/22
	 */
	private Iterable<Object> emulatorClassPath(Project __project,
		String __emulator)
		throws NullPointerException
	{
		if (__emulator == null)
			throw new NullPointerException("NARG");
		
		// Use already cached value
		Map<String, Iterable<Object>> cache = this._emuClassPathCache;
		Iterable<Object> rv = cache.get(__emulator);
		if (rv != null)
			return rv; 
		
		// Get new result
		Iterable<Object> now = EmulatedTestUtilities.emulatorClassPath(
			__project, __emulator);
		
		// Add to the cache
		List<Object> toCache = new ArrayList<>();
		for (Object item : now)
			toCache.add(item);
		
		// Store unreadable form
		cache.put(__emulator,
			(rv = Collections.unmodifiableCollection(toCache)));
		
		// Ensure it stays unreadable
		return rv;
	}
	
	/**
	 * Goes through and executes the test classes.
	 *
	 * @param __spec The specification.
	 * @param __results The output results.
	 * @param __suite The suite to run.
	 * @param __classes The classes to run.
	 * @return Did all tests pass?
	 * @throws IOException On read errors.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/03/06
	 */
	@SuppressWarnings({"FeatureEnvy", "MagicNumber"})
	private boolean __executeClasses(EmulatedTestExecutionSpec __spec,
		TestResultProcessor __results, EmulatedTestSuiteDescriptor __suite,
		Iterable<String> __classes)
		throws IOException, NullPointerException
	{
		if (__spec == null || __results == null || __suite == null ||
			__classes == null)
			throw new NullPointerException("NARG");
		
		// And any results of the runs will be placed in this pool along
		// with the number of added and finished tests
		AtomicInteger finishedTests = new AtomicInteger();
		

		// Create jobs for the tests
		Set<String> failedTests = new TreeSet<>();
		boolean allPassed = true;
		for (String testClass : __classes)
		{

			// If stopping running, discontinue and fail the tests
			if (this._stopRunning)
			{
				allPassed = false;
				break;
			}

			

			// Execute the test


			EmulatedTestResult result = this.__executeClass(

				__spec, __suite, testClass);


			
			// Report the test


			result.report(__results);


			


			// Did this fail?

			if (result.isFailure())






				failedTests.add(result.className);





			
			// Increase the test counter, as this was grabbed
			finishedTests.incrementAndGet();



		}



		


		// There were test failures?
		if (!failedTests.isEmpty())
		{



			// Not every test passed
			allPassed = false;




			






			// Print all the failed tests out
			for (String testClass : failedTests)

				System.err.printf("Failed Test: %s%n", testClass);

		}
		
		// Return how all the tests ran
		return allPassed;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/03/06
	 */
	@Override
	public void stopNow()
	{
		// Stop running and prevent the next test from stopping
		this._stopRunning = true;
	}
}

























































Added buildSrc/src/main/java/cc/squirreljme/plugin/tasks/test/EmulatedTestResult.java.





































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.plugin.tasks.test;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import org.gradle.api.internal.tasks.testing.TestResultProcessor;

/**
 * The contains the result for emulated tests.
 *
 * @since 2020/06/22
 */
public final class EmulatedTestResult
{
	/** Which test is this for? */
	protected final String className;
	
	/** The suite. */
	protected final EmulatedTestSuiteDescriptor suite;
	
	/** The console lines. */
	private final Collection<ConsoleLine> _lines =
		new ArrayList<>(128);
	
	/** The exit code of the test. */
	private int _exitCode =
		Integer.MIN_VALUE;
	
	/** The start time. */
	private long _timeStart =
		Long.MIN_VALUE;
	
	/** The end time. */
	private long _timeEnd =
		Long.MIN_VALUE;
	
	/** The tossed exception, if any. */
	private Throwable _tossed;
	
	/**
	 * Initializes the base for the test result.
	 * 
	 * @param __suite The test suite.
	 * @param __className The name of the class.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/22
	 */
	public EmulatedTestResult(EmulatedTestSuiteDescriptor __suite,
		String __className)
		throws NullPointerException
	{
		if (__suite == null || __className == null)
			throw new NullPointerException("NARG");
		
		this.suite = __suite;
		this.className = __className;
	}
	
	/**
	 * Adds a line to the output.
	 * 
	 * @param __line The line to add.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/22
	 */
	public void addLine(ConsoleLine __line)
		throws NullPointerException
	{
		if (__line == null)
			throw new NullPointerException("NARG");
		
		synchronized (this)
		{
			this._lines.add(__line);
		}
	}
	
	/**
	 * Is this a test failure?
	 * 
	 * @return If this is a test failure.
	 * @since 2020/06/22
	 */
	public final boolean isFailure()
	{
		synchronized (this)
		{
			int exitCode = this._exitCode;
			return exitCode != ExitValueConstants.SUCCESS &&
				exitCode != ExitValueConstants.SKIPPED;
		}
	}
	
	/**
	 * Sends in the test report.
	 * 
	 * @param __results The output results.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/22
	 */
	public final void report(TestResultProcessor __results)
		throws NullPointerException
	{
		if (__results == null)
			throw new NullPointerException("NARG");
		
		EmulatedTestSuiteDescriptor suite = this.suite;
		String testClass = this.className;
		
		// In SquirrelJME all tests only have a single run method, so the
		// run is the actual class of execution
		EmulatedTestClassDescriptor classy =
			new EmulatedTestClassDescriptor(suite, testClass);
		EmulatedTestMethodDescriptor method =
			new EmulatedTestMethodDescriptor(classy);
		
		synchronized (this)
		{
			// Execution times
			long timeStart = this._timeStart;
			long timeEnd = this._timeEnd;
			
			// Signal start
			__results.started(classy,
				EmulatedTestUtilities.startAt(timeStart, suite));
			__results.started(method,
				EmulatedTestUtilities.startAt(timeStart, classy));
			
			// Print all the output text
			for (ConsoleLine line : this._lines)
				line.report(__results, method);
			
			// Was the test in error?
			int exitCode = this._exitCode;
			if (exitCode != ExitValueConstants.SUCCESS &&
				exitCode != ExitValueConstants.SKIPPED)
			{
				// Was an exception thrown? If not, make a generic one
				Throwable tossed = this._tossed;
				if (tossed == null)
				{
					tossed = new Throwable("Test Failed");
					
					// Make the trace empty as it has no meaning
					tossed.setStackTrace(new StackTraceElement[0]);
				}
				
				// Toss it now
				__results.failure(method.getId(), tossed);
			}
			
			// End execution
			__results.completed(method.getId(),
				EmulatedTestUtilities.passSkipOrFailAt(timeEnd, exitCode));
			__results.completed(classy.getId(),
				EmulatedTestUtilities.passSkipOrFailAt(timeEnd, exitCode));
		}
	}
	
	/**
	 * Returns standard error.
	 * 
	 * @return Standard error.
	 * @since 2020/06/22
	 */
	public OutputStream stdErr()
	{
		return new PipeOutputStream(this, true);
	}
	
	/**
	 * Returns standard output.
	 * 
	 * @return Standard output.
	 * @since 2020/06/22
	 */
	public OutputStream stdOut()
	{
		return new PipeOutputStream(this, false);
	}
	
	/**
	 * Finishes the test with the given exit code.
	 * 
	 * @param __exitCode The exit code.
	 * @param _toss The tossed exception, if any.
	 * @since 2020/06/22
	 */
	public void testFinish(int __exitCode, Throwable _toss)
	{
		synchronized (this)
		{
			if (this._timeEnd != Long.MIN_VALUE)
				throw new IllegalStateException("Test already finished.");
			
			this._timeEnd = System.currentTimeMillis();
			this._exitCode = __exitCode;
			this._tossed = _toss;
		}
	}
	
	/**
	 * Starts the test.
	 * 
	 * @since 2020/06/22
	 */
	public final void testStart()
	{
		synchronized (this)
		{
			if (this._timeStart != Long.MIN_VALUE)
				throw new IllegalStateException("Test already started.");
			
			this._timeStart = System.currentTimeMillis();
		}
	}
}

Changes to buildSrc/src/main/java/cc/squirreljme/plugin/tasks/test/EmulatedTestUtilities.java.

1
2
3
4
5
6
7
8
9
10
11
12



13





14

15
16

17

18
19


20
21
22
23
24
25
26
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.plugin.tasks.test;

import cc.squirreljme.plugin.SquirrelJMEPluginConfiguration;



import java.io.File;





import java.nio.file.Path;

import java.util.Collection;
import java.util.Deque;

import java.util.LinkedList;

import java.util.Set;
import java.util.TreeSet;


import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.internal.tasks.testing.DefaultTestOutputEvent;
import org.gradle.api.internal.tasks.testing.TestCompleteEvent;
import org.gradle.api.internal.tasks.testing.TestDescriptorInternal;












>
>
>

>
>
>
>
>

>


>

>


>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.plugin.tasks.test;

import cc.squirreljme.plugin.SquirrelJMEPluginConfiguration;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Collection;
import java.util.Deque;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.internal.tasks.testing.DefaultTestOutputEvent;
import org.gradle.api.internal.tasks.testing.TestCompleteEvent;
import org.gradle.api.internal.tasks.testing.TestDescriptorInternal;
209
210
211
212
213
214
215













216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
		rv.add(emuProject.getConfigurations().getByName("runtimeClasspath")
			.getFiles());
		rv.add(((Jar)emuProject.getTasks().getByName("jar")).getOutputs()
			.getFiles());
		
		return rv;
	}













	
	/**
	 * Returns a failing completion.
	 *
	 * @return An event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent failNow()
	{
		return new TestCompleteEvent(System.currentTimeMillis(),
			TestResult.ResultType.FAILURE);
	}
	
	/**
	 * Outputs a message.
	 *
	 * @param __dest The destination.
	 * @param __msg The message.







>
>
>
>
>
>
>
>
>
>
>
>
>









|
<







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

252
253
254
255
256
257
258
		rv.add(emuProject.getConfigurations().getByName("runtimeClasspath")
			.getFiles());
		rv.add(((Jar)emuProject.getTasks().getByName("jar")).getOutputs()
			.getFiles());
		
		return rv;
	}
	
	/**
	 * Fails at the specified time.
	 * 
	 * @param __millis The time to fail at.
	 * @return The completion event.
	 * @since 2020/06/22
	 */
	private static TestCompleteEvent failAt(long __millis)
	{
		return new TestCompleteEvent(__millis,
			TestResult.ResultType.FAILURE);
	}
	
	/**
	 * Returns a failing completion.
	 *
	 * @return An event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent failNow()
	{
		return EmulatedTestUtilities.failAt(System.currentTimeMillis());

	}
	
	/**
	 * Outputs a message.
	 *
	 * @param __dest The destination.
	 * @param __msg The message.
261
262
263
264
265
266
267













268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304


















305
306
307
308
309
310
311
312
313
314
315
316
317


318












319




320



















































































321
322
323
324
325
326
327
328
329
330
331

332
























333
334
335
336
337
338
339
	 * @since 2020/03/06
	 */
	public static TestOutputEvent outputErr(String __msg)
	{
		return EmulatedTestUtilities.output(
			TestOutputEvent.Destination.StdErr, __msg);
	}













	
	/**
	 * Returns a passing completion.
	 *
	 * @return An event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent passNow()
	{
		return new TestCompleteEvent(System.currentTimeMillis(),
			TestResult.ResultType.SUCCESS);
	}
	
	/**
	 * Either passes or fails.
	 *
	 * @param __pass Does the test pass?
	 * @return The event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent passOrFailNow(boolean __pass)
	{
		return (__pass ? EmulatedTestUtilities.passNow() :
			EmulatedTestUtilities.failNow());
	}
	
	/**
	 * Either passes or skips.
	 *

	 * @param __pass Does the test pass?
	 * @return The event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent passOrSkipNow(boolean __pass)
	{
		return (__pass ? EmulatedTestUtilities.passNow() :
			EmulatedTestUtilities.skipNow());


















	}
	
	/**
	 * Depending on the exit code, this will pass, fail, or skip a test.
	 *
	 * @param __exitCode The exit code.
	 * @return The completion event.
	 * @since 2020/03/07
	 */
	public static TestCompleteEvent passSkipOrFailNow(int __exitCode)
	{
		if (__exitCode == ExitValueConstants.SUCCESS)
			return EmulatedTestUtilities.passNow();


		else if (__exitCode == ExitValueConstants.SKIPPED)












			return EmulatedTestUtilities.skipNow();




		return EmulatedTestUtilities.failNow();



















































































	}
	
	/**
	 * Returns a skipping completion.
	 *
	 * @return An event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent skipNow()
	{
		return new TestCompleteEvent(System.currentTimeMillis(),

			TestResult.ResultType.SKIPPED);
























	}
	
	/**
	 * Returns a test starting now.
	 *
	 * @return An event
	 * @since 2020/03/06







>
>
>
>
>
>
>
>
>
>
>
>
>









|
<


















>




|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











<
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
	 * @since 2020/03/06
	 */
	public static TestOutputEvent outputErr(String __msg)
	{
		return EmulatedTestUtilities.output(
			TestOutputEvent.Destination.StdErr, __msg);
	}
	
	/**
	 * Passes at the given time.
	 * 
	 * @param __millis The time to pass at.
	 * @return The completion event.
	 * @since 2020/06/22
	 */
	private static TestCompleteEvent passAt(long __millis)
	{
		return new TestCompleteEvent(__millis,
			TestResult.ResultType.SUCCESS);
	}
	
	/**
	 * Returns a passing completion.
	 *
	 * @return An event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent passNow()
	{
		return EmulatedTestUtilities.passAt(System.currentTimeMillis());

	}
	
	/**
	 * Either passes or fails.
	 *
	 * @param __pass Does the test pass?
	 * @return The event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent passOrFailNow(boolean __pass)
	{
		return (__pass ? EmulatedTestUtilities.passNow() :
			EmulatedTestUtilities.failNow());
	}
	
	/**
	 * Either passes or skips.
	 *
	 * @param __millis The time to finish.
	 * @param __pass Does the test pass?
	 * @return The event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent passOrSkipAt(long __millis, boolean __pass)
	{
		return (__pass ? EmulatedTestUtilities.passAt(__millis) :
			EmulatedTestUtilities.skipAt(__millis));
	}
	
	/**
	 * Passes, skips, or fails at the given time.
	 * 
	 * @param __millis The time to finish.
	 * @param __exitCode The status code.
	 * @return The completion event.
	 * @since 2020/06/22
	 */
	public static TestCompleteEvent passSkipOrFailAt(long __millis,
		int __exitCode)
	{
		if (__exitCode == ExitValueConstants.SUCCESS)
			return EmulatedTestUtilities.passAt(__millis);
		else if (__exitCode == ExitValueConstants.SKIPPED)
			return EmulatedTestUtilities.skipAt(__millis);
		return EmulatedTestUtilities.failAt(__millis);
	}
	
	/**
	 * Depending on the exit code, this will pass, fail, or skip a test.
	 *
	 * @param __exitCode The exit code.
	 * @return The completion event.
	 * @since 2020/03/07
	 */
	public static TestCompleteEvent passSkipOrFailNow(int __exitCode)
	{

		return EmulatedTestUtilities.passSkipOrFailAt(
			System.currentTimeMillis(), __exitCode);
	}
	
	/**
	 * Reads test services from the JAR. 
	 *
	 * @param __path The path to read from.
	 * @throws IOException On read failures.
	 * @since 2020/06/22
	 */
	public static Collection<String> readJarServices(Path __path)
		throws IOException, NullPointerException
	{
		if (__path == null)
			throw new NullPointerException("NARG");
		
		try (InputStream in = Files.newInputStream(
			__path, StandardOpenOption.READ);
			ZipInputStream zip = new ZipInputStream(in))
		{
			return EmulatedTestUtilities.readJarServices(zip);
		}
	}
	
	/**
	 * Reads test services from the JAR. 
	 *
	 * @param __zip The ZIP to read.
	 * @throws IOException On read failures.
	 * @since 2020/05/25
	 */
	public static Collection<String> readJarServices(ZipInputStream __zip)
		throws IOException
	{
		// Resultant collection
		Collection<String> result = new LinkedHashSet<>();
		
		// Potential resource file data
		byte[] resourceData = null;
		
		// Go through entries within the ZIP
		ZipEntry entry;
		while (null != (entry = __zip.getNextEntry()))
		{
			// Only consider the services file
			if (!Objects.equals(EmulatedTestExecutor.SERVICE_RESOURCE,
				entry.getName()))
				continue;
			
			// Copy file data
			try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
			{
				// Copy bytes
				byte[] buf = new byte[4096];
				for (;;)
				{
					int rc = __zip.read(buf);
					
					if (rc < 0)
						break;
					
					baos.write(buf, 0, rc);
				}
				
				// Set resource data and stop finding entries
				resourceData = baos.toByteArray();
				break;
			}
		}
		
		// Read in service list
		if (resourceData != null)
			try (BufferedReader br = new BufferedReader(new InputStreamReader(
				new ByteArrayInputStream(resourceData),
					StandardCharsets.UTF_8)))
			{
				for (;;)
				{
					// End of file?
					String ln = br.readLine();
					if (ln == null)
						break;
					
					// Only consider lines with content
					ln = ln.trim();
					if (!ln.isEmpty())
						result.add(ln);
				}
			}
		
		return result;
	}
	
	/**
	 * Skips at the given time.
	 * 
	 * @param __millis The time to skip at.
	 * @return The completion event.
	 * @since 2020/06/22
	 */
	private static TestCompleteEvent skipAt(long __millis)
	{
		return new TestCompleteEvent(__millis,
			TestResult.ResultType.SKIPPED);
	}
	
	/**
	 * Returns a skipping completion.
	 *
	 * @return An event.
	 * @since 2020/03/06
	 */
	public static TestCompleteEvent skipNow()
	{
		return EmulatedTestUtilities.skipAt(System.currentTimeMillis());
	}
	
	/**
	 * Returns a test starting now.
	 *
	 * @param __millis The starting time.
	 * @return An event
	 * @since 2020/06/22
	 */
	public static TestStartEvent startAt(long __millis)
	{
		return EmulatedTestUtilities.startAt(__millis, null);
	}
	
	/**
	 * Returns a test starting now.
	 *
	 * @param __test The test information.
	 * @return An event
	 * @since 2020/06/22
	 */
	public static TestStartEvent startAt(long __millis,
		TestDescriptorInternal __test)
	{
		return new TestStartEvent(__millis,
			(__test == null ? null : __test.getId()));
	}
	
	/**
	 * Returns a test starting now.
	 *
	 * @return An event
	 * @since 2020/03/06
348
349
350
351
352
353
354

355
356
357
358
	 *
	 * @param __test The test information.
	 * @return An event
	 * @since 2020/03/06
	 */
	public static TestStartEvent startNow(TestDescriptorInternal __test)
	{

		return new TestStartEvent(System.currentTimeMillis(),
			(__test == null ? null : __test.getId()));
	}
}







>
|
<


529
530
531
532
533
534
535
536
537

538
539
	 *
	 * @param __test The test information.
	 * @return An event
	 * @since 2020/03/06
	 */
	public static TestStartEvent startNow(TestDescriptorInternal __test)
	{
		return EmulatedTestUtilities.startAt(
			System.currentTimeMillis(), __test);

	}
}

Changes to buildSrc/src/main/java/cc/squirreljme/plugin/tasks/test/PipeOutputStream.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.plugin.tasks.test;

import java.io.OutputStream;
import org.gradle.api.internal.tasks.testing.TestResultProcessor;
import org.gradle.api.tasks.testing.TestOutputEvent;

/**
 * Pipes output stream to the results output accordingly.
 *
 * @since 2020/03/07
 */
public class PipeOutputStream
	extends OutputStream
{
	/** The output buffer. */
	protected final StringBuilder buffer =
		new StringBuilder();
	
	/** The test ID. */
	protected final Object testId;
	
	/** The destination. */
	protected final TestOutputEvent.Destination destination;
	
	/** Results for execution. */
	private final TestResultProcessor results;
	
	/** Do we have a carriage return? */
	private boolean haveCR;
	
	/**
	 * Initializes the pipe output.
	 *
	 * @param __id The test ID.
	 * @param __r The result processor.
	 * @param __d The destination.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/03/07
	 */
	public PipeOutputStream(Object __id, TestResultProcessor __r,
		TestOutputEvent.Destination __d)
		throws NullPointerException
	{
		if (__id == null || __r == null || __d == null)
			throw new NullPointerException();
		
		this.testId = __id;
		this.results = __r;
		this.destination = __d;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/03/07
	 */
	@SuppressWarnings("DuplicatedCode")
	@Override
	public void write(int __b)
	{
		StringBuilder buffer = this.buffer;
		
		// Flush the buffer on newlines
		if (__b == '\r' || __b == '\n')
		{
			if (__b == '\r')
				this.haveCR = true;
			else
			{
				this.__flush();
				this.haveCR = false;
			}
		}
		else
		{
			// Flush if we just gave a CR
			if (this.haveCR)
				this.__flush();
			
			if (__b < 0)
				buffer.append('?');
			else
				buffer.append((char)__b);
		}












<
<













|
|

|
|

<
<
<

|



|
|
<
|

|

|
<


|
|

<
|
|
















|



|





|







1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31



32
33
34
35
36
37
38

39
40
41
42
43

44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.plugin.tasks.test;

import java.io.OutputStream;



/**
 * Pipes output stream to the results output accordingly.
 *
 * @since 2020/03/07
 */
public class PipeOutputStream
	extends OutputStream
{
	/** The output buffer. */
	protected final StringBuilder buffer =
		new StringBuilder();
	
	/** The test result. */
	protected final EmulatedTestResult result;
	
	/** Is this standard error. */
	protected final boolean stdErr;
	



	/** Do we have a carriage return? */
	private boolean _haveCr;
	
	/**
	 * Initializes the pipe output.
	 * 
	 * @param __result The result to send to.

	 * @param __stdErr Is this standard error?
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/22
	 */
	public PipeOutputStream(EmulatedTestResult __result, boolean __stdErr)

		throws NullPointerException
	{
		if (__result == null)
			throw new NullPointerException("NARG");
		

		this.result = __result;
		this.stdErr = __stdErr;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/03/07
	 */
	@SuppressWarnings("DuplicatedCode")
	@Override
	public void write(int __b)
	{
		StringBuilder buffer = this.buffer;
		
		// Flush the buffer on newlines
		if (__b == '\r' || __b == '\n')
		{
			if (__b == '\r')
				this._haveCr = true;
			else
			{
				this.__flush();
				this._haveCr = false;
			}
		}
		else
		{
			// Flush if we just gave a CR
			if (this._haveCr)
				this.__flush();
			
			if (__b < 0)
				buffer.append('?');
			else
				buffer.append((char)__b);
		}
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164
165
166
167
168
169
170
		{
			byte b = __b[__o++];
			
			// Flush the buffer on newlines
			if (b == '\r' || b == '\n')
			{
				if (b == '\r')
					this.haveCR = true;
				else
				{
					this.__flush();
					this.haveCR = false;
				}
			}
			else
			{
				// Flush if we just gave a CR
				if (this.haveCR)
					this.__flush();
				
				if (b < 0)
					buffer.append('?');
				else
					buffer.append((char)b);
			}
		}
	}
	
	/**
	 * Flushes the buffer.
	 *
	 * @since 2020/03/07
	 */
	private void __flush()
	{

		StringBuilder buffer = this.buffer;
		
		// Send to output
		buffer.append('\n');
		this.results.output(this.testId, EmulatedTestUtilities.output(
			this.destination, buffer.toString()));
		
		// Clear the buffer
		buffer.setLength(0);
		
		// Always clear CR state
		this.haveCR = false;
	}
}







|



|





|

















>

|
<
<
<
|





|


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151



152
153
154
155
156
157
158
159
160
		{
			byte b = __b[__o++];
			
			// Flush the buffer on newlines
			if (b == '\r' || b == '\n')
			{
				if (b == '\r')
					this._haveCr = true;
				else
				{
					this.__flush();
					this._haveCr = false;
				}
			}
			else
			{
				// Flush if we just gave a CR
				if (this._haveCr)
					this.__flush();
				
				if (b < 0)
					buffer.append('?');
				else
					buffer.append((char)b);
			}
		}
	}
	
	/**
	 * Flushes the buffer.
	 *
	 * @since 2020/03/07
	 */
	private void __flush()
	{
		// Send buffer to the output
		StringBuilder buffer = this.buffer;
		this.result.addLine(new ConsoleLine(this.stdErr,



			System.currentTimeMillis(), buffer.toString()));
		
		// Clear the buffer
		buffer.setLength(0);
		
		// Always clear CR state
		this._haveCr = false;
	}
}

Changes to changelog.mkd.

25
26
27
28
29
30
31

32
33
34
35
36
37
38
 * Programs and Libraries
   * `cldc-compact`
     * Added a rehash indicator for the internal `__BucketMap__` so that
       `java.util.Hashtable` knows when a reorder was performed.
     * Added `java.util.Vector`, it was missing.
     * Added support for ISO-8859-15, this is the newer encoding with the
       Euro symbol.

     * Corrected bug in `__CanSetPrintStream__` where if it were set to itself
       then it could lead to infinite recursion, instead if this kind of
       stream is attempted to be set it will use the target.
     * Corrected `java.lang.Object.clone()` to return the new copy of the array
       when cloning and not the original.
     * Corrected `java.util.Objects.equals()` not correctly checking equality
       on two objects.







>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 * Programs and Libraries
   * `cldc-compact`
     * Added a rehash indicator for the internal `__BucketMap__` so that
       `java.util.Hashtable` knows when a reorder was performed.
     * Added `java.util.Vector`, it was missing.
     * Added support for ISO-8859-15, this is the newer encoding with the
       Euro symbol.
     * Added support for `os.arch`, `os.name`, and `os.version`.
     * Corrected bug in `__CanSetPrintStream__` where if it were set to itself
       then it could lead to infinite recursion, instead if this kind of
       stream is attempted to be set it will use the target.
     * Corrected `java.lang.Object.clone()` to return the new copy of the array
       when cloning and not the original.
     * Corrected `java.util.Objects.equals()` not correctly checking equality
       on two objects.
48
49
50
51
52
53
54

55
56
57
58
59
60
61
     * Implemented `java.io.PrintStream`.
     * Implemented `java.util.EventObject`.
     * Implemented `java.util.Hashtable`.
     * Implemented `java.util.LinkedHashMap`.
     * Implemented `java.util.LinkedList`.
     * Made the stack trace printed by `Throwable` much cleaner so that it
       takes up less screen space and is formatted a bit better.

     * Return values for `line.separator`, `microedition.encoding`,
       `microedition.configuration`, and `microedition.locale`.
   * `demo-hello`
     * Made the system properties array `final`.
   * `jblend-api`
     * Added API Stubs.
   * `launcher`







>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
     * Implemented `java.io.PrintStream`.
     * Implemented `java.util.EventObject`.
     * Implemented `java.util.Hashtable`.
     * Implemented `java.util.LinkedHashMap`.
     * Implemented `java.util.LinkedList`.
     * Made the stack trace printed by `Throwable` much cleaner so that it
       takes up less screen space and is formatted a bit better.
     * Removed `GuestDepth`, it is no longer a concept.
     * Return values for `line.separator`, `microedition.encoding`,
       `microedition.configuration`, and `microedition.locale`.
   * `demo-hello`
     * Made the system properties array `final`.
   * `jblend-api`
     * Added API Stubs.
   * `launcher`
152
153
154
155
156
157
158

159
160
161
162
163
164
165
   * SpringCoat
     * Add limit to stack frame depth.
     * Add support for system properties being based to virtual machine
       instances.
     * Allow inheritance of static methods in classes.
     * Profiler thread lists are easier to read because the main suite is
       listed instead of the VM identifier.

   * SummerCoat
     * New Virtual Machine, register based.
     * Vast improvements over SpringCoat, faster and slimmer.
   * RatufaCoat
     * New Virtual Machine, based off SummerCoat.
     * Fast and slim, written in C.
 * Cleanup







>







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
   * SpringCoat
     * Add limit to stack frame depth.
     * Add support for system properties being based to virtual machine
       instances.
     * Allow inheritance of static methods in classes.
     * Profiler thread lists are easier to read because the main suite is
       listed instead of the VM identifier.
     * Refactored greatly to be much leaner and simplified.
   * SummerCoat
     * New Virtual Machine, register based.
     * Vast improvements over SpringCoat, faster and slimmer.
   * RatufaCoat
     * New Virtual Machine, based off SummerCoat.
     * Fast and slim, written in C.
 * Cleanup

Changes to emulators/emulator-base/build.gradle.

1
2
3
4
5
6
7
8
9
10
11








12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
plugins
{
	// C++ needs to be first otherwise the build will break
	id "cpp-library"
	id "java-library"
	id "java-test-fixtures"
}

description = "This library provides the base support for testing and " +
	"running SquirrelJME on a Java SE host, which is normally not " +
	"capable of doing as such."









// Due to the combination of C++ and Java these dependencies have to be very
// specific in that they only refer to the Java or C++ portion. So
// "implementation" and "compile" cannot be used because the C++ library will
// try to use them during compilation.
dependencies
{
	// SquirrelJME just uses TestNG here since it is flexible enough to
	// support how SquirrelJME needs to be (testing more as if it were running
	// on the target device). Due to the flexibility it allows easier switching
	// from Java SE, SpringCoat, and SummerCoat
	compileClasspath "org.testng:testng:7.1.0"
	runtimeClasspath "org.testng:testng:7.1.0"

	// We need these two modules to obtain the SquirrelJME specific classes
	compileClasspath project(":modules:cldc-compact")
	compileClasspath project(":modules:cldc")
	compileClasspath project(":modules:common-vm")
	compileClasspath project(":modules:io")
	compileClasspath project(":modules:meep-swm")
	compileClasspath project(":modules:tac")
	compileClasspath project(":modules:tool-manifest-reader")
	compileClasspath project(":modules:zip")

	// And for run-time to be able to be ran
	runtimeClasspath project(":modules:cldc-compact")
	runtimeClasspath project(":modules:cldc")
	runtimeClasspath project(":modules:common-vm")
	runtimeClasspath project(":modules:io")
	runtimeClasspath project(":modules:meep-swm")
	runtimeClasspath project(":modules:tac")
	runtimeClasspath project(":modules:tool-manifest-reader")
	runtimeClasspath project(":modules:zip")
}

// We need the native library in the JAR before we can properly use it
// But we can compile the Java code just fine without it
jar {
	dependsOn "assembleRelease"

	from buildDir.toPath().resolve("lib").resolve("main").
		resolve("release").toFile()
	into "/"
}











>
>
>
>
>
>
>
>
















<


<

<




<


<

<












1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37

38

39
40
41
42

43
44

45

46
47
48
49
50
51
52
53
54
55
56
57
plugins
{
	// C++ needs to be first otherwise the build will break
	id "cpp-library"
	id "java-library"
	id "java-test-fixtures"
}

description = "This library provides the base support for testing and " +
	"running SquirrelJME on a Java SE host, which is normally not " +
	"capable of doing as such."

// Although it would be useful to use Java 8, we have to stay on Java 7
// because SquirrelJME is a Java 7 VM.
compileJava
{
	sourceCompatibility = JavaVersion.VERSION_1_7
	targetCompatibility = JavaVersion.VERSION_1_7
}

// Due to the combination of C++ and Java these dependencies have to be very
// specific in that they only refer to the Java or C++ portion. So
// "implementation" and "compile" cannot be used because the C++ library will
// try to use them during compilation.
dependencies
{
	// SquirrelJME just uses TestNG here since it is flexible enough to
	// support how SquirrelJME needs to be (testing more as if it were running
	// on the target device). Due to the flexibility it allows easier switching
	// from Java SE, SpringCoat, and SummerCoat
	compileClasspath "org.testng:testng:7.1.0"
	runtimeClasspath "org.testng:testng:7.1.0"

	// We need these two modules to obtain the SquirrelJME specific classes
	compileClasspath project(":modules:cldc-compact")

	compileClasspath project(":modules:common-vm")
	compileClasspath project(":modules:io")

	compileClasspath project(":modules:tac")

	compileClasspath project(":modules:zip")

	// And for run-time to be able to be ran
	runtimeClasspath project(":modules:cldc-compact")

	runtimeClasspath project(":modules:common-vm")
	runtimeClasspath project(":modules:io")

	runtimeClasspath project(":modules:tac")

	runtimeClasspath project(":modules:zip")
}

// We need the native library in the JAR before we can properly use it
// But we can compile the Java code just fine without it
jar {
	dependsOn "assembleRelease"

	from buildDir.toPath().resolve("lib").resolve("main").
		resolve("release").toFile()
	into "/"
}

Added emulators/emulator-base/src/main/cpp/mle_object.cpp.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/* -*- Mode: C++; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// -------------------------------------------------------------------------*/

#include "squirreljme.h"
#include "cc_squirreljme_jvm_mle_ObjectShelf.h"

JNIEXPORT jint JNICALL Impl_mle_ObjectShelf_arrayLength(JNIEnv* env,
	jclass classy, jarray array)
{
	jclass classClass;
	jmethodID classIsArrayId;

	if (array == NULL)
		return -1;

	// Determine if this is an array or not
	classClass = env->FindClass("java/lang/Class");
	classIsArrayId = env->GetMethodID(classClass, "isArray", "()Z");
	if (JNI_FALSE == env->CallBooleanMethod(env->GetObjectClass(array),
		classIsArrayId))
		return -1;

	return env->GetArrayLength(array);
}

static const JNINativeMethod mleObjectMethods[] =
{
	{"arrayLength", "(Ljava/lang/Object;)I",
		(void*)Impl_mle_ObjectShelf_arrayLength},
};

jint JNICALL mleObjectInit(JNIEnv* env, jclass classy)
{
	return env->RegisterNatives(
		env->FindClass("cc/squirreljme/jvm/mle/ObjectShelf"),
		mleObjectMethods, sizeof(mleObjectMethods) /
			sizeof(JNINativeMethod));
}

Added emulators/emulator-base/src/main/cpp/mle_runtime.cpp.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/* -*- Mode: C++; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// -------------------------------------------------------------------------*/

#include "squirreljme.h"
#include "cc_squirreljme_jvm_mle_RuntimeShelf.h"

JNIEXPORT jint JNICALL Impl_mle_RuntimeShelf_lineEnding(JNIEnv*, jclass)
{
#if defined(_WIN32)
	return 3;
#else
	return 1;
#endif
}

JNIEXPORT jint JNICALL Impl_mle_RuntimeShelf_vmType(JNIEnv*, jclass)
{
	// The value 1 is Java SE type
	return 1;
}

static const JNINativeMethod mleRuntimeMethods[] =
{
	{"lineEnding", "()I", (void*)Impl_mle_RuntimeShelf_lineEnding},
	{"vmType", "()I", (void*)Impl_mle_RuntimeShelf_vmType},
};

jint JNICALL mleRuntimeInit(JNIEnv* env, jclass classy)
{
	return env->RegisterNatives(
		env->FindClass("cc/squirreljme/jvm/mle/RuntimeShelf"),
		mleRuntimeMethods, sizeof(mleRuntimeMethods) /
			sizeof(JNINativeMethod));
}

Added emulators/emulator-base/src/main/cpp/mle_terminal.cpp.





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* -*- Mode: C++; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// -------------------------------------------------------------------------*/

#include <stdio.h>

#include "squirreljme.h"
#include "cc_squirreljme_jvm_mle_TerminalShelf.h"

static FILE* getPipeForFd(jint fd)
{
	if (fd == 1)
		return stdout;
	else if (fd == 2)
		return stderr;
	return NULL;
}

JNIEXPORT jint JNICALL Impl_mle_TerminalShelf_flush(JNIEnv* env,
	jclass classy, jint fd)
{
	FILE* pipe = getPipeForFd(fd);

	if (pipe == NULL)
		return -1;

	if (fflush(pipe) == 0)
		return 1;
	return -1;
}

JNIEXPORT jint JNICALL Impl_mle_TerminalShelf_writeII(JNIEnv* env,
	jclass classy, jint fd, jint code)
{
	FILE* pipe = getPipeForFd(fd);

	if (pipe == NULL)
		return -1;

	if (fputc(code, pipe) >= 0)
		return 1;
	return -1;
}

static const JNINativeMethod mleTerminalMethods[] =
{
	{"flush", "(I)I", (void*)Impl_mle_TerminalShelf_flush},
	{"write", "(II)I", (void*)Impl_mle_TerminalShelf_writeII},
};

jint JNICALL mleTerminalInit(JNIEnv* env, jclass classy)
{
	return env->RegisterNatives(
		env->FindClass("cc/squirreljme/jvm/mle/TerminalShelf"),
		mleTerminalMethods, sizeof(mleTerminalMethods) /
			sizeof(JNINativeMethod));
}

Changes to emulators/emulator-base/src/main/cpp/nativebinding.cpp.

9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "jni.h"
#include "cc_squirreljme_emulator_NativeBinding.h"
#include "cc_squirreljme_jvm_Assembly.h"


// Method handler for special functions
JNIEXPORT void JNICALL doNothing(JNIEnv* env, jclass classy);
JNIEXPORT jint JNICALL doNothingZeroI(JNIEnv* env, jclass classy);
JNIEXPORT void JNICALL notImplemented(JNIEnv* env, jclass classy);
JNIEXPORT void JNICALL restrictedFunction(JNIEnv* env, jclass classy);

// Glue for putting names together
#define GLUE_NAME(name) Java_cc_squirreljme_jvm_Assembly_sysCall##name

// Assembly method mappings
static const JNINativeMethod assemblyMethods[] =
{
	{"arrayLength", "(J)I", (void*)Java_cc_squirreljme_jvm_Assembly_arrayLength__J},
	{"arrayLength", "(Ljava/lang/Object;)I", (void*)Java_cc_squirreljme_jvm_Assembly_arrayLength__Ljava_lang_Object_2},
	{"arrayLengthSet", "(JI)V", (void*)restrictedFunction},
	{"arrayLengthSet", "(Ljava/lang/Object;I)V", (void*)restrictedFunction},
	{"atomicCompareGetAndSet", "(IIJ)I", (void*)notImplemented},
	{"atomicDecrementAndGet", "(J)I", (void*)notImplemented},
	{"atomicIncrement", "(J)V", (void*)notImplemented},
	{"breakpoint", "()V", (void*)doNothing},
	{"classInfoOfBoolean", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfBooleanPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfByte", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfBytePointer", "()J", (void*)restrictedFunction},
	{"classInfoOfCharacter", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfCharacterPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfDouble", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfDoublePointer", "()J", (void*)restrictedFunction},
	{"classInfoOfFloat", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfFloatPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfInteger", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfIntegerPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfLong", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfLongPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfShort", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfShortPointer", "()J", (void*)restrictedFunction},
	{"doublePack", "(II)D", (void*)notImplemented},
	{"doubleToRawLongBits", "(D)J", (void*)notImplemented},
	{"doubleUnpackHigh", "(D)I", (void*)notImplemented},
	{"doubleUnpackLow", "(D)I", (void*)notImplemented},
	{"exceptionHandle", "()V", (void*)doNothing},
	{"floatToRawIntBits", "(F)I", (void*)notImplemented},
	{"intBitsToFloat", "(I)F", (void*)notImplemented},
	{"invoke", "(JJ)V", (void*)restrictedFunction},
	{"invoke", "(JJI)V", (void*)restrictedFunction},
	{"invoke", "(JJII)V", (void*)restrictedFunction},
	{"invoke", "(JJIII)V", (void*)restrictedFunction},
	{"invoke", "(JJIIII)V", (void*)restrictedFunction},
	{"invoke", "(JJIIIII)V", (void*)restrictedFunction},
	{"invoke", "(JJIIIIII)V", (void*)restrictedFunction},







>













|
|


|
|
|
|
















|
|
|
|
|
|
|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "jni.h"
#include "cc_squirreljme_emulator_NativeBinding.h"
#include "cc_squirreljme_jvm_Assembly.h"
#include "squirreljme.h"

// Method handler for special functions
JNIEXPORT void JNICALL doNothing(JNIEnv* env, jclass classy);
JNIEXPORT jint JNICALL doNothingZeroI(JNIEnv* env, jclass classy);
JNIEXPORT void JNICALL notImplemented(JNIEnv* env, jclass classy);
JNIEXPORT void JNICALL restrictedFunction(JNIEnv* env, jclass classy);

// Glue for putting names together
#define GLUE_NAME(name) Java_cc_squirreljme_jvm_Assembly_sysCall##name

// Assembly method mappings
static const JNINativeMethod assemblyMethods[] =
{
	{"arrayLength", "(J)I", (void*)restrictedFunction},
	{"arrayLength", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"arrayLengthSet", "(JI)V", (void*)restrictedFunction},
	{"arrayLengthSet", "(Ljava/lang/Object;I)V", (void*)restrictedFunction},
	{"atomicCompareGetAndSet", "(IIJ)I", (void*)restrictedFunction},
	{"atomicDecrementAndGet", "(J)I", (void*)restrictedFunction},
	{"atomicIncrement", "(J)V", (void*)restrictedFunction},
	{"breakpoint", "()V", (void*)restrictedFunction},
	{"classInfoOfBoolean", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfBooleanPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfByte", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfBytePointer", "()J", (void*)restrictedFunction},
	{"classInfoOfCharacter", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfCharacterPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfDouble", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfDoublePointer", "()J", (void*)restrictedFunction},
	{"classInfoOfFloat", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfFloatPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfInteger", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfIntegerPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfLong", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfLongPointer", "()J", (void*)restrictedFunction},
	{"classInfoOfShort", "()Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"classInfoOfShortPointer", "()J", (void*)restrictedFunction},
	{"doublePack", "(II)D", (void*)restrictedFunction},
	{"doubleToRawLongBits", "(D)J", (void*)restrictedFunction},
	{"doubleUnpackHigh", "(D)I", (void*)restrictedFunction},
	{"doubleUnpackLow", "(D)I", (void*)restrictedFunction},
	{"exceptionHandle", "()V", (void*)restrictedFunction},
	{"floatToRawIntBits", "(F)I", (void*)restrictedFunction},
	{"intBitsToFloat", "(I)F", (void*)restrictedFunction},
	{"invoke", "(JJ)V", (void*)restrictedFunction},
	{"invoke", "(JJI)V", (void*)restrictedFunction},
	{"invoke", "(JJII)V", (void*)restrictedFunction},
	{"invoke", "(JJIII)V", (void*)restrictedFunction},
	{"invoke", "(JJIIII)V", (void*)restrictedFunction},
	{"invoke", "(JJIIIII)V", (void*)restrictedFunction},
	{"invoke", "(JJIIIIII)V", (void*)restrictedFunction},
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
	{"invokeVL", "(JJII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIIIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIIIIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIIIIIII)J", (void*)restrictedFunction},
	{"longBitsToDouble", "(J)D", (void*)notImplemented},
	{"longPack", "(II)J", (void*)Java_cc_squirreljme_jvm_Assembly_longPack},
	{"longUnpackHigh", "(J)I", (void*)Java_cc_squirreljme_jvm_Assembly_longUnpackHigh},
	{"longUnpackLow", "(J)I", (void*)Java_cc_squirreljme_jvm_Assembly_longUnpackLow},
	{"memReadByte", "(JI)I", (void*)notImplemented},
	{"memReadInt", "(JI)I", (void*)notImplemented},
	{"memReadJavaInt", "(JI)I", (void*)notImplemented},
	{"memReadJavaLong", "(JI)J", (void*)notImplemented},
	{"memReadJavaShort", "(JI)I", (void*)notImplemented},
	{"memReadPointer", "(JI)J", (void*)notImplemented},
	{"memReadShort", "(JI)I", (void*)notImplemented},
	{"memWriteByte", "(JII)V", (void*)notImplemented},
	{"memWriteInt", "(JII)V", (void*)notImplemented},
	{"memWriteJavaInt", "(JII)V", (void*)notImplemented},
	{"memWriteJavaLong", "(JIJ)V", (void*)notImplemented},
	{"memWriteJavaShort", "(JII)V", (void*)notImplemented},
	{"memWritePointer", "(JIJ)V", (void*)notImplemented},
	{"memWriteShort", "(JII)V", (void*)notImplemented},
	{"monitorCountDecrementAndGetAtomic", "(J)I", (void*)restrictedFunction},
	{"monitorCountDecrementAndGetAtomic", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"monitorCountIncrementAndGetAtomic", "(J)I", (void*)restrictedFunction},
	{"monitorCountIncrementAndGetAtomic", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"monitorCountGetAtomic", "(J)I", (void*)restrictedFunction},
	{"monitorCountGetAtomic", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"monitorCountSetAtomic", "(JI)V", (void*)restrictedFunction},







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
	{"invokeVL", "(JJII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIIIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIIIIII)J", (void*)restrictedFunction},
	{"invokeVL", "(JJIIIIIIII)J", (void*)restrictedFunction},
	{"longBitsToDouble", "(J)D", (void*)restrictedFunction},
	{"longPack", "(II)J", (void*)restrictedFunction},
	{"longUnpackHigh", "(J)I", (void*)restrictedFunction},
	{"longUnpackLow", "(J)I", (void*)restrictedFunction},
	{"memReadByte", "(JI)I", (void*)restrictedFunction},
	{"memReadInt", "(JI)I", (void*)restrictedFunction},
	{"memReadJavaInt", "(JI)I", (void*)restrictedFunction},
	{"memReadJavaLong", "(JI)J", (void*)restrictedFunction},
	{"memReadJavaShort", "(JI)I", (void*)restrictedFunction},
	{"memReadPointer", "(JI)J", (void*)restrictedFunction},
	{"memReadShort", "(JI)I", (void*)restrictedFunction},
	{"memWriteByte", "(JII)V", (void*)restrictedFunction},
	{"memWriteInt", "(JII)V", (void*)restrictedFunction},
	{"memWriteJavaInt", "(JII)V", (void*)restrictedFunction},
	{"memWriteJavaLong", "(JIJ)V", (void*)restrictedFunction},
	{"memWriteJavaShort", "(JII)V", (void*)restrictedFunction},
	{"memWritePointer", "(JIJ)V", (void*)restrictedFunction},
	{"memWriteShort", "(JII)V", (void*)restrictedFunction},
	{"monitorCountDecrementAndGetAtomic", "(J)I", (void*)restrictedFunction},
	{"monitorCountDecrementAndGetAtomic", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"monitorCountIncrementAndGetAtomic", "(J)I", (void*)restrictedFunction},
	{"monitorCountIncrementAndGetAtomic", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"monitorCountGetAtomic", "(J)I", (void*)restrictedFunction},
	{"monitorCountGetAtomic", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"monitorCountSetAtomic", "(JI)V", (void*)restrictedFunction},
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
	{"objectGetClassInfo", "(Ljava/lang/Object;)Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"objectGetClassInfoPointer", "(J)J", (void*)restrictedFunction},
	{"objectGetClassInfoPointer", "(Ljava/lang/Object;)J", (void*)restrictedFunction},
	{"objectSetClassInfo", "(JJ)V", (void*)restrictedFunction},
	{"objectSetClassInfo", "(Ljava/lang/Object;J)V", (void*)restrictedFunction},
	{"objectSetClassInfo", "(JLcc/squirreljme/jvm/ClassInfo;)V", (void*)restrictedFunction},
	{"objectSetClassInfo", "(Ljava/lang/Object;Lcc/squirreljme/jvm/ClassInfo;)V", (void*)restrictedFunction},
	{"objectToPointer", "(Ljava/lang/Object;)J", (void*)Java_cc_squirreljme_jvm_Assembly_objectToPointer},
	{"objectToPointerRefQueue", "(Ljava/lang/Object;)J", (void*)Java_cc_squirreljme_jvm_Assembly_objectToPointer},
	{"pointerToObject", "(J)Ljava/lang/Object;", (void*)Java_cc_squirreljme_jvm_Assembly_pointerToObject},
	{"pointerToClassInfo", "(J)Lcc/squirreljme/jvm/ClassInfo;", (void*)Java_cc_squirreljme_jvm_Assembly_pointerToObject},
	{"poolLoad", "(JI)J", (void*)restrictedFunction},
	{"poolLoad", "(Ljava/lang/Object;I)J", (void*)restrictedFunction},
	{"poolStore", "(JIJ)V", (void*)restrictedFunction},
	{"poolStore", "(Ljava/lang/Object;IJ)V", (void*)restrictedFunction},
	{"refCount", "(J)V", (void*)doNothing},
	{"refCount", "(Ljava/lang/Object;)V", (void*)doNothing},
	{"refGetCount", "(J)I", (void*)restrictedFunction},
	{"refGetCount", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"refSetCount", "(JI)V", (void*)restrictedFunction},
	{"refSetCount", "(Ljava/lang/Object;I)V", (void*)restrictedFunction},
	{"refUncount", "(J)V", (void*)doNothing},
	{"refUncount", "(Ljava/lang/Object;)V", (void*)doNothing},
	{"returnFrame", "()V", (void*)notImplemented},
	{"returnFrame", "(I)V", (void*)notImplemented},
	{"returnFrame", "(II)V", (void*)notImplemented},
	{"returnFrameLong", "(J)V", (void*)notImplemented},
	{"sizeOfBaseArray", "()I", (void*)notImplemented},
	{"sizeOfBaseObject", "()I", (void*)notImplemented},
	{"sizeOfPointer", "()I", (void*)notImplemented},
	{"specialGetExceptionRegister", "()Ljava/lang/Object;", (void*)restrictedFunction},
	{"specialGetExceptionRegisterThrowable", "()Ljava/lang/Throwable;", (void*)restrictedFunction},
	{"specialGetExceptionRegisterPointer", "()J", (void*)restrictedFunction},
	{"specialGetPoolRegister", "()Ljava/lang/Object;", (void*)restrictedFunction},
	{"specialGetPoolRegisterPointer", "()J", (void*)restrictedFunction},
	{"specialGetReturnRegister", "()I", (void*)restrictedFunction},
	{"specialGetReturnRegisterLong", "()J", (void*)restrictedFunction},







|
|
|
|




|
|




|
|
|
|
|
|
|
|
|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
	{"objectGetClassInfo", "(Ljava/lang/Object;)Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"objectGetClassInfoPointer", "(J)J", (void*)restrictedFunction},
	{"objectGetClassInfoPointer", "(Ljava/lang/Object;)J", (void*)restrictedFunction},
	{"objectSetClassInfo", "(JJ)V", (void*)restrictedFunction},
	{"objectSetClassInfo", "(Ljava/lang/Object;J)V", (void*)restrictedFunction},
	{"objectSetClassInfo", "(JLcc/squirreljme/jvm/ClassInfo;)V", (void*)restrictedFunction},
	{"objectSetClassInfo", "(Ljava/lang/Object;Lcc/squirreljme/jvm/ClassInfo;)V", (void*)restrictedFunction},
	{"objectToPointer", "(Ljava/lang/Object;)J", (void*)restrictedFunction},
	{"objectToPointerRefQueue", "(Ljava/lang/Object;)J", (void*)restrictedFunction},
	{"pointerToObject", "(J)Ljava/lang/Object;", (void*)restrictedFunction},
	{"pointerToClassInfo", "(J)Lcc/squirreljme/jvm/ClassInfo;", (void*)restrictedFunction},
	{"poolLoad", "(JI)J", (void*)restrictedFunction},
	{"poolLoad", "(Ljava/lang/Object;I)J", (void*)restrictedFunction},
	{"poolStore", "(JIJ)V", (void*)restrictedFunction},
	{"poolStore", "(Ljava/lang/Object;IJ)V", (void*)restrictedFunction},
	{"refCount", "(J)V", (void*)restrictedFunction},
	{"refCount", "(Ljava/lang/Object;)V", (void*)restrictedFunction},
	{"refGetCount", "(J)I", (void*)restrictedFunction},
	{"refGetCount", "(Ljava/lang/Object;)I", (void*)restrictedFunction},
	{"refSetCount", "(JI)V", (void*)restrictedFunction},
	{"refSetCount", "(Ljava/lang/Object;I)V", (void*)restrictedFunction},
	{"refUncount", "(J)V", (void*)restrictedFunction},
	{"refUncount", "(Ljava/lang/Object;)V", (void*)restrictedFunction},
	{"returnFrame", "()V", (void*)restrictedFunction},
	{"returnFrame", "(I)V", (void*)restrictedFunction},
	{"returnFrame", "(II)V", (void*)restrictedFunction},
	{"returnFrameLong", "(J)V", (void*)restrictedFunction},
	{"sizeOfBaseArray", "()I", (void*)restrictedFunction},
	{"sizeOfBaseObject", "()I", (void*)restrictedFunction},
	{"sizeOfPointer", "()I", (void*)restrictedFunction},
	{"specialGetExceptionRegister", "()Ljava/lang/Object;", (void*)restrictedFunction},
	{"specialGetExceptionRegisterThrowable", "()Ljava/lang/Throwable;", (void*)restrictedFunction},
	{"specialGetExceptionRegisterPointer", "()J", (void*)restrictedFunction},
	{"specialGetPoolRegister", "()Ljava/lang/Object;", (void*)restrictedFunction},
	{"specialGetPoolRegisterPointer", "()J", (void*)restrictedFunction},
	{"specialGetReturnRegister", "()I", (void*)restrictedFunction},
	{"specialGetReturnRegisterLong", "()J", (void*)restrictedFunction},
266
267
268
269
270
271
272


273
274
275






	env->ThrowNew(env->FindClass("java/lang/Error"),
		__func__);
}

JNIEXPORT jint JNICALL Java_cc_squirreljme_emulator_NativeBinding__1_1bindMethods
	(JNIEnv* env, jclass classy)
{


	return env->RegisterNatives(env->FindClass("cc/squirreljme/jvm/Assembly"),
		assemblyMethods, sizeof(assemblyMethods) / sizeof(JNINativeMethod));
}













>
>
|

|
>
>
>
>
>
>
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
	env->ThrowNew(env->FindClass("java/lang/Error"),
		__func__);
}

JNIEXPORT jint JNICALL Java_cc_squirreljme_emulator_NativeBinding__1_1bindMethods
	(JNIEnv* env, jclass classy)
{
	jint rv = 0;

	rv |= env->RegisterNatives(env->FindClass("cc/squirreljme/jvm/Assembly"),
		assemblyMethods, sizeof(assemblyMethods) / sizeof(JNINativeMethod));

	rv |= mleRuntimeInit(env, classy);
	rv |= mleObjectInit(env, classy);
	rv |= mleTerminalInit(env, classy);

	return rv;
}

Added emulators/emulator-base/src/main/headers/cc_squirreljme_jvm_mle_ObjectShelf.h.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cc_squirreljme_jvm_mle_ObjectShelf */

#ifndef _Included_cc_squirreljme_jvm_mle_ObjectShelf
#define _Included_cc_squirreljme_jvm_mle_ObjectShelf
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cc_squirreljme_jvm_mle_ObjectShelf
 * Method:    arrayLength
 * Signature: (Ljava/lang/Object;)I
 */
JNIEXPORT jint JNICALL Java_cc_squirreljme_jvm_mle_ObjectShelf_arrayLength
  (JNIEnv *, jclass, jobject);

/*
 * Class:     cc_squirreljme_jvm_mle_ObjectShelf
 * Method:    arrayNew
 * Signature: (Lcc/squirreljme/jvm/mle/brackets/TypeBracket;I)Ljava/lang/Object;
 */
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_mle_ObjectShelf_arrayNew
  (JNIEnv *, jclass, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

Added emulators/emulator-base/src/main/headers/cc_squirreljme_jvm_mle_RuntimeShelf.h.



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cc_squirreljme_jvm_mle_RuntimeShelf */

#ifndef _Included_cc_squirreljme_jvm_mle_RuntimeShelf
#define _Included_cc_squirreljme_jvm_mle_RuntimeShelf
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cc_squirreljme_jvm_mle_RuntimeShelf
 * Method:    encoding
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_cc_squirreljme_jvm_mle_RuntimeShelf_encoding
  (JNIEnv *, jclass);

/*
 * Class:     cc_squirreljme_jvm_mle_RuntimeShelf
 * Method:    lineEnding
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_cc_squirreljme_jvm_mle_RuntimeShelf_lineEnding
  (JNIEnv *, jclass);

/*
 * Class:     cc_squirreljme_jvm_mle_RuntimeShelf
 * Method:    locale
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_cc_squirreljme_jvm_mle_RuntimeShelf_locale
  (JNIEnv *, jclass);

/*
 * Class:     cc_squirreljme_jvm_mle_RuntimeShelf
 * Method:    vmType
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_cc_squirreljme_jvm_mle_RuntimeShelf_vmType
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

Added emulators/emulator-base/src/main/headers/cc_squirreljme_jvm_mle_TerminalShelf.h.











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cc_squirreljme_jvm_mle_TerminalShelf */

#ifndef _Included_cc_squirreljme_jvm_mle_TerminalShelf
#define _Included_cc_squirreljme_jvm_mle_TerminalShelf
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cc_squirreljme_jvm_mle_TerminalShelf
 * Method:    flush
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_cc_squirreljme_jvm_mle_TerminalShelf_flush
  (JNIEnv *, jclass, jint);

/*
 * Class:     cc_squirreljme_jvm_mle_TerminalShelf
 * Method:    write
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_cc_squirreljme_jvm_mle_TerminalShelf_write__II
  (JNIEnv *, jclass, jint, jint);

/*
 * Class:     cc_squirreljme_jvm_mle_TerminalShelf
 * Method:    write
 * Signature: (I[BII)I
 */
JNIEXPORT jint JNICALL Java_cc_squirreljme_jvm_mle_TerminalShelf_write__I_3BII
  (JNIEnv *, jclass, jint, jbyteArray, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

Added emulators/emulator-base/src/main/headers/squirreljme.h.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* -*- Mode: C++; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// -------------------------------------------------------------------------*/

#ifndef __SQUIRRELJME_H__
#define __SQUIRRELJME_H__

#include "jni.h"

jint JNICALL mleRuntimeInit(JNIEnv* env, jclass classy);
jint JNICALL mleObjectInit(JNIEnv* env, jclass classy);
jint JNICALL mleTerminalInit(JNIEnv* env, jclass classy);

#endif /* __SQUIRRELJME_H__ */

Changes to emulators/emulator-base/src/main/java/cc/squirreljme/emulator/EmulatorAssembly.java.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package cc.squirreljme.emulator;

import cc.squirreljme.emulator.fb.NativeFramebuffer;
import cc.squirreljme.jvm.SystemCallError;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.jvm.config.ConfigRomKey;
import cc.squirreljme.jvm.config.ConfigRomType;
import cc.squirreljme.jvm.config.LineEndingType;
import java.io.IOException;
import java.io.OutputStream;

/**
 * This contains the implementation of some system calls in the event that the
 * JNI emulation layer does not have a C-based implementation of a method.
 *







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package cc.squirreljme.emulator;

import cc.squirreljme.emulator.fb.NativeFramebuffer;
import cc.squirreljme.jvm.SystemCallError;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.jvm.config.ConfigRomKey;
import cc.squirreljme.jvm.config.ConfigRomType;
import cc.squirreljme.jvm.mle.constants.LineEndingType;
import java.io.IOException;
import java.io.OutputStream;

/**
 * This contains the implementation of some system calls in the event that the
 * JNI emulation layer does not have a C-based implementation of a method.
 *
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
	 * @param __h Argument.
	 * @return The result.
	 * @since 2020/02/26
	 */
	public static long systemCall(short __si, int __a, int __b,
		int __c, int __d, int __e, int __f, int __g, int __h)
	{
		// We need the context for thread based info
		EmulatorThreadContext context = EmulatorAssembly.threadContext();
		
		// Depends on the system call
		switch (__si)
		{
				// System calls that are supported?
			case SystemCallIndex.QUERY_INDEX:
				{
					// Always succeeds
					context.setError(__si, 0);
					
					// Depends on the system call requested
					switch (__a)
					{
							// Implemented here
						case SystemCallIndex.CONFIG_GET_TYPE:
						case SystemCallIndex.CONFIG_GET_VALUE:
						case SystemCallIndex.ERROR_GET:
						case SystemCallIndex.ERROR_SET:
						case SystemCallIndex.FRAMEBUFFER:
						case SystemCallIndex.QUERY_INDEX:
						case SystemCallIndex.PD_OF_STDERR:
						case SystemCallIndex.PD_OF_STDOUT:
						case SystemCallIndex.PD_WRITE_BYTE:
						case SystemCallIndex.TIME_MILLI_WALL:
						case SystemCallIndex.TIME_NANO_MONO:
							return 1;
						
							// Not-implemented
						default:
							return 0;
					}
				}
				
				// Get configuration type
			case SystemCallIndex.CONFIG_GET_TYPE:
				switch (__a)
				{
					case ConfigRomKey.LINE_ENDING:
						return ConfigRomType.INTEGER;
					
					default:
						context.setError(__si,
							SystemCallError.NO_SUCH_CONFIG_KEY);
						return 0;
				}
			
				// Get raw value
			case SystemCallIndex.CONFIG_GET_VALUE:
				switch (__a)
				{
					case ConfigRomKey.LINE_ENDING:
						switch (System.getProperty("line.separator"))
						{
							case "\r":		return LineEndingType.CR;
							case "\r\n":	return LineEndingType.CRLF;
							case "\n":		return LineEndingType.LF;
							default:		return LineEndingType.UNSPECIFIED;
						}
						
					default:
						context.setError(__si,
							SystemCallError.NO_SUCH_CONFIG_KEY);
						return 0;
				}
			
				// Get error
			case SystemCallIndex.ERROR_GET:
				{
					context.setError(__si, 0);
					
					return context.getError((short)__a);
				}
			
				// Set error
			case SystemCallIndex.ERROR_SET:
				{
					context.setError(__si, 0);
					
					int oldError = context.getError((short)__a);
					context.setError((short)__a, __b);
					return oldError;
				}
			
				// Access the framebuffer
			case SystemCallIndex.FRAMEBUFFER:
				return NativeFramebuffer.getInstance().systemCall(context,
					__a, __b, __c, __d, __e, __f, __g, __h);
				
				// Descriptor of standard error
			case SystemCallIndex.PD_OF_STDERR:
				context.setError(__si, 0);
				return 2;
				
				// Descriptor of standard output
			case SystemCallIndex.PD_OF_STDOUT:
				context.setError(__si, 0);
				return 1;
				
				// Write byte
			case SystemCallIndex.PD_WRITE_BYTE:
				{
					OutputStream pipe = (__a == 2 ? System.err :
						(__a == 1 ? System.out : null));
					
					if (pipe != null)
					{
						try
						{
							pipe.write(__b);
							context.setError(__si, 0);
							
							return 1;
						}
						catch (IOException e)
						{
							context.setError(__si,
								SystemCallError.PIPE_DESCRIPTOR_BAD_WRITE);
							
							return 0;
						}
					}
					else
					{
						context.setError(__si,
							SystemCallError.PIPE_DESCRIPTOR_INVALID);
						return 0;
					}
				}
				
				// Current wall clock
			case SystemCallIndex.TIME_MILLI_WALL:
				{
					context.setError(__si, 0);
					
					return System.currentTimeMillis();
				}
			
				// Current monotonic clock
			case SystemCallIndex.TIME_NANO_MONO:
				{
					context.setError(__si, 0);
					
					return System.nanoTime();
				}
			
				// Un-handled, set as not supported and return a default value
			default:
				// Debug
				System.err.printf(
					"SysCall?: %d(%d, %d, %d, %d, %d, %d, %d, %d)%n",
					__si, __a, __b, __c, __d, __e, __f, __g, __h);
				
				// Set error
				context.setError(__si,
					SystemCallError.UNSUPPORTED_SYSTEM_CALL);
				return 0;
		}
	}
	
	/**
	 * Returns the current thread context.
	 *
	 * @return The thread context.
	 * @since 2020/02/26







<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







53
54
55
56
57
58
59


60




























































































































































61
62
63
64
65
66
67
	 * @param __h Argument.
	 * @return The result.
	 * @since 2020/02/26
	 */
	public static long systemCall(short __si, int __a, int __b,
		int __c, int __d, int __e, int __f, int __g, int __h)
	{


		throw new Error("Invalid Emulator System Call");




























































































































































	}
	
	/**
	 * Returns the current thread context.
	 *
	 * @return The thread context.
	 * @since 2020/02/26

Changes to emulators/emulator-base/src/main/java/cc/squirreljme/emulator/NativeBinding.java.

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
				e.addSuppressed(f);
			}
			
			throw new RuntimeException("Could not copy native library.", e);
		}
		
		// Attempt cleanup at shutdown.
		final Path[] paths = new Path[]{libFile, tempDir};
		Runtime.getRuntime().addShutdownHook(new Thread(() ->
			{
				try
				{
					for (Path p : paths)
						Files.delete(p);
				}
				catch (IOException e)
				{
				}
			}, "SquirrelJME-LibraryCleanupThread"));
		
		// Try loading the library now
		System.load(libFile.toString());
		
		// Bind methods
		if (NativeBinding.__bindMethods() != 0)
			throw new RuntimeException("Could not bind methods!");







<
|
<
<
<
<
<
<
<
<
<
|







80
81
82
83
84
85
86

87









88
89
90
91
92
93
94
95
				e.addSuppressed(f);
			}
			
			throw new RuntimeException("Could not copy native library.", e);
		}
		
		// Attempt cleanup at shutdown.

		Runtime.getRuntime().addShutdownHook(









			new PathCleanup(libFile, tempDir));
		
		// Try loading the library now
		System.load(libFile.toString());
		
		// Bind methods
		if (NativeBinding.__bindMethods() != 0)
			throw new RuntimeException("Could not bind methods!");

Added emulators/emulator-base/src/main/java/cc/squirreljme/emulator/PathCleanup.java.













































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.emulator;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * Cleanup for paths.
 *
 * @since 2020/06/22
 */
public final class PathCleanup
	extends Thread
{
	/** The paths to clear. */
	private final Path[] _paths;
	
	/**
	 * Cleans up the paths.
	 * 
	 * @param __paths The paths to clear.
	 * @since 2020/06/22
	 */
	public PathCleanup(Path... __paths)
	{
		this._paths = (__paths == null ? new Path[0] : __paths.clone());
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public final void run()
	{
		for (Path p : this._paths)
			try
			{
				Files.delete(p);
			}
			catch (IOException ignored)
			{
			}
	}
}

Changes to emulators/emulator-base/src/main/java/cc/squirreljme/emulator/profiler/ProfiledFrame.java.

57
58
59
60
61
62
63



64
65
66
67
68
69
70
	private long _currentstart =
		Long.MIN_VALUE;
	
	/** Current time sub-frame started execution, to remove self time. */
	private long _currentsubstart =
		Long.MIN_VALUE;
	



	/**
	 * Initializes this frame.
	 *
	 * @param __l The frame location.
	 * @param __d The depth of this frame.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/11







>
>
>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
	private long _currentstart =
		Long.MIN_VALUE;
	
	/** Current time sub-frame started execution, to remove self time. */
	private long _currentsubstart =
		Long.MIN_VALUE;
	
	/** The current in-call count for this frame. */
	private int _inCallCount;
	
	/**
	 * Initializes this frame.
	 *
	 * @param __l The frame location.
	 * @param __d The depth of this frame.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/11
97
98
99
100
101
102
103



104
105
106
107
108
109
110
			
		// {@squirreljme.error AH02 Cannot enter frame that is in an invoke.}
		if (this._currentsubstart != Long.MIN_VALUE)
			throw new IllegalStateException("AH02");
		
		// Mark time
		this._currentstart = __ns;



	}
	
	/**
	 * Indicates that the frame has been exited.
	 *
	 * @param __ns The time of the exit.
	 * @return The time spent in this frame, in total, self time, and CPU







>
>
>







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
			
		// {@squirreljme.error AH02 Cannot enter frame that is in an invoke.}
		if (this._currentsubstart != Long.MIN_VALUE)
			throw new IllegalStateException("AH02");
		
		// Mark time
		this._currentstart = __ns;
		
		// Increase call count
		this._inCallCount++;
	}
	
	/**
	 * Indicates that the frame has been exited.
	 *
	 * @param __ns The time of the exit.
	 * @return The time spent in this frame, in total, self time, and CPU
139
140
141
142
143
144
145




146
147
148
149











150
151
152
153
154
155
156
		// And only this frame time
		this._frameruntime += self;
		this._framecputime += self;
		
		// Clear these for next time
		this._currentstart = Long.MIN_VALUE;
		this._subtractself = 0;




		
		// Return both times since they may be useful
		return new long[]{total, self, total};
	}











	
	/**
	 * Indicates that this frame is no longer invoking some other method.
	 *
	 * @param __ns The ending nanoseconds.
	 * @return The time which has passed.
	 * @throws IllegalStateException If the frame is not in an invoke.







>
>
>
>




>
>
>
>
>
>
>
>
>
>
>







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
		// And only this frame time
		this._frameruntime += self;
		this._framecputime += self;
		
		// Clear these for next time
		this._currentstart = Long.MIN_VALUE;
		this._subtractself = 0;
		
		// Lower the in-call count, make sure it never goes below zero
		if ((--this._inCallCount) < 0)
			this._inCallCount = 0;
		
		// Return both times since they may be useful
		return new long[]{total, self, total};
	}
	
	/**
	 * Returns the number of times this frame is currently in a call.
	 *
	 * @return The number of times this frame is considered in a call.
	 * @since 2020/06/17
	 */
	public final int inCallCount()
	{
		return this._inCallCount;
	}
	
	/**
	 * Indicates that this frame is no longer invoking some other method.
	 *
	 * @param __ns The ending nanoseconds.
	 * @return The time which has passed.
	 * @throws IllegalStateException If the frame is not in an invoke.

Changes to emulators/emulator-base/src/main/java/cc/squirreljme/emulator/vm/VMFactory.java.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.emulator.vm;

import cc.squirreljme.emulator.profiler.ProfilerSnapshot;
import cc.squirreljme.runtime.cldc.Poking;
import cc.squirreljme.runtime.swm.EntryPoints;
import cc.squirreljme.vm.JarClassLibrary;
import cc.squirreljme.vm.NameOverrideClassLibrary;
import cc.squirreljme.vm.VMClassLibrary;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.stream.Stream;
import net.multiphasicapps.tool.manifest.JavaManifest;

/**
 * This class is used to initialize virtual machines based on a set of factory
 * classes.
 *
 * This was added because there were many cases where tons of code was
 * duplicated to initialize the virtual machine, which were effectively







<





<






<










<







8
9
10
11
12
13
14

15
16
17
18
19

20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.emulator.vm;

import cc.squirreljme.emulator.profiler.ProfilerSnapshot;
import cc.squirreljme.runtime.cldc.Poking;

import cc.squirreljme.vm.JarClassLibrary;
import cc.squirreljme.vm.NameOverrideClassLibrary;
import cc.squirreljme.vm.VMClassLibrary;
import java.io.File;
import java.io.IOException;

import java.io.OutputStream;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import java.util.Arrays;
import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.stream.Stream;


/**
 * This class is used to initialize virtual machines based on a set of factory
 * classes.
 *
 * This was added because there were many cases where tons of code was
 * duplicated to initialize the virtual machine, which were effectively
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
		// -Xemulator:(vm)
		// -Xsnapshot:(path-to-nps)
		// -Xlibraries:(class:path:...)
		// -Dsysprop=value
		// -classpath (class:path:...)
		// Main-class
		// Arguments...
		Deque<String> queue = new ArrayDeque<>(Arrays.<String>asList(__args));
		while (!queue.isEmpty())
		{
			// End of our items?
			String item = queue.peekFirst();
			if (item == null || item.isEmpty() || item.charAt(0) != '-')
				break;
			







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
		// -Xemulator:(vm)
		// -Xsnapshot:(path-to-nps)
		// -Xlibraries:(class:path:...)
		// -Dsysprop=value
		// -classpath (class:path:...)
		// Main-class
		// Arguments...
		Deque<String> queue = new LinkedList<>(Arrays.<String>asList(__args));
		while (!queue.isEmpty())
		{
			// End of our items?
			String item = queue.peekFirst();
			if (item == null || item.isEmpty() || item.charAt(0) != '-')
				break;
			
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

428
429
430
431
432
433
434
		if (!__path.endsWith("*"))
		{
			__files.add(__path);
			return;
		}
		
		// Try searching for JAR files in a directory
		try (Stream<Path> stream = Files.walk(
			Paths.get(__path.substring(0, __path.length() - 1)), 1,
			FileVisitOption.FOLLOW_LINKS))
		{
			stream.forEach(__scan ->
				{
					String fn = __scan.getFileName().toString();
					if (fn.endsWith(".jar") || fn.endsWith(".JAR"))
						__files.add(__scan.toString());
				});

		}
		catch (IOException e)
		{
			throw new RuntimeException(String.format(
				"Could not load wildcard JARs: %s", __path), e);
		}
	}







|
<
<

<
<
|
<
|
<
>







407
408
409
410
411
412
413
414


415


416

417

418
419
420
421
422
423
424
425
		if (!__path.endsWith("*"))
		{
			__files.add(__path);
			return;
		}
		
		// Try searching for JAR files in a directory
		try


		{


			Path startPath = Paths.get(

				__path.substring(0, __path.length() - 1));

			Files.walkFileTree(startPath, new __JarWalker__(__files));
		}
		catch (IOException e)
		{
			throw new RuntimeException(String.format(
				"Could not load wildcard JARs: %s", __path), e);
		}
	}

Added emulators/emulator-base/src/main/java/cc/squirreljme/emulator/vm/__JarWalker__.java.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.emulator.vm;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;

/**
 * Walks the file tree for wildcard JARs.
 *
 * @since 2020/06/22
 */
public final class __JarWalker__
	extends SimpleFileVisitor<Path>
{
	/** Where to place found files. */
	private final Collection<String> _files;
	
	/**
	 * Initializes the Jar walker.
	 * 
	 * @param __files The files to write to.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/22
	 */
	public __JarWalker__(Collection<String> __files)
		throws NullPointerException
	{
		if (__files == null)
			throw new NullPointerException("NARG");
		
		this._files = __files;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public FileVisitResult visitFile(Path __path, BasicFileAttributes __attrib)
		throws IOException
	{
		// If this is a JAR, we will grab it
		String fn = __path.getFileName().toString();
		if (fn.endsWith(".jar") || fn.endsWith(".JAR"))
			this._files.add(__path.toString());
		
		// The default way is to just handle it
		return super.visitFile(__path, __attrib);
	}
}

Changes to emulators/springcoat-vm/build.gradle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
plugins
{
	id "java-library"
}

description = "This is a SpringCoat virtual machine which " +
	"is an unoptimized pure interpreter aimed for the purpose of being an " +
	"educational stepping stone to other future virtual machines."

dependencies
{
	api project(":emulators:emulator-base")

	api project(":modules:cldc-compact")
	api project(":modules:tool-classfile")
	api project(":modules:tool-manifest-reader")
	api project(":modules:meep-swm")
	api project(":modules:meep-midlet")
	api project(":modules:common-vm")
	api project(":modules:collections")
}












|

|
<

|
|
<

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18

19
plugins
{
	id "java-library"
}

description = "This is a SpringCoat virtual machine which " +
	"is an unoptimized pure interpreter aimed for the purpose of being an " +
	"educational stepping stone to other future virtual machines."

dependencies
{
	api project(":emulators:emulator-base")
	
	api project(":modules:cldc-compact")
	api project(":modules:common-vm")

	api project(":modules:meep-swm")
	api project(":modules:tool-classfile")
	api project(":modules:tool-manifest-reader")

}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/AbstractGhostObject.java.

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.brackets.RefLinkHolder;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;

/**
 * This is the base for ghost objects which do not have a defined class type
 * or anything associated with a class object.
 *
 * @since 2020/05/30
 */
public abstract class AbstractGhostObject
	implements SpringObject
{
	/**
	 * {@inheritDoc}
	 * @since 2020/05/30
	 */
	@Override
	public final SpringMonitor monitor()
	{
		throw new SpringVirtualMachineException(
			"Ghost objects cannot have monitors: " + this.toString());
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/05/31
	 */
	@Override
	public RefLinkHolder refLink()
	{
		throw new SpringVirtualMachineException(
			"Ghost objects cannot have refLinks: " + this.toString());
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/05/30
	 */
	@Override
	public final SpringClass type()
	{
		throw new SpringVirtualMachineException(
			"Ghost objects cannot have types: " + this.toString());
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/GlobalState.java.

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Contains virtual machine global state.
 *
 * @since 2020/05/30
 */
public final class GlobalState
{
	/** Ticker for atomic values. */
	public static final AtomicInteger TICKER =
		new AtomicInteger();
	
	/** The GC lock. */
	public static final AtomicInteger GC_LOCK =
		new AtomicInteger();
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEAtomic.java.















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.AtomicShelf;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;

/**
 * Functions for {@link AtomicShelf}.
 *
 * @since 2020/06/18
 */
public enum MLEAtomic
	implements MLEFunction
{
	/** {@link AtomicShelf#gcLock()}. */
	GC_LOCK("gcLock:()I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			// Generate a key which will be returned in the lock
			int key = (int)MLEAtomic.TICK.handle(__thread);
			
			// When unlocked the lock will have zero, so we can set it to the
			// key we generated... otherwise we fail here
			if (GlobalState.GC_LOCK.compareAndSet(0, key))
				return key;
			return 0;
		}
	},
	
	/** {@link AtomicShelf#gcUnlock(int)}. */
	GC_UNLOCK("gcUnlock:(I)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			// Unlocking is simple and only works if we have the key used to
			// lock the garbage collector
			if (!GlobalState.GC_LOCK.compareAndSet((int)__args[0], 0))
				throw new SpringMLECallError("Wrong lock code.");
			
			return null;
		}
	},
	
	/** {@link AtomicShelf#spinLock(int)}. */
	SPIN_LOCK("spinLock:(I)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			int count = (int)__args[0];
			
			if (count < 0)
				throw new SpringMLECallError("Negative spin count.");
			
			// If we spin for too long, instead give up our cycles
			if (count > MLEAtomic._SPIN_LIMIT)
				Thread.yield();
			
			return null;
		}
	},
	
	/** {@link AtomicShelf#tick()}. */
	TICK("tick:()I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return GlobalState.TICKER.decrementAndGet();
		}
	},
	
	/* End. */
	;
	
	/** How many times to spin before yielding. */
	private static final int _SPIN_LIMIT =
		8;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEAtomic(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEDebug.java.





















































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.DebugShelf;
import cc.squirreljme.jvm.mle.brackets.TracePointBracket;
import cc.squirreljme.runtime.cldc.debug.CallTraceElement;
import cc.squirreljme.vm.springcoat.brackets.TracePointObject;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;

/**
 * Functions for {@link DebugShelf}.
 *
 * @since 2020/06/18
 */
public enum MLEDebug
	implements MLEFunction
{
	/** {@link DebugShelf#getThrowableTrace(Throwable)}. */
	GET_THROWABLE_TRACE("getThrowableTrace:(Ljava/lang/Throwable;)" +
		"[Lcc/squirreljme/jvm/mle/brackets/TracePointBracket;")
	{
		/**
		 * {@inheritDoc
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringObject object = (SpringObject)__args[0];
			
			// Must be throwable type
			if (!(object instanceof SpringSimpleObject) ||
				object.type().isAssignableFrom(
				__thread.resolveClass("java/lang/Throwable")))
				throw new SpringMLECallError("Not a Throwable.");
			
			return ((SpringSimpleObject)object).fieldByNameAndType(
				false, "_stack",
				"[Lcc/squirreljme/jvm/mle/brackets/TracePointBracket;")
				.get();
		}
	},
	
	/** {@link DebugShelf#pointAddress(TracePointBracket)}. */
	POINT_ADDRESS("pointAddress:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TracePointBracket;)J")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEDebug.__trace(__args[0]).getTrace().address();
		}
	},
	
	/** {@link DebugShelf#pointClass(TracePointBracket)} .*/
	POINT_CLASS("pointClass:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TracePointBracket;)Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.asVMObject(MLEDebug.__trace(__args[0])
				.getTrace().className());
		}
	},
	
	/** {@link DebugShelf#pointFile(TracePointBracket)}. */
	POINT_FILE("pointFile:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TracePointBracket;)Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.asVMObject(MLEDebug.__trace(__args[0])
				.getTrace().file());
		}
	},
	
	/** {@link DebugShelf#pointJavaAddress(TracePointBracket)}. */
	POINT_JAVA_ADDRESS("pointJavaAddress:(Lcc/squirreljme/jvm/mle/" +
		"brackets/TracePointBracket;)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEDebug.__trace(__args[0]).getTrace().byteCodeAddress();
		}
	},
	
	/** {@link DebugShelf#pointJavaOperation(TracePointBracket)}. */
	POINT_JAVA_OPERATION("pointJavaOperation:(Lcc/squirreljme/jvm/mle/" +
		"brackets/TracePointBracket;)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEDebug.__trace(__args[0]).getTrace()
				.byteCodeInstruction();
		}
	},
	
	/** {@link DebugShelf#pointLine(TracePointBracket)}. */
	POINT_LINE("pointLine:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TracePointBracket;)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEDebug.__trace(__args[0]).getTrace().line();
		}
	},
	
	/** {@link DebugShelf#pointMethodName(TracePointBracket)}. */
	POINT_METHOD_NAME("pointMethodName:(Lcc/squirreljme/jvm/mle/" +
		"brackets/TracePointBracket;)Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.asVMObject(MLEDebug.__trace(__args[0])
				.getTrace().methodName());
		}
	},
	
	/** {@link DebugShelf#pointMethodType(TracePointBracket)}. */
	POINT_METHOD_TYPE( "pointMethodType:(Lcc/squirreljme/jvm/mle/" +
		"brackets/TracePointBracket;)Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.asVMObject(MLEDebug.__trace(__args[0])
				.getTrace().methodDescriptor());
		}
	},
	
	/** {@link DebugShelf#traceStack()}. */
	TRACE_STACK("traceStack:()" +
		"[Lcc/squirreljme/jvm/mle/brackets/TracePointBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			CallTraceElement[] trace = __thread.thread.getStackTrace();
			
			int n = trace.length;
			TracePointObject[] rv = new TracePointObject[n];
			
			for (int i = 0; i < n; i++)
				rv[i] = new TracePointObject(trace[i]);
			
			return __thread.asVMObjectArray(__thread.loadClass(
				"[Lcc/squirreljme/jvm/mle/brackets/TracePointBracket;"),
				rv);
		}
	}
	
	/* End. */
	;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEDebug(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
	
	/**
	 * Checks if this is a trace point object.
	 * 
	 * @param __object The object to check.
	 * @return As a trace point if this is one.
	 * @throws SpringMLECallError If this is not a trace point object.
	 * @since 2020/06/22
	 */
	static TracePointObject __trace(Object __object)
		throws SpringMLECallError
	{
		if (!(__object instanceof TracePointObject))
			throw new SpringMLECallError("Not a trace point.");
		
		return (TracePointObject)__object; 
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEDispatcher.java.



















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.AtomicShelf;
import cc.squirreljme.jvm.mle.DebugShelf;
import cc.squirreljme.jvm.mle.JarPackageShelf;
import cc.squirreljme.jvm.mle.MathShelf;
import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.ReferenceShelf;
import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.TerminalShelf;
import cc.squirreljme.jvm.mle.ThreadShelf;
import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.util.Map;
import java.util.TreeMap;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.MethodNameAndType;

/**
 * Not Described.
 *
 * @since 2020/06/18
 */
public enum MLEDispatcher
	implements MLEDispatcherKey
{
	/** {@link AtomicShelf}. */
	ATOMIC("cc/squirreljme/jvm/mle/AtomicShelf",
		MLEAtomic.values()),
	
	/** {@link DebugShelf}. */
	DEBUG("cc/squirreljme/jvm/mle/DebugShelf",
		MLEDebug.values()),
	
	/** {@link JarPackageShelf}. */
	JAR_PACKAGE("cc/squirreljme/jvm/mle/JarPackageShelf",
		MLEJarPackage.values()),
	
	/** {@link MathShelf}. */
	MATH("cc/squirreljme/jvm/mle/MathShelf",
		MLEMath.values()),
	
	/** {@link ObjectShelf}. */
	OBJECT("cc/squirreljme/jvm/mle/ObjectShelf",
		MLEObject.values()),
	
	/** {@link ReferenceShelf}. */
	REFERENCE("cc/squirreljme/jvm/mle/ReferenceShelf",
		MLEReference.values()),
	
	/** {@link RuntimeShelf}. */
	RUNTIME("cc/squirreljme/jvm/mle/RuntimeShelf",
		MLERuntime.values()),
	
	/** {@link TerminalShelf}. */
	TERMINAL("cc/squirreljme/jvm/mle/TerminalShelf",
		MLETerminal.values()),
	
	/** {@link ThreadShelf}. */
	THREAD("cc/squirreljme/jvm/mle/ThreadShelf",
		MLEThread.values()),
	
	/** {@link TypeShelf}. */
	TYPE("cc/squirreljme/jvm/mle/TypeShelf",
		MLEType.values()),
	
	/* End. */
	;
	
	/** The function tree. */
	private static Map<String, Map<String, MLEDispatcherTarget>> _fnTree;
	
	/** The dispatcher key. */
	protected final String key;
	
	/** The functions. */
	private final MLEFunction[] _functions;
	
	static
	{
		Map<String, Map<String, MLEDispatcherTarget>> functionTree =
			new TreeMap<>();
		
		// Build the function tree
		for (MLEDispatcher dispatch : MLEDispatcher.values())
		{
			Map<String, MLEDispatcherTarget> subTree = new TreeMap<>();
			
			for (MLEFunction function : dispatch._functions)
				subTree.put(function.key(), function);
			
			functionTree.put(dispatch.key(), subTree);
		}
		
		MLEDispatcher._fnTree = functionTree;
	}
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @param __functions Functions for the dispatcher.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEDispatcher(String __key, MLEFunction[] __functions)
		throws NullPointerException
	{
		if (__key == null || __functions == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
		this._functions = __functions;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
	
	/**
	 * Handles the dispatching of the native method.
	 *
	 * @param __thread The current thread this is acting under.
	 * @param __class The native class being called.
	 * @param __func The method being called.
	 * @param __args The arguments to the call.
	 * @return The resulting object returned by the dispatcher.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/05/30
	 */
	public static Object dispatch(SpringThreadWorker __thread,
		ClassName __class, MethodNameAndType __func, Object... __args)
		throws NullPointerException
	{
		if (__thread == null || __class == null)
			throw new NullPointerException("NARG");
		
		// Find the sub-tree
		Map<String, MLEDispatcherTarget> subTree = MLEDispatcher._fnTree.get(
			__class.toString());
		if (subTree == null)
			throw new SpringVirtualMachineException(String.format(
				"Unknown MLE Shelf: %s", __class));
		
		// Find the target function
		MLEDispatcherTarget target = subTree.get(__func.toString());
		if (target == null)
			throw new SpringVirtualMachineException(String.format(
				"Unknown MLE Shelf Function: %s::%s", __class, __func));
		
		// Call it
		return target.handle(__thread, __args);
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEDispatcherKey.java.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

/**
 * This interface is used to represent keys for the dispatcher.
 *
 * @since 2020/06/18
 */
public interface MLEDispatcherKey
{
	/**
	 * Returns the key for the item.
	 *
	 * @return The key for the item.
	 * @since 2020/06/18
	 */
	String key();
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEDispatcherTarget.java.

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

/**
 * This represents a target for MLE dispatching.
 *
 * @since 2020/06/18
 */
public interface MLEDispatcherTarget
{
	/**
	 * Handles the MLE call.
	 *
	 * @param __thread The thread to dispatch.
	 * @param __args The arguments.
	 * @return The result of the call.
	 * @since 2020/06/18
	 */
	Object handle(SpringThreadWorker __thread, Object... __args);
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEFunction.java.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

/**
 * This represents a function in the MLE.
 *
 * @since 2020/06/18
 */
public interface MLEFunction
	extends MLEDispatcherKey, MLEDispatcherTarget
{
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEJarPackage.java.















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.JarPackageShelf;
import cc.squirreljme.jvm.mle.brackets.JarPackageBracket;
import cc.squirreljme.vm.VMClassLibrary;
import cc.squirreljme.vm.springcoat.brackets.JarPackageObject;
import cc.squirreljme.vm.springcoat.brackets.TracePointObject;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import net.multiphasicapps.classfile.MethodDescriptor;

/**
 * Functions for {@link JarPackageShelf}.
 *
 * @since 2020/06/18
 */
public enum MLEJarPackage
	implements MLEFunction
{
	/** {@link JarPackageShelf#classPath()}. */
	CLASS_PATH("classPath:()[Lcc/squirreljme/jvm/mle/brackets/" +
		"JarPackageBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			VMClassLibrary[] springPath = __thread.machine.classloader
				.classPath();
		
			// Wrap the classpath in package objects
			int n = springPath.length;
			SpringObject[] rv = new SpringObject[n];
			for (int i = 0; i < n; i++)
				rv[i] = new JarPackageObject(springPath[i]);
			
			// Wrap
			return __thread.asVMObjectArray(__thread.resolveClass(
				"[Lcc/squirreljme/jvm/mle/brackets/JarPackageBracket;"),
				rv);
		}
	},
	
	/** {@link JarPackageShelf#openResource(JarPackageBracket, String)}. */
	OPEN_RESOURCE("openResource:(Lcc/squirreljme/jvm/mle/brackets/" +
		"JarPackageBracket;Ljava/lang/String;)Ljava/io/InputStream;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			JarPackageObject jar = MLEJarPackage.__jarObject(__args[0]);
			
			String rcName = __thread.<String>asNativeObject(
				String.class, __args[1]);
			if (rcName == null)
				throw new SpringMLECallError("Null resource string.");
			
			// Locate the resource
			try (InputStream in = jar.library().resourceAsStream(rcName))
			{
				// Not found
				if (in == null)
					return SpringNullObject.NULL;
				
				// Copy everything to the a byte array, since it is easier to
				// handle resources without juggling special resource streams
				// and otherwise
				try (ByteArrayOutputStream baos = new ByteArrayOutputStream(
					Math.max(1024, in.available())))
				{
					// Copy all the data
					byte[] copy = new byte[4096];
					for (;;)
					{
						int rc = in.read(copy);
						
						if (rc < 0)
							break;
						
						baos.write(copy, 0, rc);
					}
					
					// Use this as the stream input
					return __thread.newInstance(__thread.loadClass(
						"java/io/ByteArrayInputStream"),
						new MethodDescriptor("([B)V"),
						__thread.asVMObject(baos.toByteArray()));
				}
			}
			
			// Could not read it
			catch (IOException e)
			{
				throw new SpringVirtualMachineException(
					"Failed to read resource", e);
			}
		}
	}
	
	/* End. */
	;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEJarPackage(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
	
	/**
	 * Checks if this is a {@link JarPackageObject}.
	 * 
	 * @param __object The object to check.
	 * @return As a jar if this is one.
	 * @throws SpringMLECallError If this is not a jar.
	 * @since 2020/06/22
	 */
	static JarPackageObject __jarObject(Object __object)
		throws SpringMLECallError
	{
		if (!(__object instanceof JarPackageObject))
			throw new SpringMLECallError("Not a JarPackageObject.");
		
		return (JarPackageObject)__object; 
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEMath.java.



























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.MathShelf;

/**
 * Functions for {@link MathShelf}.
 *
 * @since 2020/06/18
 */
public enum MLEMath
	implements MLEFunction
{
	/** {@link MathShelf#rawDoubleToLong(double)}. */
	RAW_DOUBLE_TO_LONG("rawDoubleToLong:(D)J")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return Double.doubleToRawLongBits((double)__args[0]);
		}
	},
	
	/** {@link MathShelf#rawFloatToInt(float)}. */
	RAW_FLOAT_TO_INT("rawFloatToInt:(F)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return Float.floatToRawIntBits((float)__args[0]);
		}
	},
	
	/** {@link MathShelf#rawIntToFloat(int)}. */
	RAW_INT_TO_FLOAT("rawIntToFloat:(I)F")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return Float.intBitsToFloat((int)__args[0]);
		}
	},
	
	/** {@link MathShelf#rawLongToDouble(long)}. */
	RAW_LONG_TO_DOUBLE("rawLongToDouble:(J)D")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return Double.longBitsToDouble((long)__args[0]);
		}
	},
	
	/* End. */
	;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEMath(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEObject.java.





















































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.brackets.TypeBracket;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;
import net.multiphasicapps.classfile.MethodDescriptor;

/**
 * Functions for {@link MLEObject}.
 *
 * @since 2020/06/18
 */
public enum MLEObject
	implements MLEFunction
{
	/** {@link ObjectShelf#arrayCopy(boolean[], int, boolean[], int, int)}. */
	ARRAY_COPY_BOOLEAN("arrayCopy:([ZI[ZII)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEObject.<SpringArrayObjectBoolean>__arrayCopy(
				SpringArrayObjectBoolean.class,
				__args[0], (int)__args[1],
				__args[2], (int)__args[3], (int)__args[4]);
			return null;
		}
	},
	
	/** {@link ObjectShelf#arrayCopy(byte[], int, byte[], int, int)}. */
	ARRAY_COPY_BYTE("arrayCopy:([BI[BII)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEObject.<SpringArrayObjectByte>__arrayCopy(
				SpringArrayObjectByte.class,
				__args[0], (int)__args[1],
				__args[2], (int)__args[3], (int)__args[4]);
			return null;
		}
	},
	
	/** {@link ObjectShelf#arrayCopy(short[], int, short[], int, int)}. */
	ARRAY_COPY_SHORT("arrayCopy:([SI[SII)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEObject.<SpringArrayObjectShort>__arrayCopy(
				SpringArrayObjectShort.class,
				__args[0], (int)__args[1],
				__args[2], (int)__args[3], (int)__args[4]);
			return null;
		}
	},
	
	/** {@link ObjectShelf#arrayCopy(char[], int, char[], int, int)}. */
	ARRAY_COPY_CHAR("arrayCopy:([CI[CII)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEObject.<SpringArrayObjectChar>__arrayCopy(
				SpringArrayObjectChar.class,
				__args[0], (int)__args[1],
				__args[2], (int)__args[3], (int)__args[4]);
			return null;
		}
	},
	
	/** {@link ObjectShelf#arrayCopy(int[], int, int[], int, int)}. */
	ARRAY_COPY_INTEGER("arrayCopy:([II[III)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEObject.<SpringArrayObjectInteger>__arrayCopy(
				SpringArrayObjectInteger.class,
				__args[0], (int)__args[1],
				__args[2], (int)__args[3], (int)__args[4]);
			return null;
		}
	},
	
	/** {@link ObjectShelf#arrayCopy(long[], int, long[], int, int)}. */
	ARRAY_COPY_LONG("arrayCopy:([JI[JII)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEObject.<SpringArrayObjectLong>__arrayCopy(
				SpringArrayObjectLong.class,
				__args[0], (int)__args[1],
				__args[2], (int)__args[3], (int)__args[4]);
			return null;
		}
	},
	
	/** {@link ObjectShelf#arrayCopy(float[], int, float[], int, int)}. */
	ARRAY_COPY_FLOAT("arrayCopy:([FI[FII)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEObject.<SpringArrayObjectFloat>__arrayCopy(
				SpringArrayObjectFloat.class,
				__args[0], (int)__args[1],
				__args[2], (int)__args[3], (int)__args[4]);
			return null;
		}
	},
	
	/** {@link ObjectShelf#arrayCopy(double[], int, double[], int, int)}. */
	ARRAY_COPY_DOUBLE("arrayCopy:([DI[DII)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEObject.<SpringArrayObjectDouble>__arrayCopy(
				SpringArrayObjectDouble.class,
				__args[0], (int)__args[1],
				__args[2], (int)__args[3], (int)__args[4]);
			return null;
		}
	},
	
	/** {@link ObjectShelf#arrayLength(Object)}. */
	ARRAY_LENGTH("arrayLength:(Ljava/lang/Object;)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringObject object = MLEType.__notNullObject(__args[0]);
			
			if (object instanceof SpringArrayObject)
				return ((SpringArrayObject)object).length();
			
			return -1;
		}
	},
	
	/** {@link ObjectShelf#arrayNew(TypeBracket, int)}. */
	ARRAY_NEW( "arrayNew:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;I)Ljava/lang/Object;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			int len = (int)__args[1];
			if (len < 0)
				throw new SpringMLECallError("Negative array size.");
			
			SpringClass type = MLEType.__type(__args[0]).getSpringClass();
			if (!type.isArray())
				throw new SpringMLECallError("Type not an array.");
			
			return __thread.allocateArray(type, len);
		}
	},
	
	/** {@link ObjectShelf#holdsLock(Thread, Object)}. */
	HOLDS_LOCK("holdsLock:(Ljava/lang/Thread;Ljava/lang/Object;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/27
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringThread vmThread = MLEThread.__vmThread(
				MLEThread.TO_VM_THREAD.handle(__thread, __args[0]))
				.getThread();
			SpringObject target = (SpringObject)__args[1];
			
			// Cannot be null
			if (target == null || target == SpringNullObject.NULL)
				throw new SpringMLECallError("Target object is null.");
			
			return target.monitor().isHeldBy(vmThread);
		}
	}, 
	
	/** {@link ObjectShelf#identityHashCode(Object)}. */
	IDENTITY_HASH_CODE("identityHashCode:(Ljava/lang/Object;)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringObject object = (SpringObject)__args[0];
			return System.identityHashCode(MLEType.__notNullObject(object));
		}
	},
	
	/** {@link ObjectShelf#newInstance(TypeBracket)}. */
	NEW_INSTANCE("newInstance:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)Ljava/lang/Object;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringClass type = MLEType.__type(__args[0]).getSpringClass();
			
			if (type.isArray())
				throw new SpringMLECallError("Cannot newInstance array");
			
			return __thread.newInstance(type, new MethodDescriptor("()V"));
		}
	},
	
	/** {@link ObjectShelf#notify(Object, boolean)}. */
	NOTIFY("notify:(Ljava/lang/Object;Z)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringObject target = MLEType.__notNullObject(__args[0]);
			boolean notifyAll = (int)__args[1] != 0; 
			
			// Signal the monitor
			return target.monitor().monitorNotify(__thread.thread, notifyAll);
		}
	},
	
	/** {@link ObjectShelf#wait(Object, long, int)}. */
	WAIT("wait:(Ljava/lang/Object;JI)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringObject target = MLEType.__notNullObject(__args[0]);
			long ms = (long)__args[1];
			int ns = (int)__args[2];
			
			return target.monitor().monitorWait(__thread.thread, ms, ns);
		}
	}, 
	
	/* End. */
	;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEObject(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
	
	/**
	 * Copies the given array.
	 * 
	 * @param <A> The SpringCoat array type.
	 * @param __classy The class type.
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The length.
	 * @throws SpringMLECallError If the input is not valid.
	 * @since 2020/06/22
	 */
	@SuppressWarnings("SuspiciousSystemArraycopy")
	static <A extends SpringArrayObject> void __arrayCopy(
		Class<A> __classy, Object __src, int __srcOff,
		Object __dest, int __destOff, int __len)
		throws SpringMLECallError
	{
		// Wrong array type
		if (!__classy.isInstance(__src) ||
			!__classy.isInstance(__dest))
			throw new SpringMLECallError("Null array.");
		
		if (__srcOff < 0 || __destOff < 0 || __len < 0)
			throw new SpringMLECallError("Negative offset or length.");
		
		// Try to copy
		try
		{
			System.arraycopy(((SpringArrayObject)__src).array(), __srcOff,
				((SpringArrayObject)__dest).array(), __destOff, __len);
		}
		
		// Not a valid copy
		catch (ArrayStoreException|IndexOutOfBoundsException|
			NullPointerException e)
		{
			throw new SpringMLECallError("Invalid copy.", e);
		}
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEReference.java.



































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.ReferenceShelf;
import cc.squirreljme.jvm.mle.brackets.RefLinkBracket;
import cc.squirreljme.vm.springcoat.brackets.RefLinkObject;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;

/**
 * Functions for {@link ReferenceShelf}.
 *
 * @since 2020/06/18
 */
public enum MLEReference
	implements MLEFunction
{
	/** {@link ReferenceShelf#deleteLink(RefLinkBracket)}. */
	DELETE_LINK("deleteLink:(Lcc/squirreljme/jvm/mle/brackets/" +
		"RefLinkBracket;)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			// Check it, but otherwise do nothing
			MLEReference.__refLink(__args[0]);
			
			return null;
		}
	},
	
	/** {@link ReferenceShelf#linkGetNext(RefLinkBracket)}. */
	LINK_GET_NEXT("linkGetNext:(Lcc/squirreljme/jvm/mle/brackets/" +
		"RefLinkBracket;)Lcc/squirreljme/jvm/mle/brackets/RefLinkBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEReference.__refLink(__args[0]).getNext();
		}
	},
	
	/** {@link ReferenceShelf#linkGetObject(RefLinkBracket)}. */
	LINK_GET_OBJECT("linkGetObject:(Lcc/squirreljme/jvm/mle/brackets/" +
		"RefLinkBracket;)Ljava/lang/Object;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEReference.__refLink(__args[0]).getObject();
		}
	},
	
	/** {@link ReferenceShelf#linkGetPrev(RefLinkBracket)}. */
	LINK_GET_PREV("linkGetPrev:(Lcc/squirreljme/jvm/mle/brackets/" +
		"RefLinkBracket;)Lcc/squirreljme/jvm/mle/brackets/RefLinkBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEReference.__refLink(__args[0]).getPrev();
		}
	},
	
	/** {@link ReferenceShelf#linkSetNext(RefLinkBracket, RefLinkBracket)}. */
	LINK_SET_NEXT("linkSetNext:(Lcc/squirreljme/jvm/mle/brackets/" +
		"RefLinkBracket;Lcc/squirreljme/jvm/mle/brackets/RefLinkBracket;)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEReference.__refLink(__args[0]).setNext(
				MLEReference.__refLink(__args[1]));
			return null;
		}
	},
	
	/** {@link ReferenceShelf#linkSetObject(RefLinkBracket, Object)}. */
	LINK_SET_OBJECT("linkSetObject:(Lcc/squirreljme/jvm/mle/brackets/" +
		"RefLinkBracket;Ljava/lang/Object;)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEReference.__refLink(__args[0])
				.setObject((SpringObject)__args[1]);
			return null;
		}
	},
	
	/** {@link ReferenceShelf#linkSetPrev(RefLinkBracket, RefLinkBracket)}. */
	LINK_SET_PREV("linkSetPrev:(Lcc/squirreljme/jvm/mle/brackets/" +
		"RefLinkBracket;Lcc/squirreljme/jvm/mle/brackets/RefLinkBracket;)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			MLEReference.__refLink(__args[0]).setPrev(
				MLEReference.__refLink(__args[1]));
			return null;
		}
	},
	
	/** {@link ReferenceShelf#newLink()}. */
	NEW_LINK("newLink:()Lcc/squirreljme/jvm/mle/brackets/" +
		"RefLinkBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new RefLinkObject();
		}
	},
	
	/** {@link ReferenceShelf#objectGet(Object)}. */
	OBJECT_GET("objectGet:(Ljava/lang/Object;)" +
		"Lcc/squirreljme/jvm/mle/brackets/RefLinkBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringObject object = (SpringObject)__args[0];
			if (!(object instanceof SpringSimpleObject))
				throw new SpringMLECallError("Invalid object"); 
			
			return object.refLink().get();
		}
	},
	
	/** {@link ReferenceShelf#objectSet(Object, RefLinkBracket)}. */
	OBJECT_SET("objectSet:(Ljava/lang/Object;" +
		"Lcc/squirreljme/jvm/mle/brackets/RefLinkBracket;)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringObject object = (SpringObject)__args[0];
			if (!(object instanceof SpringSimpleObject))
				throw new SpringMLECallError("Invalid object"); 
			
			object.refLink().set(MLEReference.__refLink(__args[1]));
			return null;
		}
	}
	
	/* End. */
	;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEReference(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
	
	/**
	 * Checks if this is a {@link RefLinkObject}.
	 * 
	 * @param __object The object to check.
	 * @return As a {@link RefLinkObject} if this is one.
	 * @throws SpringMLECallError If this is not a {@link RefLinkObject}.
	 * @since 2020/06/28
	 */
	static RefLinkObject __refLink(Object __object)
		throws SpringMLECallError
	{
		if (!(__object instanceof RefLinkObject))
			throw new SpringMLECallError("Not a RefLinkObject.");
		
		return (RefLinkObject)__object; 
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLERuntime.java.









































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.BuiltInEncodingType;
import cc.squirreljme.jvm.mle.constants.BuiltInLocaleType;
import cc.squirreljme.jvm.mle.constants.VMDescriptionType;
import cc.squirreljme.jvm.mle.constants.VMStatisticType;
import cc.squirreljme.jvm.mle.constants.VMType;
import cc.squirreljme.runtime.cldc.SquirrelJME;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.cldc.lang.LineEndingUtils;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;

/**
 * Functions for {@link MLERuntime}.
 *
 * @since 2020/06/18
 */
public enum MLERuntime
	implements MLEFunction
{
	/** {@link RuntimeShelf#currentTimeMillis()}. */
	CURRENT_TIME_MILLIS("currentTimeMillis:()J")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return System.currentTimeMillis();
		}
	},
	
	/** {@link RuntimeShelf#encoding()}. */
	ENCODING("encoding:()I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return BuiltInEncodingType.UTF8;
		}
	},
	
	/** {@link RuntimeShelf#exit(int)}. */
	EXIT("exit:(I)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			__thread.machine.exit((int)__args[0]);
			return null;
		}
	},
	
	/** {@link RuntimeShelf#lineEnding()}. */
	LINE_ENDING("lineEnding:()I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return LineEndingUtils.toType(
				System.getProperty("line.separator"));
		}
	},
	
	/** {@link RuntimeShelf#locale()}. */
	LOCALE("locale:()I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@SuppressWarnings("SwitchStatementWithTooFewBranches")
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			switch (System.getProperty("user.country"))
			{
				case "US":
					switch (System.getProperty("user.language"))
					{
						case "en":
							return BuiltInLocaleType.ENGLISH_US;
					}
					return BuiltInLocaleType.UNSPECIFIED;
				
				default:
					return BuiltInLocaleType.UNSPECIFIED;
			}
		}
	},
	
	/** {@link RuntimeShelf#nanoTime()}. */
	NANO_TIME("nanoTime:()J")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return System.nanoTime();
		}
	},
	
	/** {@link RuntimeShelf#systemProperty(String)}. */
	SYSTEM_PROPERTY("systemProperty:(Ljava/lang/String;)" +
		"Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			String key = __thread
				.<String>asNativeObject(String.class, __args[0]);
			
			if (key == null)
				throw new SpringMLECallError("Null key.");
			
			return __thread.machine._sysproperties.get(key);
		}
	},
	
	/** {@link RuntimeShelf#vmDescription(int)}. */
	VM_DESCRIPTION("vmDescription:(I)Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			int index = (int)__args[0];
			if (index < 0 || index >= VMDescriptionType.NUM_TYPES)
				throw new SpringMLECallError(
					"Index out of range: " + index);
			
			switch (index)
			{
				case VMDescriptionType.EXECUTABLE_PATH:
					return null;
				
				case VMDescriptionType.OS_ARCH:
					return "springcoat/" + System.getProperty("os.arch");
					
				case VMDescriptionType.OS_NAME:
					return System.getProperty("os.name");
				
				case VMDescriptionType.OS_VERSION:
					return System.getProperty("os.version");
				
				case VMDescriptionType.VM_EMAIL:
					return "xer@multiphasicapps.net";
					
				case VMDescriptionType.VM_NAME:
					return "SquirrelJME SpringCoat";
				
				case VMDescriptionType.VM_URL:
					return "https://squirreljme.cc/";
					
				case VMDescriptionType.VM_VENDOR:
					return "Stephanie Gawroriski";
				
				case VMDescriptionType.VM_VERSION:
					return SquirrelJME.RUNTIME_VERSION;
			}
			
			return null;
		}
	},
	
	/** {@link RuntimeShelf#vmStatistic(int)}. */
	VM_STATISTIC("vmStatistic:(I)J")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			int index = (int)__args[0];
			if (index < 0 || index >= VMStatisticType.NUM_STATISTICS)
				throw new SpringMLECallError(
					"Index out of range: " + index);
			
			switch (index)
			{
				case VMStatisticType.MEM_FREE:
					return Runtime.getRuntime().freeMemory();
					
				case VMStatisticType.MEM_MAX:
					return Runtime.getRuntime().maxMemory();
				
				case VMStatisticType.MEM_USED:
					return Runtime.getRuntime().totalMemory();
			}
			
			return 0L;
		}
	},
	
	/** {@link RuntimeShelf#vmType()}. */
	VM_TYPE("vmType:()I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return VMType.SPRINGCOAT;
		}
	},
	
	/* End. */
	;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLERuntime(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLETerminal.java.































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.TerminalShelf;
import cc.squirreljme.jvm.mle.constants.StandardPipeType;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Functions for {@link MLETerminal}.
 *
 * @since 2020/06/18
 */
public enum MLETerminal
	implements MLEFunction
{
	/** {@link TerminalShelf#flush(int)}. */
	FLUSH("flush:(I)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@SuppressWarnings("resource")
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			try
			{
				MLETerminal.__fdOutput((int)__args[0]).flush();
				return 1;
			}
			catch (IllegalArgumentException|IOException e)
			{
				return -1;
			}
		}
	},
	
	/** {@link TerminalShelf#write(int, int)}. */
	WRITE_BYTE("write:(II)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@SuppressWarnings("resource")
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			try
			{
				MLETerminal.__fdOutput((int)__args[0]).write((int)__args[1]);
				return 1;
			}
			catch (IllegalArgumentException|IOException e)
			{
				return -1;
			}
		}
	},
	
	/** {@link TerminalShelf#write(int, byte[], int, int)}. */
	WRITE_BYTES("write:(I[BII)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@SuppressWarnings("resource")
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			if (!(__args[1] instanceof SpringArrayObjectByte))
				throw new SpringMLECallError("Not a byte array.");
			
			SpringArrayObjectByte buf = (SpringArrayObjectByte)__args[1];
			int off = (int)__args[2];
			int len = (int)__args[3];
			
			// Perform basic bounds checking here
			if (off < 0 || len < 0 || (off + len) > buf.length)
				throw new SpringMLECallError("Index out of bounds.");
			
			try
			{
				MLETerminal.__fdOutput((int)__args[0])
					.write(buf.array(), off, len);
				return len;
			}
			catch (IllegalArgumentException|IOException e)
			{
				return -1;
			}
		}
	},
	
	/* End. */
	;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLETerminal(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
	
	/**
	 * Returns the output stream for the given descriptor.
	 *
	 * @param __fd The file descriptor.
	 * @return The output stream for it.
	 * @throws SpringMLECallError If the descriptor is not valid.
	 * @since 2020/06/13
	 */
	static OutputStream __fdOutput(int __fd)
		throws SpringMLECallError
	{
		switch (__fd)
		{
			case StandardPipeType.STDOUT:	return System.out;
			case StandardPipeType.STDERR:	return System.err;
			
			default:
				throw new SpringMLECallError("Unknown FD: " + __fd);
		}
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEThread.java.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.ThreadShelf;
import cc.squirreljme.jvm.mle.brackets.VMThreadBracket;
import cc.squirreljme.vm.springcoat.brackets.VMThreadObject;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.MethodNameAndType;

/**
 * Functions for {@link ThreadShelf}.
 *
 * @since 2020/06/18
 */
public enum MLEThread
	implements MLEFunction
{
	/** {@link ThreadShelf#aliveThreadCount(boolean, boolean)}. */
	ALIVE_THREAD_COUNT("aliveThreadCount:(ZZ)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			boolean includeMain = ((int)__args[0] != 0);
			boolean includeDaemon = ((int)__args[1] != 0);
			
			// Count every thread
			int count = 0;
			SpringMachine machine = __thread.machine;
			synchronized (machine)
			{
				for (SpringThread thread : machine.getThreads())
				{
					boolean isMain = thread.isMain();
					boolean isDaemon = thread.isDaemon();
					
					if ((includeMain && isMain) ||
						(includeDaemon && isDaemon) ||
						(!isMain && !isDaemon))
						count++;
				}
			}
			
			return count;
		}
	},
	
	/** {@link ThreadShelf#createVMThread(Thread)}. */
	CREATE_VM_THREAD( "createVMThread:(Ljava/lang/Thread;)Lcc/" +
		"squirreljme/jvm/mle/brackets/VMThreadBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringSimpleObject javaThread = MLEThread.__javaThread(__thread,
				__args[0]);
			
			// Find the thread which the given passed object is bound to, this
			// is the target thread
			SpringThread target = null;
			SpringMachine machine = __thread.machine;
			synchronized (machine)
			{
				// Search through every thread
				SpringThread[] threads = machine.getThreads();
				for (SpringThread thread : threads)
				{
					SpringObject instance;
					try
					{
						instance = thread.threadInstance();
					}
					catch (IllegalStateException ignored)
					{
						continue;
					}
					
					// If this is the thread for this, then use that!
					if (javaThread == instance)
					{
						target = thread;
						break;
					}
				}
				
				// If there is exactly one thread, we can rather get into a bit
				// of a loop where our main thread is created outside of normal
				// means by the VM and not by any other thread.. but only if
				// this initial thread has no actual instance
				if (threads.length == 1 && !threads[0].hasThreadInstance())
					target = threads[0];
				
				// No actual thread exists that the object is bound to, so
				// oops! We need to actually create one here and bind it
				// accordingly!
				if (target == null)
					target = machine.createThread(null, false);
			}
			
			// Create object with this attached thread
			VMThreadObject vmThread = new VMThreadObject(target);
			
			// The thread gets these as well
			target.setThreadInstance(javaThread);
			target.setVMThread(vmThread);
			
			return vmThread;
		}
	},
	
	/** {@link ThreadShelf#currentExitCode()}. */
	CURRENT_EXIT_CODE("currentExitCode:()I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.machine._exitcode;
		}
	},
	
	/** {@link ThreadShelf#currentJavaThread()}. */
	CURRENT_JAVA_THREAD("currentJavaThread:()Ljava/lang/Thread;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.thread.threadInstance();
		}
	},
	
	/** {@link ThreadShelf#javaThreadClearInterrupt(Thread)}. */
	JAVA_THREAD_CLEAR_INTERRUPT("javaThreadClearInterrupt:" +
		"(Ljava/lang/Thread;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/28
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringFieldStorage field = MLEThread.__javaThread(__thread,
				__args[0]).fieldByNameAndType(false, 
				"_interrupted", "Z");
			
			// Get and clear the field value
			Object old = field.get();
			field.set(false);
			return old;
		}
	}, 
	
	/** {@link ThreadShelf#javaThreadFlagStarted(Thread)}. */
	JAVA_THREAD_FLAG_STARTED("javaThreadFlagStarted:(Ljava/lang/" +
		"Thread;)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			// Just set the started field to true
			MLEThread.__javaThread(__thread, __args[0]).fieldByNameAndType(
				false, "_started", "Z").set(true);
			return null;
		}
	},
	
	/** {@link ThreadShelf#javaThreadIsStarted(Thread)}. */
	JAVA_THREAD_IS_STARTED("javaThreadIsStarted:(Ljava/lang/Thread;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			// Just get the state of the given field
			return MLEThread.__javaThread(__thread, __args[0])
				.fieldByNameAndType(false, 
					"_started", "Z").get();
		}
	},
	
	/** {@link ThreadShelf#javaThreadRunnable(Thread)}. */
	JAVA_THREAD_RUNNABLE("javaThreadRunnable:(Ljava/lang/Thread;)" +
		"Ljava/lang/Runnable;")
	{
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			// Just get the state of the given field
			return MLEThread.__javaThread(__thread, __args[0])
				.fieldByNameAndType(
				false, "_runnable",
				"Ljava/lang/Runnable;").get();
		}
	},
	
	/** {@link ThreadShelf#javaThreadSetAlive(Thread, boolean)}. */
	JAVA_THREAD_SET_ALIVE("javaThreadSetAlive:(Ljava/lang/Thread;Z)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			// Just set the started field to true
			MLEThread.__javaThread(__thread, __args[0]).fieldByNameAndType(
				false, "_isAlive", "Z")
				.set((int)__args[1] != 0);
			return null;
		}
	},
	
	/** {@link ThreadShelf#runProcessMain()}. */
	RUN_PROCESS_MAIN("runProcessMain:()V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			__thread.runProcessMain();
			return null;
		}
	},
	
	/** {@link ThreadShelf#setCurrentExitCode(int)}. */
	SET_CURRENT_EXIT_CODE("setCurrentExitCode:(I)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/27
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			int exitCode = (int)__args[0];
			
			__thread.machine.setExitCode(exitCode);
			
			return null;
		}
	}, 
	
	/** {@link ThreadShelf#sleep(int, int)}. */
	SLEEP("sleep:(II)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			int ms = (int)__args[0];
			int ns = (int)__args[1];
			
			if (ms < 0 || ns < 0 || ns > 1000000000)
				throw new SpringMLECallError("Out of range time.");
			
			if (ms == 0 && ns == 0)
				Thread.yield();
			else
				try
				{
					Thread.sleep(ms, ns);
				}
				catch (InterruptedException ignored)
				{
					return true;
				}
			
			return false;
		}
	},
	
	/** {@link ThreadShelf#toJavaThread(VMThreadBracket)}. */
	TO_JAVA_THREAD("toJavaThread:(Lcc/squirreljme/jvm/mle/" +
		"brackets/VMThreadBracket;)Ljava/lang/Thread;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			VMThreadObject vmThread = MLEThread.__vmThread(__args[0]);
			
			return vmThread.getThread().threadInstance();
		}
	}, 
	
	/** {@link ThreadShelf#toVMThread(Thread)}. */
	TO_VM_THREAD("toVMThread:(Ljava/lang/Thread;)Lcc/squirreljme/" +
		"jvm/mle/brackets/VMThreadBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEThread.__javaThread(__thread, __args[0]).fieldByField(
				__thread.resolveClass("java/lang/Thread")
				.lookupField(false, "_vmThread",
				"Lcc/squirreljme/jvm/mle/brackets/VMThreadBracket;"))
				.get();
		}
	},
	
	/** {@link ThreadShelf#vmThreadId(VMThreadBracket)}. */
	VM_THREAD_ID("vmThreadId:(Lcc/squirreljme/jvm/mle/brackets/" +
		"VMThreadBracket;)I")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEThread.__vmThread(__args[0]).getThread().id;
		}
	},
	
	/** {@link ThreadShelf#vmThreadInterrupt(VMThreadBracket)}. */ 
	VM_THREAD_INTERRUPT("vmThreadInterrupt:(Lcc/squirreljme/jvm/mle/" +
		"brackets/VMThreadBracket;)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/22
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			VMThreadObject vmThread = MLEThread.__vmThread(__args[0]);
			
			// Send an interrupt to the thread
			vmThread.getThread().hardInterrupt();
			
			return null;
		}
	},
	
	/** {@link ThreadShelf#vmThreadIsMain(VMThreadBracket)}. */
	VM_THREAD_IS_MAIN("vmThreadIsMain:(Lcc/squirreljme/jvm/mle/" +
		"brackets/VMThreadBracket;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEThread.__vmThread(__args[0]).getThread().isMain();
		}
	},
	
	/** {@link ThreadShelf#vmThreadSetPriority(VMThreadBracket, int)}. */
	VM_THREAD_SET_PRIORITY("vmThreadSetPriority:(Lcc/squirreljme/" +
		"jvm/mle/brackets/VMThreadBracket;I)V")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringThread thread = MLEThread.__vmThread(__args[0]).getThread();
			int priority = (int)__args[1];
			
			if (priority < Thread.MIN_PRIORITY ||
				priority > Thread.MAX_PRIORITY)
				throw new SpringMLECallError(
					"Thread priority out of range.");
			
			// Try to set the priority
			try
			{
				thread._worker.setPriority(priority);
			}
			catch (IllegalArgumentException|SecurityException e)
			{
				throw new SpringMLECallError(
					"Could not set priority.", e);
			}
			
			return null;
		}
	}, 
	
	/** {@link ThreadShelf#vmThreadStart(VMThreadBracket)}. */
	VM_THREAD_START("vmThreadStart:(Lcc/squirreljme/jvm/mle/brackets/" +
		"VMThreadBracket;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringThread target = MLEThread.__vmThread(__args[0]).getThread();
			
			// Create worker for thread and start it
			SpringThreadWorker worker = new SpringThreadWorker(
				__thread.machine, target, false);
			
			// Enter the base setup frame
			target.enterFrame(worker.loadClass(MLEThread._START_CLASS)
				.lookupMethod(true, MLEThread._BASE_THREAD_METHOD));
			
			// Try to start it
			try
			{
				worker.start();
				return true;
			}
			catch (IllegalThreadStateException ignored)
			{
				return false;
			}
		}
	},
	
	/** {@link ThreadShelf#waitForUpdate(int)}. */
	WAIT_FOR_UPDATE("waitForUpdate:(I)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			int ms = (int)__args[0];
			
			if (ms < 0)
				throw new SpringMLECallError("Negative milliseconds");
			
			// Waiting for nothing? just give up our slice
			if (ms == 0)
			{
				Thread.yield();
				return false;
			}
			
			// Wait until the monitor is hit
			SpringMachine machine = __thread.machine;
			synchronized (machine)
			{
				try
				{
					machine.wait(ms);
				}
				catch (InterruptedException e)
				{
					return true;
				}
			}
			
			// Assume not interrupted
			return false;
		}
	}, 
	
	/* End. */
	;
	
	/** The class which contains the thread starting point. */
	static final ClassName _START_CLASS =
		new ClassName("java/lang/__Start__");
	
	/** The method to enter for main threads. */
	static final MethodNameAndType _BASE_THREAD_METHOD =
		new MethodNameAndType("__base", "()V");
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEThread(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
	
	/**
	 * Checks if this is a Java thread.
	 * 
	 * @param __thread The context thread.
	 * @param __object The object to check.
	 * @return The verified object.
	 * @throws SpringMLECallError If {@code __object} is {@code null} or is
	 * not an instance of {@link Throwable}.
	 * @since 2020/06/28
	 */
	static SpringSimpleObject __javaThread(SpringThreadWorker __thread,
		Object __object)
		throws SpringMLECallError
	{
		if (__thread == null)
			throw new NullPointerException("NARG");
		
		if (!(__object instanceof SpringSimpleObject))
			throw new SpringMLECallError("Not a Java Thread");
		
		SpringSimpleObject rv = (SpringSimpleObject)__object;
		if (!rv.type().isAssignableFrom(
			__thread.resolveClass("java/lang/Thread")))
			throw new SpringMLECallError("Not instance of Thread.");
		
		return rv;
	}
	
	/**
	 * Ensures that this is a {@link VMThreadObject}.
	 * 
	 * @param __object The object to check.
	 * @return As a {@link VMThreadObject}.
	 * @throws SpringMLECallError If this is not one.
	 * @since 2020/06/27
	 */
	static VMThreadObject __vmThread(Object __object)
		throws SpringMLECallError
	{
		if (!(__object instanceof VMThreadObject))
			throw new SpringMLECallError("Not a VMThreadObject.");
		
		return (VMThreadObject)__object; 
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLEType.java.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.jvm.mle.brackets.TypeBracket;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.vm.springcoat.brackets.JarPackageObject;
import cc.squirreljme.vm.springcoat.brackets.TypeObject;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassNotFoundException;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;
import java.util.Objects;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.MethodNameAndType;
import net.multiphasicapps.classfile.PrimitiveType;

/**
 * Functions for {@link TypeShelf}.
 *
 * @since 2020/06/18
 */
public enum MLEType
	implements MLEFunction
{
	/** {@link TypeShelf#binaryName(TypeBracket)}. */
	BINARY_NAME("binaryName:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/27
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.asVMObject(MLEType.__type(__args[0])
				.getSpringClass().name().binaryName().toString());
		}
	}, 
	
	/** {@link TypeShelf#binaryPackageName(TypeBracket)}. */
	BINARY_PACKAGE_NAME("binaryPackageName:(Lcc/squirreljme/jvm/" +
		"mle/brackets/TypeBracket;)Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.asVMObject(MLEType.__type(__args[0])
				.getSpringClass().name().binaryName().inPackage()
				.toString());
		}
	},
	
	/** {@link TypeShelf#classToType(Class)}. */
	CLASS_TO_TYPE("classToType:(Ljava/lang/Class;)" +
		"Lcc/squirreljme/jvm/mle/brackets/TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEType.__simple(__args[0]).fieldByField(
				__thread.resolveClass(new ClassName("java/lang/Class"))
				.lookupField(false, "_type",
				"Lcc/squirreljme/jvm/mle/brackets/TypeBracket;")).get();
		}
	},
	
	/** {@link TypeShelf#component(TypeBracket)}. */
	COMPONENT("component:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)Lcc/squirreljme/jvm/mle/brackets/TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/28
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringClass type = MLEType.__type(__args[0]).getSpringClass();
			
			if (!type.isArray())
				throw new SpringMLECallError("Not an array type.");
			
			return new TypeObject(type.componentType());
		}
	},
	
	/** {@link TypeShelf#componentRoot(TypeBracket)}. */
	COMPONENT_ROOT("componentRoot:(Lcc/squirreljme/jvm/mle/" +
		"brackets/TypeBracket;)Lcc/squirreljme/jvm/mle/brackets/TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/28
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringClass type = MLEType.__type(__args[0]).getSpringClass();
			
			if (!type.isArray())
				throw new SpringMLECallError("Not an array type.");
			
			// Find the root component
			while (type.isArray())
				type = type.componentType();
			return new TypeObject(type);
		}
	},
	
	/** {@link TypeShelf#enumValues(TypeBracket)}. */
	ENUM_VALUES("enumValues:(Lcc/squirreljme/jvm/mle/" +
		"brackets/TypeBracket;)[Ljava/lang/Enum;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/28
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringClass type = MLEType.__type(__args[0]).getSpringClass();
			
			// Must be an enumeration
			if (!type.isEnum())
				throw new SpringMLECallError("Not an enumeration type");
			
			// Call the static values() method in the given class, it is
			// automatically generated by the Java compiler (it is synthetic)
			return __thread.invokeMethod(true, type.name(),
				new MethodNameAndType("values", 
					"()" + type.name().field().addDimensions(1)));
		}
	}, 
	
	/** {@link TypeShelf#equals(TypeBracket, TypeBracket)}. */
	EQUALS("equals:(Lcc/squirreljme/jvm/mle/brackets/TypeBracket;" +
		"Lcc/squirreljme/jvm/mle/brackets/TypeBracket;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return Objects.equals(
				MLEType.__type(__args[0]).getSpringClass(),
				MLEType.__type(__args[1]).getSpringClass());
		}
	},
	
	/** {@link TypeShelf#findType(String)}. */
	FIND_TYPE("findType:(Ljava/lang/String;)" +
		"Lcc/squirreljme/jvm/mle/brackets/TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringObject name = MLEType.__notNullObject(__args[0]);
			
			try
			{
				return new TypeObject(__thread.loadClass(
					__thread.<String>asNativeObject(String.class, name)));
			}
			
			// Since the method returns null when not found, we want to return
			// this here
			catch (SpringClassNotFoundException e)
			{
				return null;
			}
		}
	},
	
	/** {@link TypeShelf#inJar(TypeBracket)}. */
	IN_JAR("inJar:(Lcc/squirreljme/jvm/mle/brackets/TypeBracket;)" +
		"Lcc/squirreljme/jvm/mle/brackets/JarPackageBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new JarPackageObject(MLEType.__type(__args[0])
				.getSpringClass().inJar());
		}
	},
	
	/** {@link TypeShelf#interfaces(TypeBracket)}. */
	INTERFACES("interfaces:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)[Lcc/squirreljme/jvm/mle/brackets/TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/29
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringClass type = MLEType.__type(__args[0]).getSpringClass();
			
			SpringClass[] interfaces = type.interfaceClasses();
			int n = interfaces.length;
			
			SpringObject[] rv = new SpringObject[n];
			for (int i = 0; i < n; i++)
				rv[i] = new TypeObject(interfaces[i]);
			
			return __thread.asVMObjectArray(__thread.resolveClass(
				"[Lcc/squirreljme/jvm/mle/brackets/TypeBracket;"), rv);
		}
	}, 
	
	/** {@link TypeShelf#isArray(TypeBracket)}. */
	IS_ARRAY("isArray:(Lcc/squirreljme/jvm/mle/brackets/TypeBracket;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEType.__type(__args[0]).getSpringClass().isArray();
		}
	},
	
	/** {@link TypeShelf#isEnum(TypeBracket)}. */
	IS_ENUM("isEnum:(Lcc/squirreljme/jvm/mle/brackets/TypeBracket;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/28
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEType.__type(__args[0]).getSpringClass().isEnum();
		}
	},
	
	/** {@link TypeShelf#isInterface(TypeBracket)}. */
	IS_INTERFACE("isInterface:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEType.__type(__args[0]).getSpringClass().flags()
				.isInterface();
		}
	},
	
	/** {@link TypeShelf#isPrimitive(TypeBracket)}. */
	IS_PRIMITIVE("isPrimitive:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)Z")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEType.__type(__args[0]).getSpringClass().name()
				.isPrimitive();
		}
	},
	
	/** {@link TypeShelf#objectType(Object)}. */
	OBJECT_TYPE("objectType:(Ljava/lang/Object;)" +
		"Lcc/squirreljme/jvm/mle/brackets/TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				MLEType.__notNullObject(__args[0]).type().name().toString()));
		}
	},
	
	/** {@link TypeShelf#runtimeName(TypeBracket)}. */
	RUNTIME_NAME("runtimeName:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)Ljava/lang/String;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return MLEType.__type(__args[0]).getSpringClass()
				.name().toRuntimeString();
		}
	},
	
	/** {@link TypeShelf#superClass(TypeBracket)}. */
	SUPER_CLASS("superClass:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)Lcc/squirreljme/jvm/mle/brackets/TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			SpringClass superClass = MLEType.__type(__args[0]).getSpringClass()
				.superClass();
			
			if (superClass == null)
				return SpringNullObject.NULL;
			return new TypeObject(superClass);
		}
	},
	
	/** {@link TypeShelf#typeOfBoolean()}. */
	TYPE_OF_BOOLEAN("typeOfBoolean:()Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				ClassName.fromPrimitiveType(PrimitiveType.BOOLEAN)));
		}
	},
	
	/** {@link TypeShelf#typeOfByte()}. */
	TYPE_OF_BYTE("typeOfByte:()Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				ClassName.fromPrimitiveType(PrimitiveType.BYTE)));
		}
	},
	
	/** {@link TypeShelf#typeOfCharacter()}. */
	TYPE_OF_CHARACTER("typeOfCharacter:()Lcc/squirreljme/jvm/mle/" +
		"brackets/TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				ClassName.fromPrimitiveType(PrimitiveType.CHARACTER)));
		}
	},
	
	/** {@link TypeShelf#typeOfDouble()}. */
	TYPE_OF_DOUBLE("typeOfDouble:()Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				ClassName.fromPrimitiveType(PrimitiveType.DOUBLE)));
		}
	},
	
	/** {@link TypeShelf#typeOfFloat()}. */
	TYPE_OF_FLOAT("typeOfFloat:()Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				ClassName.fromPrimitiveType(PrimitiveType.FLOAT)));
		}
	},
	
	/** {@link TypeShelf#typeOfInteger()}. */
	TYPE_OF_INTEGER("typeOfInteger:()Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				ClassName.fromPrimitiveType(PrimitiveType.INTEGER)));
		}
	},
	
	/** {@link TypeShelf#typeOfLong()}. */
	TYPE_OF_LONG("typeOfLong:()Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				ClassName.fromPrimitiveType(PrimitiveType.LONG)));
		}
	},
	
	/** {@link TypeShelf#typeOfShort()}. */
	TYPE_OF_SHORT("typeOfShort:()Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return new TypeObject(__thread.loadClass(
				ClassName.fromPrimitiveType(PrimitiveType.SHORT)));
		}
	},
	
	/** {@link TypeShelf#typeToClass(TypeBracket)}. */
	TYPE_TO_CLASS("typeToClass:(Lcc/squirreljme/jvm/mle/brackets/" +
		"TypeBracket;)Ljava/lang/Class;")
	{
		/**
		 * {@inheritDoc}
		 * @since 2020/06/18
		 */
		@Override
		public Object handle(SpringThreadWorker __thread, Object... __args)
		{
			return __thread.asVMObject(MLEType.__type(__args[0])
				.getSpringClass());
		}
	},
	
	/* End. */
	;
	
	/** The dispatch key. */
	protected final String key;
	
	/**
	 * Initializes the dispatcher info.
	 *
	 * @param __key The key.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	MLEType(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		this.key = __key;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/18
	 */
	@Override
	public String key()
	{
		return this.key;
	}
	
	/**
	 * Checks if the object is {@code null}.
	 * 
	 * @param __object The object to check.
	 * @return The object.
	 * @throws SpringMLECallError If is null.
	 * @since 2020/06/22
	 */
	static SpringObject __notNullObject(Object __object)
		throws SpringMLECallError
	{
		if (__object == null || SpringNullObject.NULL == __object)
			throw new SpringMLECallError("Null object.");
		
		return (SpringObject)__object;
	}
	
	/**
	 * Checks if this is a simple object.
	 * 
	 * @param __object The object to check.
	 * @return The simple object.
	 * @throws SpringMLECallError If not a simple object.
	 * @since 2020/06/22
	 */
	static SpringSimpleObject __simple(Object __object)
	{
		if (!(__object instanceof SpringSimpleObject))
			throw new SpringMLECallError("Not a SpringSimpleObject.");
		
		return (SpringSimpleObject)__object; 
	}
	
	/**
	 * Checks if this is a {@link TypeObject}.
	 * 
	 * @param __object The object to check.
	 * @return As a {@link TypeObject} if this is one.
	 * @throws SpringMLECallError If this is not a {@link TypeObject}.
	 * @since 2020/06/22
	 */
	static TypeObject __type(Object __object)
		throws SpringMLECallError
	{
		if (!(__object instanceof TypeObject))
			throw new SpringMLECallError("Not a TypeObject.");
		
		return (TypeObject)__object; 
	}
}

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObject.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26




27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51

52
53
54
55




56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This is an object which acts as an array, which stores some kind of data.
 *
 * @since 2018/09/15
 */
public abstract class SpringArrayObject
	implements SpringObject
{
	/** The monitor for this array. */
	protected final SpringMonitor monitor =
		new SpringMonitor();




	
	/** The type of this object itself. */
	protected final SpringClass selftype;
	
	/** The component type. */
	protected final SpringClass component;
	
	/** The length of the array. */
	protected final int length;
	
	/** String representation. */
	private Reference<String> _string;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.

	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/09/15
	 */
	public SpringArrayObject(SpringClass __self, SpringClass __cl, int __l)
		throws NullPointerException

	{
		if (__self == null || __cl == null)
			throw new NullPointerException("NARG");
		




		// {@squirreljme.error BK01 Attempt to allocate an array of a
		// negative size. (The length requested)}
		if (__l < 0)
			throw new SpringNegativeArraySizeException(
				String.format("BK01 %d", __l));
		
		this.selftype = __self;
		this.component = __cl;
		this.length = __l;
	}
	
	/**
	 * Returns the raw backing array.
	 *
	 * @return The array.












>
>
>
>














>
>
>
>

















<

>




|
|
>

|


>
>
>
>







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.brackets.RefLinkHolder;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This is an object which acts as an array, which stores some kind of data.
 *
 * @since 2018/09/15
 */
public abstract class SpringArrayObject
	implements SpringObject
{
	/** The monitor for this array. */
	protected final SpringMonitor monitor =
		new SpringMonitor();
	
	/** The reference link holder. */
	protected final RefLinkHolder refLink =
		new RefLinkHolder();
	
	/** The type of this object itself. */
	protected final SpringClass selftype;
	
	/** The component type. */
	protected final SpringClass component;
	
	/** The length of the array. */
	protected final int length;
	
	/** String representation. */
	private Reference<String> _string;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws IllegalArgumentException If the type is not an array.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/09/15
	 */
	public SpringArrayObject(SpringClass __self, int __l)
		throws IllegalArgumentException, NullPointerException,
			SpringNegativeArraySizeException
	{
		if (__self == null)
			throw new NullPointerException("NARG");
		
		// The passed type must always be an array
		if (!__self.isArray())
			throw new IllegalArgumentException("Type not an array: " + __self);
		
		// {@squirreljme.error BK01 Attempt to allocate an array of a
		// negative size. (The length requested)}
		if (__l < 0)
			throw new SpringNegativeArraySizeException(
				String.format("BK01 %d", __l));
		
		this.selftype = __self;
		this.component = __self.componentType();
		this.length = __l;
	}
	
	/**
	 * Returns the raw backing array.
	 *
	 * @return The array.
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133


134








135
136
137
138
139
140
141
	 * @throws SpringArrayIndexOutOfBoundsException If the index is not within
	 * bounds.
	 * @since 2018/09/16
	 */
	public abstract void set(int __dx, Object __v)
		throws SpringArrayStoreException, SpringArrayIndexOutOfBoundsException;
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override
	public final SpringMonitor monitor()
	{
		return this.monitor;
	}
	
	/**
	 * Returns the length of this array.
	 *
	 * @return The array length.
	 * @since 2018/09/16
	 */
	public final int length()
	{
		return this.length;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final SpringPointerArea pointerArea()
	{


		throw new todo.TODO();








	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override







<
<
<
<
<
<
<
<
<
<













|


|

>
>
|
>
>
>
>
>
>
>
>







112
113
114
115
116
117
118










119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
	 * @throws SpringArrayIndexOutOfBoundsException If the index is not within
	 * bounds.
	 * @since 2018/09/16
	 */
	public abstract void set(int __dx, Object __v)
		throws SpringArrayStoreException, SpringArrayIndexOutOfBoundsException;
	










	/**
	 * Returns the length of this array.
	 *
	 * @return The array length.
	 * @since 2018/09/16
	 */
	public final int length()
	{
		return this.length;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override
	public final SpringMonitor monitor()
	{
		return this.monitor;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/05/31
	 */
	@Override
	public final RefLinkHolder refLink()
	{
		return this.refLink;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectBoolean.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





/**
 * Array backed by a boolean array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectBoolean
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final boolean[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectBoolean(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException
	{
		super(__self, __cl, __l);
		
		// Initialize elements
		this._elements = new boolean[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectBoolean(SpringClass __self, SpringClass __cl,
		boolean[] __a)
		throws NullPointerException
	{
		super(__self, __cl, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14












>
>
>
>















<





|
<


|














|
<


|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Array backed by a boolean array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectBoolean
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final boolean[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectBoolean(SpringClass __self, int __l)

		throws NullPointerException
	{
		super(__self, __l);
		
		// Initialize elements
		this._elements = new boolean[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectBoolean(SpringClass __self, boolean[] __a)

		throws NullPointerException
	{
		super(__self, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final boolean[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectByte.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





/**
 * Array backed by a byte array.
 *
 * @since 2018/11/04
 */
public final class SpringArrayObjectByte
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final byte[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/04
	 */
	public SpringArrayObjectByte(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException
	{
		super(__self, __cl, __l);
		
		// Initialize elements
		this._elements = new byte[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectByte(SpringClass __self, SpringClass __cl,
		byte[] __a)
		throws NullPointerException
	{
		super(__self, __cl, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14












>
>
>
>















<





|
<


|









<




|
<


|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Array backed by a byte array.
 *
 * @since 2018/11/04
 */
public final class SpringArrayObjectByte
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final byte[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/04
	 */
	public SpringArrayObjectByte(SpringClass __self, int __l)

		throws NullPointerException
	{
		super(__self, __l);
		
		// Initialize elements
		this._elements = new byte[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.

	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectByte(SpringClass __self, byte[] __a)

		throws NullPointerException
	{
		super(__self, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final byte[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectChar.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





/**
 * Array backed by a char array.
 *
 * @since 2018/11/04
 */
public final class SpringArrayObjectChar
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final char[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/04
	 */
	public SpringArrayObjectChar(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException
	{
		super(__self, __cl, __l);
		
		// Initialize elements
		this._elements = new char[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectChar(SpringClass __self, SpringClass __cl,
		char[] __a)
		throws NullPointerException
	{
		super(__self, __cl, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14












>
>
>
>















<





|
<


|









<




|
<


|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Array backed by a char array.
 *
 * @since 2018/11/04
 */
public final class SpringArrayObjectChar
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final char[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/04
	 */
	public SpringArrayObjectChar(SpringClass __self, int __l)

		throws NullPointerException
	{
		super(__self, __l);
		
		// Initialize elements
		this._elements = new char[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.

	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectChar(SpringClass __self, char[] __a)

		throws NullPointerException
	{
		super(__self, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final char[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectDouble.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





/**
 * Array backed by a double array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectDouble
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final double[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectDouble(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException
	{
		super(__self, __cl, __l);
		
		// Initialize elements
		this._elements = new double[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectDouble(SpringClass __self, SpringClass __cl,
		double[] __a)
		throws NullPointerException
	{
		super(__self, __cl, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14












>
>
>
>















<





|
<


|









<




|
<


|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Array backed by a double array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectDouble
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final double[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectDouble(SpringClass __self, int __l)

		throws NullPointerException
	{
		super(__self, __l);
		
		// Initialize elements
		this._elements = new double[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.

	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectDouble(SpringClass __self, double[] __a)

		throws NullPointerException
	{
		super(__self, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final double[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectFloat.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





/**
 * Array backed by a float array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectFloat
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final float[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectFloat(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException
	{
		super(__self, __cl, __l);
		
		// Initialize elements
		this._elements = new float[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectFloat(SpringClass __self, SpringClass __cl,
		float[] __a)
		throws NullPointerException
	{
		super(__self, __cl, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14












>
>
>
>















<





|
<


|









<




|
<


|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Array backed by a float array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectFloat
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final float[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectFloat(SpringClass __self, int __l)

		throws NullPointerException
	{
		super(__self, __l);
		
		// Initialize elements
		this._elements = new float[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.

	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectFloat(SpringClass __self, float[] __a)

		throws NullPointerException
	{
		super(__self, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final float[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectGeneric.java.

1
2
3
4
5
6
7
8
9
10
11
12

13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41

42
43
44







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

















86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107






108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

















126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;


import net.multiphasicapps.classfile.PrimitiveType;


/**
 * Generic array that can store any type.
 *
 * @since 2018/11/04
 */
public final class SpringArrayObjectGeneric
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final Object[] _elements;
	
	/** The last class which was checked for compatibility. */
	private SpringClass _lastvalid;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.

	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/09/15
	 */
	public SpringArrayObjectGeneric(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException

	{
		super(__self, __cl, __l);
		







		// Initialize elements
		Object[] elements;
		this._elements = (elements = new Object[__l]);
		
		// Determine the initial value to use
		PrimitiveType type = __cl.name().primitiveType();
		Object v;
		if (type == null)
			v = SpringNullObject.NULL;
		else
			switch (type)
			{
				case BOOLEAN:
				case BYTE:
				case SHORT:
				case CHARACTER:
				case INTEGER:
					v = Integer.valueOf(0);
					break;
				
				case LONG:
					v = Long.valueOf(0);
					break;
				
				case FLOAT:
					v = Float.valueOf(0);
					break;
				
				case DOUBLE:
					v = Double.valueOf(0);
					break;
				
				default:
					throw new todo.OOPS();
			}
		
		// Set all elements to an initial value depending on the type
		// Set all 
		for (int i = 0; i < __l; i++)
			elements[i] = v;
	}

















	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14
	 */
	@Override
	public final <C> C get(Class<C> __cl, int __dx)
		throws NullPointerException, SpringArrayIndexOutOfBoundsException
	{
		// Faster to just have the host VM do bounds check
		try
		{






			return __cl.cast(this._elements[__dx]);
		}
		
		// {@squirreljme.error BK0h Out of bounds access to array.
		// (The index; The length of the array)}
		catch (IndexOutOfBoundsException e)
		{
			throw new SpringArrayIndexOutOfBoundsException(
				String.format("BK0h %d %d", __dx, this.length), e);
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14
	 */
	@Override
	public final void set(int __dx, Object __v)

















		throws SpringArrayStoreException, SpringArrayIndexOutOfBoundsException
	{
		try
		{
			// This is a cached type for setting because an array of one type
			// will usually in most cases set with objects which are compatible
			// so the rather involved instanceof check will take awhile and
			// compound for setting single elements.
			SpringClass lastvalid = this._lastvalid,
				wouldset = null;
			
			// If the input value is an object
			boolean docheck;
			if (__v instanceof SpringObject)
			{
				// If a check is done, then 
				wouldset = ((SpringObject)__v).type();
				
				// Only if the types differ would we actually check
				docheck = (wouldset != lastvalid);
			}
			
			// Otherwise always do a check since we do not really know the
			// class type here
			else
				docheck = true;
			
			// Performing the check for cache?
			if (docheck)
			{
				// {@squirreljme.error BK0i The specified type is not
				// compatible with the values this array stores. (The input
				// value; The component type)}
				SpringClass component = this.component;
				if (!component.isCompatible(__v))
					throw new SpringArrayStoreException(String.format(
						"BK0i %s %s", __v, component));
				
				// Next validity check would be set if done on an object
				// Ignore setting it back to null, if one was previously
				// valid
				if (wouldset != null)
					this._lastvalid = wouldset;
			}
			
			// Set
			this._elements[__dx] = __v;
		}
		
		// {@squirreljme.error BK0j Out of bounds access to array. (The index;
		// The length of the array)}
		catch (IndexOutOfBoundsException e)
		{
			throw new SpringArrayIndexOutOfBoundsException(
				String.format("BK0j %d %d", __dx, this.length), e);
		}
	}
}













>
|
>










|


|





<

>




|
<
|
>

|

>
>
>
>
>
>
>

|
|


<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|















>
>
>
>
>
>
|













|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<

|












|
|



|












1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58



59


60
























61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

154



155












156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Generic array that can store any type.
 *
 * @since 2018/11/04
 */
public final class SpringArrayObjectGeneric
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final SpringObject[] _elements;
	
	/** The last class which was checked for compatibility. */
	private SpringClass _lastValid;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws IllegalArgumentException If the given type is primitive.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/09/15
	 */
	public SpringArrayObjectGeneric(SpringClass __self, int __l)

		throws IllegalArgumentException, NullPointerException,
			SpringNegativeArraySizeException
	{
		super(__self, __l);
		
		// Previously this was permitted, however since there are other more
		// optimal forms for arrays this is no longer needed to have a generic
		// array to store these values
		if (__self.componentType().name().primitiveType() != null)
			throw new IllegalArgumentException("Cannot have a generic " +
				"array of primitive types: " + __self);
		
		// Initialize elements
		SpringObject[] elements;
		this._elements = (elements = new SpringObject[__l]);
		
		// Determine the initial value to use



		SpringObject v = SpringNullObject.NULL;


		
























		// Set all elements to an initial value depending on the type

		for (int i = 0; i < __l; i++)
			elements[i] = v;
	}
	
	/**
	 * Wraps the given array as a generic array.
	 *
	 * @param __self The self type.
	 * @param __elements The array elements.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/13
	 */
	public SpringArrayObjectGeneric(SpringClass __self,
		SpringObject[] __elements)
		throws NullPointerException
	{
		super(__self, __elements.length);
		
		this._elements = __elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final SpringObject[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14
	 */
	@Override
	public final <C> C get(Class<C> __cl, int __dx)
		throws NullPointerException, SpringArrayIndexOutOfBoundsException
	{
		// Faster to just have the host VM do bounds check
		try
		{
			SpringObject rv = this._elements[__dx];
			
			// Always have the special null be used here
			if (rv == null)
				rv = SpringNullObject.NULL;
			
			return __cl.cast(rv);
		}
		
		// {@squirreljme.error BK0h Out of bounds access to array.
		// (The index; The length of the array)}
		catch (IndexOutOfBoundsException e)
		{
			throw new SpringArrayIndexOutOfBoundsException(
				String.format("BK0h %d %d", __dx, this.length), e);
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/13
	 */
	@Override
	public final void set(int __dx, Object __v)
		throws ClassCastException, SpringArrayStoreException,
			SpringArrayIndexOutOfBoundsException
	{
		this.set(__dx, (SpringObject)__v);
	}
	
	/**
	 * Sets the value in the array.
	 *
	 * @param __dx The index.
	 * @param __v The value to set.
	 * @throws SpringArrayStoreException If the type is not valid.
	 * @throws SpringArrayIndexOutOfBoundsException If the index is out of
	 * bounds.
	 * @since 2018/11/14
	 */
	public final void set(int __dx, SpringObject __v)
		throws SpringArrayStoreException, SpringArrayIndexOutOfBoundsException
	{
		try
		{
			// This is a cached type for setting because an array of one type
			// will usually in most cases set with objects which are compatible
			// so the rather involved instanceof check will take awhile and
			// compound for setting single elements.
			SpringClass lastValid = this._lastValid;

			SpringClass wouldSet = (__v == null ? null : __v.type());



			












			// Performing the check for cache?
			if (wouldSet != lastValid)
			{
				// {@squirreljme.error BK0i The specified type is not
				// compatible with the values this array stores. (The input
				// value; The component type)}
				SpringClass component = this.component;
				if (!component.isCompatible(__v))
					throw new SpringArrayStoreException(String.format(
						"BK0i %s %s", __v, component));
				
				// Next validity check would be set if done on an object
				// Ignore setting it back to null, if one was previously
				// valid
				if (wouldSet != null)
					this._lastValid = wouldSet;
			}
			
			// Set
			this._elements[__dx] = (__v == null ? SpringNullObject.NULL : __v);
		}
		
		// {@squirreljme.error BK0j Out of bounds access to array. (The index;
		// The length of the array)}
		catch (IndexOutOfBoundsException e)
		{
			throw new SpringArrayIndexOutOfBoundsException(
				String.format("BK0j %d %d", __dx, this.length), e);
		}
	}
}

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectInteger.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





/**
 * Array backed by an int array.
 *
 * @since 2018/11/04
 */
public final class SpringArrayObjectInteger
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final int[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/04
	 */
	public SpringArrayObjectInteger(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException
	{
		super(__self, __cl, __l);
		
		// Initialize elements
		this._elements = new int[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectInteger(SpringClass __self, SpringClass __cl,
		int[] __a)
		throws NullPointerException
	{
		super(__self, __cl, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14












>
>
>
>















<





|
<


|









<




|
<


|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Array backed by an int array.
 *
 * @since 2018/11/04
 */
public final class SpringArrayObjectInteger
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final int[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/04
	 */
	public SpringArrayObjectInteger(SpringClass __self, int __l)

		throws NullPointerException
	{
		super(__self, __l);
		
		// Initialize elements
		this._elements = new int[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.

	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectInteger(SpringClass __self, int[] __a)

		throws NullPointerException
	{
		super(__self, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final int[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectLong.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





/**
 * Array backed by a long array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectLong
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final long[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectLong(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException
	{
		super(__self, __cl, __l);
		
		// Initialize elements
		this._elements = new long[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectLong(SpringClass __self, SpringClass __cl,
		long[] __a)
		throws NullPointerException
	{
		super(__self, __cl, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14












>
>
>
>















<





|
<


|









<




|
<


|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Array backed by a long array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectLong
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final long[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectLong(SpringClass __self, int __l)

		throws NullPointerException
	{
		super(__self, __l);
		
		// Initialize elements
		this._elements = new long[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.

	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectLong(SpringClass __self, long[] __a)

		throws NullPointerException
	{
		super(__self, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final long[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayObjectShort.java.

1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





/**
 * Array backed by a short array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectShort
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final short[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectShort(SpringClass __self, SpringClass __cl,
		int __l)
		throws NullPointerException
	{
		super(__self, __cl, __l);
		
		// Initialize elements
		this._elements = new short[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.
	 * @param __cl The component type.
	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectShort(SpringClass __self, SpringClass __cl,
		short[] __a)
		throws NullPointerException
	{
		super(__self, __cl, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final Object array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14












>
>
>
>















<





|
<


|









<




|
<


|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringArrayIndexOutOfBoundsException;
import cc.squirreljme.vm.springcoat.exceptions.SpringArrayStoreException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;

/**
 * Array backed by a short array.
 *
 * @since 2018/11/14
 */
public final class SpringArrayObjectShort
	extends SpringArrayObject
{
	/** Elements in the array. */
	private final short[] _elements;
	
	/**
	 * Initializes the array.
	 *
	 * @param __self The self type.

	 * @param __l The array length.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/11/14
	 */
	public SpringArrayObjectShort(SpringClass __self, int __l)

		throws NullPointerException
	{
		super(__self, __l);
		
		// Initialize elements
		this._elements = new short[__l];
	}
	
	/**
	 * Wraps the native array.
	 *
	 * @param __self The self type.

	 * @param __a The array to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/18
	 */
	public SpringArrayObjectShort(SpringClass __self, short[] __a)

		throws NullPointerException
	{
		super(__self, __a.length);
		
		this._elements = __a;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/19
	 */
	@Override
	public final short[] array()
	{
		return this._elements;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/14

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringClass.java.

1
2
3
4
5
6
7
8
9
10
11
12
13






14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.Constants;






import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.multiphasicapps.classfile.ClassFile;
import net.multiphasicapps.classfile.ClassFlags;
import net.multiphasicapps.classfile.ClassName;













>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.Constants;
import cc.squirreljme.vm.VMClassLibrary;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassFormatException;
import cc.squirreljme.vm.springcoat.exceptions.SpringIncompatibleClassChangeException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNoSuchFieldException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNoSuchMethodException;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.multiphasicapps.classfile.ClassFile;
import net.multiphasicapps.classfile.ClassFlags;
import net.multiphasicapps.classfile.ClassName;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
	
	/** The super class. */
	protected final SpringClass superclass;
	
	/** The number of instance fields that exist. */
	protected final int instancefieldcount;
	
	/** The special class index. */
	protected final int specialindex;
	
	/** The dimentions of this class. */
	protected final int dimensions;
	
	/** The component type. */
	protected final SpringClass component;
	
	/** The JAR this class is in. */
	protected final String injar;
	
	/** The virtualized size of instances for this class. */
	protected final int instancesize;
	
	/** Interface classes. */
	private final SpringClass[] _interfaceclasses;
	







<
<
<







|







52
53
54
55
56
57
58



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
	
	/** The super class. */
	protected final SpringClass superclass;
	
	/** The number of instance fields that exist. */
	protected final int instancefieldcount;
	



	/** The dimentions of this class. */
	protected final int dimensions;
	
	/** The component type. */
	protected final SpringClass component;
	
	/** The JAR this class is in. */
	protected final VMClassLibrary inJar;
	
	/** The virtualized size of instances for this class. */
	protected final int instancesize;
	
	/** Interface classes. */
	private final SpringClass[] _interfaceclasses;
	
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
	
	/**
	 * Initializes the spring class.
	 *
	 * @param __super The super class of this class.
	 * @param __interfaces The the interfaces this class implements.
	 * @param __cf The class file for this class.
	 * @param __si The special class index.
	 * @param __ct The component type.
	 * @param __injar The JAR this class is in.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/07/21
	 */
	SpringClass(SpringClass __super, SpringClass[] __interfaces,
		ClassFile __cf, int __si, SpringClass __ct, String __injar)
		throws NullPointerException
	{
		if (__interfaces == null || __cf == null)
			throw new NullPointerException("NARG");
		
		ClassName name = __cf.thisName();
		this.name = name;
		this.specialindex = __si;
		this.injar = __injar;
		this.file = __cf;
		this.superclass = __super;
		this.component = __ct;
		this.dimensions = name.dimensions();
		
		// Check
		this._interfaceclasses = (__interfaces = __interfaces.clone());







<

|




|







<
|







91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
	
	/**
	 * Initializes the spring class.
	 *
	 * @param __super The super class of this class.
	 * @param __interfaces The the interfaces this class implements.
	 * @param __cf The class file for this class.

	 * @param __ct The component type.
	 * @param __inJar The JAR this class is in.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/07/21
	 */
	SpringClass(SpringClass __super, SpringClass[] __interfaces,
		ClassFile __cf, SpringClass __ct, VMClassLibrary __inJar)
		throws NullPointerException
	{
		if (__interfaces == null || __cf == null)
			throw new NullPointerException("NARG");
		
		ClassName name = __cf.thisName();
		this.name = name;

		this.inJar = __inJar;
		this.file = __cf;
		this.superclass = __super;
		this.component = __ct;
		this.dimensions = name.dimensions();
		
		// Check
		this._interfaceclasses = (__interfaces = __interfaces.clone());
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
	
	/**
	 * Returns the JAR this class is in.
	 *
	 * @return The JAR this class is in.
	 * @since 2018/10/07
	 */
	public final String inJar()
	{
		return this.injar;
	}
	
	/**
	 * Returns the number of instance fields this class stores. This is for
	 * the most part the size of the given class.
	 *
	 * @return The number of instance fields this class stores.







|

|







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
	
	/**
	 * Returns the JAR this class is in.
	 *
	 * @return The JAR this class is in.
	 * @since 2018/10/07
	 */
	public final VMClassLibrary inJar()
	{
		return this.inJar;
	}
	
	/**
	 * Returns the number of instance fields this class stores. This is for
	 * the most part the size of the given class.
	 *
	 * @return The number of instance fields this class stores.
443
444
445
446
447
448
449











450
451
452
453
454
455
456
		else if (__v instanceof SpringObject)
			return this.isAssignableFrom(((SpringObject)__v).type());
		
		// Unknown
		else
			throw new todo.OOPS();
	}











	
	/**
	 * Has this class been initialized?
	 *
	 * @return If the class has been initialized.
	 * @since 2018/09/08
	 */







>
>
>
>
>
>
>
>
>
>
>







444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
		else if (__v instanceof SpringObject)
			return this.isAssignableFrom(((SpringObject)__v).type());
		
		// Unknown
		else
			throw new todo.OOPS();
	}
	
	/**
	 * Checks if this is an enumeration.
	 * 
	 * @return If this is an enumeration.
	 * @since 2020/06/28
	 */
	public final boolean isEnum()
	{
		return this.flags().isEnum();
	}
	
	/**
	 * Has this class been initialized?
	 *
	 * @return If the class has been initialized.
	 * @since 2018/09/08
	 */
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
		if (this._initialized)
			throw new SpringVirtualMachineException(String.format(
				"BK11 %s", this.name));
		
		this._initialized = true;
	}
	
	/**
	 * Returns the special class index.
	 *
	 * @return The special class index.
	 * @since 2018/09/20
	 */
	public final int specialIndex()
	{
		return this.specialindex;
	}
	
	/**
	 * Returns the super class of this class.
	 *
	 * @return The super class of this class.
	 * @since 2018/09/08
	 */
	public final SpringClass superClass()







<
<
<
<
<
<
<
<
<
<
<







751
752
753
754
755
756
757











758
759
760
761
762
763
764
		if (this._initialized)
			throw new SpringVirtualMachineException(String.format(
				"BK11 %s", this.name));
		
		this._initialized = true;
	}
	











	/**
	 * Returns the super class of this class.
	 *
	 * @return The super class of this class.
	 * @since 2018/09/08
	 */
	public final SpringClass superClass()

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringClassLoader.java.

1
2
3
4
5
6
7
8
9
10
11
12
13



14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.VMClassLibrary;



import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import net.multiphasicapps.classfile.ClassFile;













>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.VMClassLibrary;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassFormatException;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassNotFoundException;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import net.multiphasicapps.classfile.ClassFile;
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
				return rv;
			
			// Debug
			/*todo.DEBUG.note("Loading class `%s`...", __cn);*/
			
			// Load class file for this class
			ClassFile cf;
			String[] injar = new String[1];
			try
			{
				cf = this.loadClassFile(__cn, injar);
			}
			catch (InvalidClassFormatException e)
			{
				// {@squirreljme.error BK12 Could not load class. (The class
				// to load)}
				throw new InvalidClassFormatException(
					String.format("BK12 %s", __cn), e);







|


|







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
				return rv;
			
			// Debug
			/*todo.DEBUG.note("Loading class `%s`...", __cn);*/
			
			// Load class file for this class
			ClassFile cf;
			VMClassLibrary[] inJar = new VMClassLibrary[1];
			try
			{
				cf = this.loadClassFile(__cn, inJar);
			}
			catch (InvalidClassFormatException e)
			{
				// {@squirreljme.error BK12 Could not load class. (The class
				// to load)}
				throw new InvalidClassFormatException(
					String.format("BK12 %s", __cn), e);
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
			// Component?
			SpringClass component = null;
			if (__cn.isArray())
				component = this.loadClass(__cn.componentType());
			
			// Load class information
			rv = new SpringClass(superclass, interfaceclasses, cf,
				this._nexcsi++, component, injar[0]);
			
			// Store for later use
			classes.put(__cn, rv);
			
			return rv;
		}
	}







|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
			// Component?
			SpringClass component = null;
			if (__cn.isArray())
				component = this.loadClass(__cn.componentType());
			
			// Load class information
			rv = new SpringClass(superclass, interfaceclasses, cf,
				component, inJar[0]);
			
			// Store for later use
			classes.put(__cn, rv);
			
			return rv;
		}
	}
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
	 * @return The loaded class file data.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringClassFormatException If the class is not formatted
	 * properly.
	 * @throws SpringClassNotFoundException If the class was not found.
	 * @since 2018/09/01
	 */
	public final ClassFile loadClassFile(ClassName __cn, String[] __ij)
		throws NullPointerException, SpringClassFormatException,
			SpringClassNotFoundException
	{
		if (__cn == null)
			throw new NullPointerException("NARG");
		
		// Debug







|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
	 * @return The loaded class file data.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringClassFormatException If the class is not formatted
	 * properly.
	 * @throws SpringClassNotFoundException If the class was not found.
	 * @since 2018/09/01
	 */
	public final ClassFile loadClassFile(ClassName __cn, VMClassLibrary[] __ij)
		throws NullPointerException, SpringClassFormatException,
			SpringClassNotFoundException
	{
		if (__cn == null)
			throw new NullPointerException("NARG");
		
		// Debug
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
						
						baos.write(buf, 0, rc);
					}
				}
				
				// Record the binary
				if (__ij != null && __ij.length > 0)
					__ij[0] = b.name();
				
				break;
			}
			catch (IOException e)
			{
				// {@squirreljme.error BK13 Failed to read from the class
				// path.}







|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
						
						baos.write(buf, 0, rc);
					}
				}
				
				// Record the binary
				if (__ij != null && __ij.length > 0)
					__ij[0] = b;
				
				break;
			}
			catch (IOException e)
			{
				// {@squirreljme.error BK13 Failed to read from the class
				// path.}

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringCoatFactory.java.

45
46
47
48
49
50
51
52
53
54
55
56
		VMSuiteManager __sm, VMClassLibrary[] __cp, String __maincl,
		Map<String, String> __sprops, String[] __args)
		throws IllegalArgumentException, NullPointerException, VMException
	{
		// Create a new instance of the VM
		SpringTaskManager tm = new SpringTaskManager(__sm, __ps, __sprops);
		return new SpringMachine(__sm, new SpringClassLoader(__cp),
			tm, __maincl, false, -1,
			1, __ps, __sprops, __args);
	}
}








|
<



45
46
47
48
49
50
51
52

53
54
55
		VMSuiteManager __sm, VMClassLibrary[] __cp, String __maincl,
		Map<String, String> __sprops, String[] __args)
		throws IllegalArgumentException, NullPointerException, VMException
	{
		// Create a new instance of the VM
		SpringTaskManager tm = new SpringTaskManager(__sm, __ps, __sprops);
		return new SpringMachine(__sm, new SpringClassLoader(__cp),
			tm, __maincl, __ps, __sprops, tm.globalState, __args);

	}
}

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringDisplayEventCallback.java.

1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.runtime.cldc.asm.NativeDisplayEventCallback;


import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.MethodDescriptor;
import net.multiphasicapps.classfile.MethodNameAndType;

/**
 * This is the callback to use which calls the given spring object, this is
 * needed by the native display.
 *
 * @since 2018/12/03
 */

public final class SpringDisplayEventCallback
	implements NativeDisplayEventCallback
{
	/** The class used for callback. */
	private static final ClassName _CALLBACK_CLASS =
		new ClassName("cc/squirreljme/runtime/cldc/asm/" +
			"NativeDisplayEventCallback");













>
>










>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.runtime.cldc.asm.NativeDisplayEventCallback;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.vm.springcoat.exceptions.SpringMachineExitException;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.MethodDescriptor;
import net.multiphasicapps.classfile.MethodNameAndType;

/**
 * This is the callback to use which calls the given spring object, this is
 * needed by the native display.
 *
 * @since 2018/12/03
 */
@Deprecated
public final class SpringDisplayEventCallback
	implements NativeDisplayEventCallback
{
	/** The class used for callback. */
	private static final ClassName _CALLBACK_CLASS =
		new ClassName("cc/squirreljme/runtime/cldc/asm/" +
			"NativeDisplayEventCallback");
48
49
50
51
52
53
54



55
56
57
58
59
60
61
62
63
64
65
66
	 */
	public SpringDisplayEventCallback(SpringMachine __m, SpringObject __o)
		throws NullPointerException
	{
		if (__m == null || __o == null)
			throw new NullPointerException("NARG");
		



		// Set object to call
		this.object = __o;
		
		// Setup thread
		SpringThread thread = __m.createThread("SpringCoat-LCDUIThread");
		SpringThreadWorker worker = new SpringThreadWorker(__m, thread, false);
		
		// Need to initialize a thread object because this thread has to be
		// registered with the runtime in order for programs to operate
		// correctly on it, even though it is a weird thread
		// This is always registered until it is explicitely not registered
		SpringObject fakethread = worker.newInstance(







>
>
>




|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	 */
	public SpringDisplayEventCallback(SpringMachine __m, SpringObject __o)
		throws NullPointerException
	{
		if (__m == null || __o == null)
			throw new NullPointerException("NARG");
		
		if (true)
			throw Debugging.todo("SDEC again or something else?");
		
		// Set object to call
		this.object = __o;
		
		// Setup thread
		SpringThread thread = __m.createThread("SpringCoat-LCDUIThread", false);
		SpringThreadWorker worker = new SpringThreadWorker(__m, thread, false);
		
		// Need to initialize a thread object because this thread has to be
		// registered with the runtime in order for programs to operate
		// correctly on it, even though it is a weird thread
		// This is always registered until it is explicitely not registered
		SpringObject fakethread = worker.newInstance(

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringFieldStorage.java.

1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.ConstantValue;
import net.multiphasicapps.classfile.FieldNameAndType;

/**
 * Contains storage and other information for fields.
 *












>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.exceptions.SpringIllegalAccessException;
import cc.squirreljme.vm.springcoat.exceptions.SpringIncompatibleClassChangeException;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.ConstantValue;
import net.multiphasicapps.classfile.FieldNameAndType;

/**
 * Contains storage and other information for fields.
 *

Deleted emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringInstance.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

/**
 * This represents an instance of an object which has a class and defined
 * fields.
 *
 * @since 2018/07/22
 */
public final class SpringInstance
{
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringMachine.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22

23
24
25

26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.runtime.cldc.asm.TaskAccess;
import cc.squirreljme.runtime.cldc.lang.GuestDepth;
import cc.squirreljme.runtime.swm.EntryPoint;
import cc.squirreljme.runtime.swm.EntryPoints;
import cc.squirreljme.vm.VMClassLibrary;
import cc.squirreljme.emulator.vm.VMResourceAccess;
import cc.squirreljme.emulator.vm.VMSuiteManager;
import cc.squirreljme.emulator.vm.VirtualMachine;

import java.io.IOException;
import java.io.InputStream;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;

import java.util.List;
import java.util.Map;

import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.ConstantValueString;
import net.multiphasicapps.classfile.MethodDescriptor;
import net.multiphasicapps.classfile.MethodNameAndType;
import cc.squirreljme.emulator.profiler.ProfilerSnapshot;
import net.multiphasicapps.tool.manifest.JavaManifest;

/**
 * This class contains the instance of the SpringCoat virtual machine and has
 * a classpath along with all the needed storage for variables and such.
 *
 * @since 2018/07/29
 */
public final class SpringMachine
	implements Runnable, VirtualMachine
{
	/** Lock. */
	public final Object strlock =

		new Object();



	
	/** The class loader. */
	protected final SpringClassLoader classloader;
	
	/** Resources accessor. */
	protected final VMResourceAccess resourceaccessor;
	
	/** The boot class. */
	protected final String bootcl;
	
	/** Is the boot a midlet? */
	protected final boolean bootmid;
	
	/** The boot index. */
	protected final int bootdx;
	
	/** The manager for suites. */
	protected final VMSuiteManager suites;
	
	/** Task manager. */
	protected final SpringTaskManager tasks;
	
	/** The depth of this machine. */
	protected final int guestdepth;
	
	/** The profiling information. */
	protected final ProfilerSnapshot profiler;
	
	/** Pointer manager. */
	protected final SpringPointerManager pointers =
		new SpringPointerManager();
	
	/** Threads which are available. */
	private final List<SpringThread> _threads =
		new ArrayList<>();
	
	/** Static fields which exist within the virtual machine. */
	private final Map<SpringField, SpringFieldStorage> _staticfields =
		new HashMap<>();












<
<
<
<
|



>
|
|
>



>


>




<
<










|
|
>
|
>
>
>








|
<
<
<
<
<
<







|
|




<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57






58
59
60
61
62
63
64
65
66
67
68
69
70




71
72
73
74
75
76
77
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;





import cc.squirreljme.emulator.profiler.ProfilerSnapshot;
import cc.squirreljme.emulator.vm.VMResourceAccess;
import cc.squirreljme.emulator.vm.VMSuiteManager;
import cc.squirreljme.emulator.vm.VirtualMachine;
import cc.squirreljme.runtime.cldc.asm.TaskAccess;
import cc.squirreljme.vm.springcoat.exceptions.SpringFatalException;
import cc.squirreljme.vm.springcoat.exceptions.SpringMachineExitException;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.ConstantValueString;
import net.multiphasicapps.classfile.MethodDescriptor;
import net.multiphasicapps.classfile.MethodNameAndType;



/**
 * This class contains the instance of the SpringCoat virtual machine and has
 * a classpath along with all the needed storage for variables and such.
 *
 * @since 2018/07/29
 */
public final class SpringMachine
	implements Runnable, VirtualMachine
{
	/** The class which contains the thread starting point. */
	private static final ClassName _START_CLASS =
		new ClassName("java/lang/__Start__");
	
	/** The method to enter for main threads. */
	private static final MethodNameAndType _MAIN_THREAD_METHOD =
		new MethodNameAndType("__main", "()V");
	
	/** The class loader. */
	protected final SpringClassLoader classloader;
	
	/** Resources accessor. */
	protected final VMResourceAccess resourceaccessor;
	
	/** The boot class. */
	protected final String bootClass;






	
	/** The manager for suites. */
	protected final VMSuiteManager suites;
	
	/** Task manager. */
	protected final SpringTaskManager tasks;
	
	/** The global VM state. */
	protected final GlobalState globalState;
	
	/** The profiling information. */
	protected final ProfilerSnapshot profiler;
	




	/** Threads which are available. */
	private final List<SpringThread> _threads =
		new ArrayList<>();
	
	/** Static fields which exist within the virtual machine. */
	private final Map<SpringField, SpringFieldStorage> _staticfields =
		new HashMap<>();
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
	/** Class names by their objects. */
	private final Map<SpringObject, ClassName> _namesbyclass =
		new HashMap<>();
	
	/** Main entry point arguments. */
	private final String[] _args;
	
	/** Long to string map. */
	private final Map<Long, String> _strlongtostring =
		new HashMap<>();
	
	/** String to long map. */
	private final Map<String, Long> _strstringtolong =
		new HashMap<>();
	
	/** System properties. */
	final Map<String, String> _sysproperties;
	
	/** The next thread ID to use. */
	private volatile int _nextthreadid;
	
	/** The next long to choose. */
	private long _strnextlong;
	
	/** Is the VM exiting? */
	private volatile boolean _exiting;
	
	/** Exit code of the VM. */
	volatile int _exitcode;
	
	/**
	 * Initializes the virtual machine.
	 *
	 * @param __sm The manager for suites.
	 * @param __cl The class loader.
	 * @param __tm Task manager.
	 * @param __bootcl The boot class.
	 * @param __bootmid The boot class a midlet.
	 * @param __bootdx The entry point which should be booted when the VM
	 * runs.
	 * @param __gd Guest depth.
	 * @param __profiler The profiler to use.
	 * @param __sprops System properties.

	 * @param __args Main entry point arguments.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/03
	 */
	public SpringMachine(VMSuiteManager __sm, SpringClassLoader __cl,
		SpringTaskManager __tm, String __bootcl, boolean __bootmid,
		int __bootdx, int __gd, ProfilerSnapshot __profiler,
		Map<String, String> __sprops, String... __args)
		throws NullPointerException
	{
		if (__cl == null || __sm == null)
			throw new NullPointerException("NARG");
		
		this.suites = __sm;
		this.classloader = __cl;
		this.tasks = __tm;
		this.bootcl = __bootcl;
		this.bootmid = __bootmid;
		this.bootdx = __bootdx;
		this.guestdepth = __gd;
		this._args = (__args == null ? new String[0] : __args.clone());
		this.profiler = (__profiler != null ? __profiler :
			new ProfilerSnapshot());
		this._sysproperties = (__sprops == null ?
			new HashMap<String, String>() : new HashMap<>(__sprops));
		
		// Setup resource accessor







<
<
<
<
<
<
<
<






<
<
<













<
<
<
<


>





|
|
|








|
<
<
|







87
88
89
90
91
92
93








94
95
96
97
98
99



100
101
102
103
104
105
106
107
108
109
110
111
112




113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132


133
134
135
136
137
138
139
140
	/** Class names by their objects. */
	private final Map<SpringObject, ClassName> _namesbyclass =
		new HashMap<>();
	
	/** Main entry point arguments. */
	private final String[] _args;
	








	/** System properties. */
	final Map<String, String> _sysproperties;
	
	/** The next thread ID to use. */
	private volatile int _nextthreadid;
	



	/** Is the VM exiting? */
	private volatile boolean _exiting;
	
	/** Exit code of the VM. */
	volatile int _exitcode;
	
	/**
	 * Initializes the virtual machine.
	 *
	 * @param __sm The manager for suites.
	 * @param __cl The class loader.
	 * @param __tm Task manager.
	 * @param __bootcl The boot class.




	 * @param __profiler The profiler to use.
	 * @param __sprops System properties.
	 * @param __gs Global system state.
	 * @param __args Main entry point arguments.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/03
	 */
	public SpringMachine(VMSuiteManager __sm, SpringClassLoader __cl,
		SpringTaskManager __tm, String __bootcl,
		ProfilerSnapshot __profiler, Map<String, String> __sprops,
		GlobalState __gs, String... __args)
		throws NullPointerException
	{
		if (__cl == null || __sm == null)
			throw new NullPointerException("NARG");
		
		this.suites = __sm;
		this.classloader = __cl;
		this.tasks = __tm;
		this.bootClass = __bootcl;


		this.globalState = __gs;
		this._args = (__args == null ? new String[0] : __args.clone());
		this.profiler = (__profiler != null ? __profiler :
			new ProfilerSnapshot());
		this._sysproperties = (__sprops == null ?
			new HashMap<String, String>() : new HashMap<>(__sprops));
		
		// Setup resource accessor
175
176
177
178
179
180
181
182


183
184
185
186
187
188
189
190
191
192
193
194
195
196




197
198
199


200
201
202



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
	{
		return this.classloader;
	}
	
	/**
	 * Creates a new thread within the virtual machine.
	 *
	 * @param __n The name of the thread.


	 * @return The newly created thread.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/01
	 */
	public final SpringThread createThread(String __n)
		throws NullPointerException
	{
		if (__n == null)
			throw new NullPointerException("NARG");
		
		// Store thread
		List<SpringThread> threads = this._threads;
		synchronized (threads)
		{




			// Initialize new thread
			int v;
			SpringThread rv = new SpringThread((v = ++this._nextthreadid), __n,


				this.profiler.measureThread(String.format("%s-vm%08x-%d-%s",
				this.classloader.bootLibrary().name(),
				System.identityHashCode(this), v, __n)));



			
			// Store thread
			threads.add(rv);
			return rv;
		}
	}
	
	/**
	 * Resolves the given string pointer.
	 *
	 * @param __p The pointer.
	 * @return The string at the given pointer or {@code null} if it has no
	 * resolution.
	 * @since 2018/09/29
	 */
	public final String debugResolveString(long __p)
	{
		if (__p == -1L)
			return null;
		
		synchronized (this.strlock)
		{
			return this._strlongtostring.get(__p);
		}
	}
	
	/**
	 * Unresolves the given string.
	 *
	 * @param __s The string to unresolve.
	 * @return The pointer to the string.
	 * @since 2018/09/29
	 */
	public final long debugUnresolveString(String __s)
	{
		if (__s == null)
			return -1L;
		
		synchronized (this.strlock)
		{
			Long rv = this._strstringtolong.get(__s);
			if (rv != null)
				return rv.longValue();
			
			Long next = Long.valueOf(++this._strnextlong);
			this._strstringtolong.put(__s, next);
			this._strlongtostring.put(next, __s);
			
			return next;
		}
	}
	
	/**
	 * Exits the virtual machine.
	 *
	 * @param __code The exit code.
	 * @throws SpringMachineExitException To signal virtual machine exit.
	 * @since 2018/10/13
	 */







|
>
>




|
<

<
<
<


|

>
>
>
>


|
>
>


|
>
>
>







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192













































193
194
195
196
197
198
199
	{
		return this.classloader;
	}
	
	/**
	 * Creates a new thread within the virtual machine.
	 *
	 * @param __n The name of the thread, may be {@code null} in which case
	 * the thread will just get an ID number.
	 * @param __main Is this a main thread?
	 * @return The newly created thread.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/01
	 */
	public final SpringThread createThread(String __n, boolean __main)

	{



		// Store thread
		List<SpringThread> threads = this._threads;
		synchronized (this)
		{
			// The name of the thread to use
			String usedName = (__n != null ? __n :
				"hwThread-" + this.numThreads());
			
			// Initialize new thread
			int v;
			SpringThread rv = new SpringThread(
				(v = ++this._nextthreadid), __main,
				usedName,
				this.profiler.measureThread(String.format("%s-vm%08x-%d-%s",
				this.classloader.bootLibrary().name(),
				System.identityHashCode(this), v, usedName)));
			
			// Signal that a major state has changed
			this.notifyAll();
			
			// Store thread
			threads.add(rv);
			return rv;
		}
	}
	













































	/**
	 * Exits the virtual machine.
	 *
	 * @param __code The exit code.
	 * @throws SpringMachineExitException To signal virtual machine exit.
	 * @since 2018/10/13
	 */
293
294
295
296
297
298
299











300
301
302
303
304
305


306
307
308

309
310
311
312
313
314
315
316
317


318





































319
320
321
322
323
324
325
	public final void exitNoException(int __code)
		throws SpringMachineExitException
	{
		// Set as exiting
		this._exitcode = __code;
		this._exiting = true;
	}











	
	/**
	 * Gets the thread by the given ID.
	 *
	 * @param __id The ID of the thread.
	 * @return The thread by this ID or {@code null} if it was not found.


	 * @since 2018/11/21
	 */
	public final SpringThread getThread(int __id)

	{
		List<SpringThread> threads = this._threads;
		synchronized (threads)
		{
			for (SpringThread t : threads)
				if (t.id == __id)
					return t;
		}
		


		return null;





































	}
	
	/**
	 * Returns the static field for the given field.
	 *
	 * @param __f The field to get the static field for.
	 * @return The static field.







>
>
>
>
>
>
>
>
>
>
>





|
>
>



>


|






>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
	public final void exitNoException(int __code)
		throws SpringMachineExitException
	{
		// Set as exiting
		this._exitcode = __code;
		this._exiting = true;
	}
	
	/**
	 * Returns the main arguments.
	 *
	 * @return The main arguments.
	 * @since 2020/06/17
	 */
	public final String[] getMainArguments()
	{
		return this._args.clone();
	}
	
	/**
	 * Gets the thread by the given ID.
	 *
	 * @param __id The ID of the thread.
	 * @return The thread by this ID.
	 * @throws NoSuchElementException If there is no thread that exists by
	 * that ID.
	 * @since 2018/11/21
	 */
	public final SpringThread getThread(int __id)
		throws NoSuchElementException
	{
		List<SpringThread> threads = this._threads;
		synchronized (this)
		{
			for (SpringThread t : threads)
				if (t.id == __id)
					return t;
		}
		
		throw new NoSuchElementException("No such thread ID: " + __id);
	}
	
	/**
	 * Returns all of the process threads.
	 *
	 * @return All of the current process threads.
	 * @since 2020/06/17
	 */
	@SuppressWarnings("UnnecessaryLocalVariable")
	public final SpringThread[] getThreads()
	{
		List<SpringThread> rv = new ArrayList<>();
		
		// Go through threads but also cleanup any that have ended
		List<SpringThread> threads = this._threads;
		synchronized (this)
		{
			for (Iterator<SpringThread> it = threads.iterator(); it.hasNext();)
			{
				SpringThread thread = it.next();
				
				// If the thread is terminating, clean it up
				if (thread.isTerminated())
				{
					// Remove it
					it.remove();
					
					// Signal that a state of a thread has changed
					this.notifyAll();
				}
				
				// Otherwise add it
				else
					rv.add(thread);
			}
		}
		
		// Use whatever was found
		return rv.<SpringThread>toArray(new SpringThread[rv.size()]);
	}
	
	/**
	 * Returns the static field for the given field.
	 *
	 * @param __f The field to get the static field for.
	 * @return The static field.
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
	 * @return The number of active and alive threads.
	 * @since 2018/09/03
	 */
	public final int numThreads()
	{
		// Store thread
		List<SpringThread> threads = this._threads;
		synchronized (threads)
		{
			return threads.size();
		}
	}
	
	/**
	 * Returns the access for resources.







|







346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
	 * @return The number of active and alive threads.
	 * @since 2018/09/03
	 */
	public final int numThreads()
	{
		// Store thread
		List<SpringThread> threads = this._threads;
		synchronized (this)
		{
			return threads.size();
		}
	}
	
	/**
	 * Returns the access for resources.
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
	/**
	 * {@inheritDoc}
	 * @since 2018/09/13
	 */
	@Override
	public final void run()
	{
		// Obtain the boot library to read entry points from
		SpringClassLoader classloader = this.classloader;
		VMClassLibrary bootbin = classloader.bootLibrary();
		
		// May be specified or not
		String entryclass = this.bootcl;
		boolean ismidlet = this.bootmid;
		int launchid = this.bootdx;
		
		// Lookup the entry class via the manifest
		if (entryclass == null)
		{
			// Need to load the manifest where the entry points will be
			EntryPoints entries;
			try (InputStream in = bootbin.resourceAsStream(
				"META-INF/MANIFEST.MF"))
			{
				// {@squirreljme.error BK1a Entry point JAR has no manifest.
				// (The name of the boot binary)}
				if (in == null)
					throw new SpringVirtualMachineException("BK1a " +
						bootbin.name());
				
				entries = new EntryPoints(new JavaManifest(in));
			}
			
			// {@squirreljme.error BK1b Failed to read the manifest.}
			catch (IOException e)
			{
				throw new SpringVirtualMachineException("BK1b", e);
			}
			
			int n = entries.size();
			
			// Print entry points out out for debug, but only for the first
			// guest because this is annoying!
			if (GuestDepth.guestDepth() + 1 == this.guestdepth)
			{
				todo.DEBUG.note("Entry points:");
				for (int i = 0; i < n; i++)
					todo.DEBUG.note("    %d: %s", i, entries.get(i));
			}
			
			// Use the first program if the ID is not valid
			if (launchid < 0 || launchid >= n)
				launchid = 0;
			
			// Needed to enter the machine
			EntryPoint entry = entries.get(launchid);
			entryclass = entry.entryPoint().toString();
			ismidlet = entry.isMidlet();
		}
		
		// Thread that will be used as the main thread of execution, also used
		// to initialize classes when they are requested
		SpringThread mainthread = this.createThread("main");
		
		// We will be using the same logic in the thread worker if we need to
		// initialize any objects or arguments
		SpringThreadWorker worker = new SpringThreadWorker(this,
			mainthread, true);
		mainthread._worker = worker;
		
		// Load the entry point class
		SpringClass entrycl = worker.loadClass(new ClassName(
			entryclass.replace('.', '/')));
		
		// Find the method to be entered in
		SpringMethod mainmethod;
		if (ismidlet)
			mainmethod = entrycl.lookupMethod(false,
				new MethodNameAndType("startApp", "()V"));
		else
			mainmethod = entrycl.lookupMethod(true,
				new MethodNameAndType("main", "([Ljava/lang/String;)V"));
		
		// Setup object to initialize with for thread
		SpringVMStaticMethod vmsm = new SpringVMStaticMethod(mainmethod);
		
		// Determine the entry argument, midlets is just the class to run
		Object entryarg;
		if (ismidlet)
			entryarg = worker.asVMObject(entryclass.replace('.', '/'));
		else
		{
			String[] inargs = this._args;
			int inlen = inargs.length;
			
			// Setup array
			SpringArrayObject outargs = worker.allocateArray(
				worker.resolveClass(new ClassName("java/lang/String")), inlen);
			
			// Initialize the argument array
			for (int i = 0; i < inlen; i++)
				outargs.set(i, worker.asVMObject(inargs[i]));
			
			entryarg = outargs;
		}
		
		// Setup new thread object
		SpringObject threadobj = worker.newInstance(worker.loadClass(
			new ClassName("java/lang/Thread")), new MethodDescriptor(
			"(Ljava/lang/String;ILcc/squirreljme/runtime/cldc/asm/" +
			"StaticMethod;Ljava/lang/Object;)V"), worker.asVMObject("Main"),
			(ismidlet ? 3 : 4), vmsm, entryarg);
		
		// Enter the frame for that method using the arguments we passed (in
		// a static fashion)
		mainthread.enterFrame(worker.loadClass(
			new ClassName("java/lang/Thread")).lookupMethod(false,
			new MethodNameAndType("__start", "()V")), threadobj);
		
		// The main although it executes in this context will always have the
		// same exact logic as other threads running apart from this main
		// thread, so no code is needed to be duplicated at all.
		try
		{
			worker.run();
		}
		
		// Virtual machine exited, do not print fatal trace just exit here
		catch (SpringMachineExitException e)
		{
			throw e;
		}
		
		// Ooopsie!
		catch (RuntimeException e)
		{
			/*PrintStream err = System.err;
			
			err.println("****************************");
			
			// Print the real stack trace
			err.println("*** EXTERNAL STACK TRACE ***");
			e.printStackTrace(err);
			err.println();
			
			// Print the VM seen stack trace
			err.println("*** INTERNAL STACK TRACE ***");
			mainthread.printStackTrace(err);
			err.println();
			
			err.println("****************************");*/
			
			// Retoss
			throw e;
		}
		
		// Wait until all threads have terminated before actually leaving
		for (;;)
		{
			// Check if the VM is exiting, this would have happen if another
			// thread called exit
			// If we do not check, then the VM will never exit even after
			// another thread has exited
			this.exitCheck();
			
			// No more threads left?
			int okay = 0,
				notokay = 0;
			List<SpringThread> threads = this._threads;
			synchronized (threads)
			{
				for (SpringThread t : threads)
					if (t.isExitOkay())
						okay++;
					else
						notokay++;
			}
			
			// Okay to exit?
			if (notokay == 0)
				return;
			
			// Wait a short duration before checking again
			try
			{
				Thread.sleep(500);
			}
			catch (InterruptedException e)
			{
			}
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/17
	 */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|




|
|

<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
|
<
<
|
<
<
<
|
<
<
<
|
<
<
<
<
|
|
|
|
<
<
<
<
<
<
<









<
<
<
<
<
|
<


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







370
371
372
373
374
375
376





















































377
378
379
380
381
382
383
384
385
386



387








388


389





390


391



392



393




394
395
396
397







398
399
400
401
402
403
404
405
406





407

408
409

















410




































411
412
413
414
415
416
417
	/**
	 * {@inheritDoc}
	 * @since 2018/09/13
	 */
	@Override
	public final void run()
	{





















































		// Thread that will be used as the main thread of execution, also used
		// to initialize classes when they are requested
		SpringThread mainThread = this.createThread("main", true);
		
		// We will be using the same logic in the thread worker if we need to
		// initialize any objects or arguments
		SpringThreadWorker worker = new SpringThreadWorker(this,
			mainThread, true);
		mainThread._worker = worker;
		



		// Enter the main entry point which handles the thread logic








		mainThread.enterFrame(worker.loadClass(SpringMachine._START_CLASS)


			.lookupMethod(true, SpringMachine._MAIN_THREAD_METHOD));





		


		// Initialize an instance of Thread for this thread, as this is



		// very important, the call to create VM threads will bind the instance



		// object and the vm thread together.




		worker.newInstance(
			new ClassName("java/lang/Thread"),
			new MethodDescriptor("(Ljava/lang/String;)V"),
			worker.asVMObject("main"));







		
		// The main although it executes in this context will always have the
		// same exact logic as other threads running apart from this main
		// thread, so no code is needed to be duplicated at all.
		try
		{
			worker.run();
		}
		





		// Either failed or threw exit exception

		catch (RuntimeException e)
		{

















			throw e;




































		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/17
	 */
612
613
614
615
616
617
618























619
620
621
622
623
624
625
			err.println();
			
			err.println("****************************");
			
			return TaskAccess.EXIT_CODE_FATAL_EXCEPTION;
		}
	}























	
	/**
	 * Returns the suite manager which is available.
	 *
	 * @return The suite manager that is available.
	 * @since 2018/10/26
	 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
			err.println();
			
			err.println("****************************");
			
			return TaskAccess.EXIT_CODE_FATAL_EXCEPTION;
		}
	}
	
	/**
	 * Sets the current exit code.
	 * 
	 * @param __exitCode The exit code to set.
	 * @since 2020/06/27
	 */
	public final void setExitCode(int __exitCode)
	{
		this._exitcode = __exitCode;
	}
	
	/**
	 * Signals that the given thread terminated.
	 * 
	 * @param __thread The thread that was terminated.
	 * @since 2020/06/29
	 */
	public void signalThreadTerminate(SpringThread __thread)
	{
		// The act of getting all threads will clear out terminated threads
		this.getThreads();
	}
	
	/**
	 * Returns the suite manager which is available.
	 *
	 * @return The suite manager that is available.
	 * @since 2018/10/26
	 */

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringMonitor.java.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.runtime.cldc.asm.ObjectAccess;


/**
 * This is a monitor which is associated with an object.
 *
 * @since 2018/09/15
 */
public final class SpringMonitor
{
	/** The monitor lock. */
	protected final Object lock =
		new Object();
	
	/** The thread which owns this monitor. */
	volatile SpringThread _owner;
	
	/** Number of threads which are waiting on this monitor. */
	volatile int _waitcount;
	
	/** The number of notifications happening. */












|
>








<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22




23
24
25
26
27
28
29
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.constants.MonitorResultType;
import cc.squirreljme.vm.springcoat.exceptions.SpringIllegalMonitorStateException;

/**
 * This is a monitor which is associated with an object.
 *
 * @since 2018/09/15
 */
public final class SpringMonitor
{




	/** The thread which owns this monitor. */
	volatile SpringThread _owner;
	
	/** Number of threads which are waiting on this monitor. */
	volatile int _waitcount;
	
	/** The number of notifications happening. */
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
	public final void enter(SpringThread __t)
		throws NullPointerException
	{
		if (__t == null)
			throw new NullPointerException("NARG");
		
		// Lock on the monitor lock
		Object lock = this.lock;
		for (;;)
			synchronized (lock)
			{
				// We take possession of this monitor
				SpringThread owner = this._owner;
				if (owner == null)
				{
					this._owner = __t;
					this._count = 1;







<

|







42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
	public final void enter(SpringThread __t)
		throws NullPointerException
	{
		if (__t == null)
			throw new NullPointerException("NARG");
		
		// Lock on the monitor lock

		for (;;)
			synchronized (this)
			{
				// We take possession of this monitor
				SpringThread owner = this._owner;
				if (owner == null)
				{
					this._owner = __t;
					this._count = 1;
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
				
				// Need to wait for it to be cleared
				else
				{
					// Wait for lock to be freed
					try
					{
						lock.wait();
					}
					catch (InterruptedException e)
					{
						// Ignore
					}
				}
			}







|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
				
				// Need to wait for it to be cleared
				else
				{
					// Wait for lock to be freed
					try
					{
						this.wait();
					}
					catch (InterruptedException e)
					{
						// Ignore
					}
				}
			}
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
	public final void exit(SpringThread __t, boolean __notify)
		throws NullPointerException, SpringIllegalMonitorStateException
	{
		if (__t == null)
			throw new NullPointerException("NARG");
		
		// Lock on the monitor lock
		Object lock = this.lock;
		synchronized (lock)
		{
			// {@squirreljme.error BK1c This thread does not own the
			// monitor.}
			if (this._owner != __t)
				throw new SpringIllegalMonitorStateException("BK1c");	
			
			// {@squirreljme.error BK1d No previous entry call was made.







<
|







94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
	public final void exit(SpringThread __t, boolean __notify)
		throws NullPointerException, SpringIllegalMonitorStateException
	{
		if (__t == null)
			throw new NullPointerException("NARG");
		
		// Lock on the monitor lock

		synchronized (this)
		{
			// {@squirreljme.error BK1c This thread does not own the
			// monitor.}
			if (this._owner != __t)
				throw new SpringIllegalMonitorStateException("BK1c");	
			
			// {@squirreljme.error BK1d No previous entry call was made.
122
123
124
125
126
127
128
129
130
131
132




















133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
			if (count <= 0)
			{
				this._owner = null;
				
				// Wake up all threads so that they try and lock on the lock
				// so whoever gets that chance
				if (__notify)
					lock.notifyAll();
			}
		}
	}




















	
	/**
	 * Notifies on this monitor and returns the status.
	 *
	 * @param __by The thread that is doing the notify.
	 * @param __all Notify all threads?
	 * @return The notification status.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/20
	 */
	public final int monitorNotify(SpringThread __by, boolean __all)
		throws NullPointerException
	{
		if (__by == null)
			throw new NullPointerException("NARG");
		
		// Lock on the monitor lock
		Object lock = this.lock;
		synchronized (lock)
		{
			// Wrong thread?
			if (this._owner != __by)
				return ObjectAccess.MONITOR_NOT_OWNED;
			
			// Nothing is waiting, do not bother at all!
			int waitcount = this._waitcount;
			if (waitcount == 0)
				return 0;
			
			// Notify all threads or just one?
			// Never let the notify count exceed the wait count as well
			int notifycount = this._notifycount;
			this._notifycount = Math.min(waitcount,
				(__all ? waitcount : notifycount + 1));
			
			// Notify all threads that something happened with the lock
			lock.notifyAll();
			
			return 0;
		}
	}
	
	/**
	 * Waits on the monitor.
	 *
	 * @param __by The thread doing the wait.
	 * @param __ms The milliseconds to wait.
	 * @param __ns The nanoseconds to wait.
	 * @return The wait result.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/21
	 */
	public final int monitorWait(SpringThread __by, long __ms, int __ns)
		throws NullPointerException
	{
		if (__by == null)
			throw new NullPointerException("NARG");
		
		// Lock on the monitor lock
		Object lock = this.lock;
		synchronized (lock)
		{
			// Wrong thread?
			if (this._owner != __by)
				return ObjectAccess.MONITOR_NOT_OWNED;
			
			// Increase our wait count
			this._waitcount++;
			
			// Relinquish control of this monitor, so that way when we actually
			// internally do the wait we check notify counts and such.
			this.exit(__by, true);







|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|










<
|



|













|











|










<
|



|







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
			if (count <= 0)
			{
				this._owner = null;
				
				// Wake up all threads so that they try and lock on the lock
				// so whoever gets that chance
				if (__notify)
					this.notifyAll();
			}
		}
	}
	
	/**
	 * Checks if this monitor is held by the given thread.
	 * 
	 * @param __vmThread The virtual machine thread.
	 * @return If this is held by the given thread.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/27
	 */
	public boolean isHeldBy(SpringThread __vmThread)
		throws NullPointerException
	{
		if (__vmThread == null)
			throw new NullPointerException("NARG");
		
		synchronized (this)
		{
			return this._owner == __vmThread;
		}
	}
	
	/**
	 * Notifies on this monitor and returns the status.
	 *
	 * @param __by The thread that is doing the notify.
	 * @param __all Notify all threads?
	 * @return The {@link MonitorResultType}.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/20
	 */
	public final int monitorNotify(SpringThread __by, boolean __all)
		throws NullPointerException
	{
		if (__by == null)
			throw new NullPointerException("NARG");
		
		// Lock on the monitor lock

		synchronized (this)
		{
			// Wrong thread?
			if (this._owner != __by)
				return MonitorResultType.NOT_OWNED;
			
			// Nothing is waiting, do not bother at all!
			int waitcount = this._waitcount;
			if (waitcount == 0)
				return 0;
			
			// Notify all threads or just one?
			// Never let the notify count exceed the wait count as well
			int notifycount = this._notifycount;
			this._notifycount = Math.min(waitcount,
				(__all ? waitcount : notifycount + 1));
			
			// Notify all threads that something happened with the lock
			this.notifyAll();
			
			return 0;
		}
	}
	
	/**
	 * Waits on the monitor.
	 *
	 * @param __by The thread doing the wait.
	 * @param __ms The milliseconds to wait.
	 * @param __ns The nanoseconds to wait.
	 * @return The {@link MonitorResultType}.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/21
	 */
	public final int monitorWait(SpringThread __by, long __ms, int __ns)
		throws NullPointerException
	{
		if (__by == null)
			throw new NullPointerException("NARG");
		
		// Lock on the monitor lock

		synchronized (this)
		{
			// Wrong thread?
			if (this._owner != __by)
				return MonitorResultType.NOT_OWNED;
			
			// Increase our wait count
			this._waitcount++;
			
			// Relinquish control of this monitor, so that way when we actually
			// internally do the wait we check notify counts and such.
			this.exit(__by, true);
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
						this._notifycount = waitcount;
					
					// Re-enter the monitor
					this.enter(__by);
					
					// Whatever state we ended up in
					if (interrupted)
						return ObjectAccess.MONITOR_INTERRUPTED;
					return ObjectAccess.MONITOR_NOT_INTERRUPTED;
				}
				
				// Otherwise wait for notification to happen
				else
				{
					// Could be interrupted
					try
					{
						// Check if time expired
						if (!waitforever)
						{
							long rem = end - System.nanoTime();
							if (rem <= 0)
							{
								expired = true;
								continue;
							}
							
							// Wait for this time
							lock.wait(rem / 1_000_000L,
								(int)(rem % 1_000_000L));
						}
						
						// Wait forever
						else
						{
							lock.wait();
						}
					}
					
					// Was interrupted
					catch (InterruptedException e)
					{
						interrupted = true;
					}
				}
			}
		}
	}
	
	/**
	 * Waiting information on this monitor.
	 *
	 * @since 2018/11/20
	 */
	private static final class __Waiting__
	{
	}
}








|
|



















|






|











<
<
<
<
<
<
<
<
<



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292









293
294
295
						this._notifycount = waitcount;
					
					// Re-enter the monitor
					this.enter(__by);
					
					// Whatever state we ended up in
					if (interrupted)
						return MonitorResultType.INTERRUPTED;
					return MonitorResultType.NOT_INTERRUPTED;
				}
				
				// Otherwise wait for notification to happen
				else
				{
					// Could be interrupted
					try
					{
						// Check if time expired
						if (!waitforever)
						{
							long rem = end - System.nanoTime();
							if (rem <= 0)
							{
								expired = true;
								continue;
							}
							
							// Wait for this time
							this.wait(rem / 1_000_000L,
								(int)(rem % 1_000_000L));
						}
						
						// Wait forever
						else
						{
							this.wait();
						}
					}
					
					// Was interrupted
					catch (InterruptedException e)
					{
						interrupted = true;
					}
				}
			}
		}









	}
}

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringNullObject.java.

1
2
3
4
5
6
7
8
9
10
11
12



13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;




/**
 * Represents the null object.
 *
 * @since 2018/09/08
 */
public final class SpringNullObject
	implements SpringObject












>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.brackets.RefLinkHolder;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;

/**
 * Represents the null object.
 *
 * @since 2018/09/08
 */
public final class SpringNullObject
	implements SpringObject
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	 * @since 2018/09/15
	 */
	@Override
	public final SpringMonitor monitor()
	{
		// {@squirreljme.error BK1e Cannot obtain the monitor of an object
		// that is null.}
		throw new SpringNullPointerException("BK1e");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final SpringPointerArea pointerArea()
	{
		return SpringPointerArea.NULL;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/09
	 */
	@Override
	public final SpringClass type()
	{
		return null;
	}
}








|



|
|


|

|













39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
	 * @since 2018/09/15
	 */
	@Override
	public final SpringMonitor monitor()
	{
		// {@squirreljme.error BK1e Cannot obtain the monitor of an object
		// that is null.}
		throw new SpringVirtualMachineException("BK1e");
	}
	
	/**
	 * {@inheritDoc
	 * @since 2020/05/31
	 */
	@Override
	public RefLinkHolder refLink()
	{
		throw new SpringVirtualMachineException("NULL has no refLink.");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/09
	 */
	@Override
	public final SpringClass type()
	{
		return null;
	}
}

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringObject.java.

1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



/**
 * This represents anything that is treated by the virtual machine as a kind
 * of object reference. This is needed for SquirrelJME since it exposes a
 * pointer logic which is magically handled by the virtual machine.
 *
 * @since 2018/09/08
 */
public interface SpringObject
{
	/**
	 * Returns the monitor for this object.
	 *
	 * @return This object's monitor.
	 * @since 2018/09/15
	 */
	SpringMonitor monitor();
	
	/**
	 * Returns the pointer area for this object.
	 *
	 * @return The pointer area for this object.
	 * @since 2019/12/21
	 */
	SpringPointerArea pointerArea();
	
	/**
	 * Returns the object type.
	 *
	 * @return The object type.
	 * @since 2018/09/09
	 */
	SpringClass type();
}













>
>


















|

|
|

|










1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.brackets.RefLinkHolder;

/**
 * This represents anything that is treated by the virtual machine as a kind
 * of object reference. This is needed for SquirrelJME since it exposes a
 * pointer logic which is magically handled by the virtual machine.
 *
 * @since 2018/09/08
 */
public interface SpringObject
{
	/**
	 * Returns the monitor for this object.
	 *
	 * @return This object's monitor.
	 * @since 2018/09/15
	 */
	SpringMonitor monitor();
	
	/**
	 * Returns the reference link holder for this object.
	 *
	 * @return The reference link for the object.
	 * @since 2020/05/31
	 */
	RefLinkHolder refLink();
	
	/**
	 * Returns the object type.
	 *
	 * @return The object type.
	 * @since 2018/09/09
	 */
	SpringClass type();
}

Deleted emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringPointerArea.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

/**
 * This represents a new area where pointers can go.
 *
 * @since 2019/12/21
 */
public final class SpringPointerArea
	implements Comparable<SpringPointerArea>
{
	/** Null pointer. */
	public static final SpringPointerArea NULL =
		new SpringPointerArea(0, 0);
	
	/** The base address. */
	public final int base;
	
	/** The length of the area. */
	public final int length;
	
	/**
	 * Initializes the pointer area.
	 *
	 * @param __b The basee.
	 * @param __l The length.
	 * @throws IllegalArgumentException If the length is negative.
	 * @since 2019/12/21
	 */
	public SpringPointerArea(int __b, int __l)
		throws IllegalArgumentException
	{
		// {@squirreljme.error BK3f Cannot have a negative length pointer
		// area.}
		if (__l < 0)
			throw new IllegalArgumentException("BK3f");
		
		this.base = __b;
		this.length = __l;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final int compareTo(SpringPointerArea __o)
	{
		throw new todo.TODO();
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final boolean equals(Object __o)
	{
		throw new todo.TODO();
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final int hashCode()
	{
		throw new todo.TODO();
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final String toString()
	{
		throw new todo.TODO();
	}
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































































































Deleted emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringPointerManager.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

/**
 * This is used to manage pointers within SpringCoat.
 *
 * @since 2019/12/21
 */
public final class SpringPointerManager
{
	/** Queue for cleared references. */
	private final ReferenceQueue<SpringObject> _queue =
		new ReferenceQueue<>();
	
	/** Reference to integer. */
	private final Map<Reference<SpringObject>, Integer> _rtoi =
		new HashMap<>();
	
	/** Integer to reference. */
	private final Map<Integer, Reference<SpringObject>> _itor =
		new HashMap<>();
	
	/** The next allocation address. */
	private int _next =
		4;
	
	/**
	 * Allocates and returns a new pointer area.
	 *
	 * @param __l The length to allocate.
	 * @return The resulting pointer.
	 * @throws IllegalArgumentException If the length is negative.
	 * @since 2019/12/21
	 */
	public final SpringPointerArea allocate(int __l)
		throws IllegalArgumentException
	{
		// {@squirreljme.error BK3g Cannot allocate negative pointer space.}
		if (__l < 0)
			throw new IllegalArgumentException("BK3g");
		
		// Determine base pointer
		int base = this._next;
		
		// {@squirreljme.error BK3h Ran out of address space allocating
		// object. (The requested length)}
		if (base < 0)
			throw new SpringVirtualMachineException("BK3h " + __l);
		
		// Set next position
		this._next = base + ((__l + 3) & ~3);
		
		// Build pointer here
		return new SpringPointerArea(base, __l);
	}
	
	/**
	 * Allocates a pointer of the given length and binds the specified object
	 * to that pointer.
	 *
	 * @param __l The length to allocate.
	 * @param __o The object to bind.
	 * @return The resulting pointer.
	 * @throws IllegalArgumentException If the length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/12/22
	 */
	public final SpringPointerArea allocateAndBind(int __l, SpringObject __o)
		throws IllegalArgumentException, NullPointerException
	{
		if (__o == null)
			throw new NullPointerException("NARG");
		
		// Allocate pointer
		SpringPointerArea rv = this.allocate(__l);
		
		// Setup reference
		Reference<SpringObject> ref = new WeakReference(__o, this._queue);
		
		// Bind it
		synchronized (this)
		{
			Integer ibase = rv.base;
			
			// Store into both referencing maps
			this._rtoi.put(ref, ibase);
			this._itor.put(ibase, ref);
		}
		
		// Return the result
		return rv;
	}
	
	/**
	 * Locates the object at the given address.
	 *
	 * @param __p The object to find.
	 * @return The object which was found.
	 * @since 2019/12/22
	 */
	public final SpringObject findObject(int __p)
	{
		// Zero address always returns null pointers!
		if (__p == 0)
			return SpringNullObject.NULL;
		
		// Need to use both maps
		Map<Reference<SpringObject>, Integer> rtoi = this._rtoi;
		Map<Integer, Reference<SpringObject>> itor = this._itor;
		
		// Lock on self
		synchronized (this)
		{
			// First try to cleanup anything that was cleared reference
			// wise
			ReferenceQueue<SpringObject> queue = this._queue;
			for (;;)
			{
				// Any new ones appeared?
				Reference<? extends SpringObject> polled = queue.poll();
				if (polled == null)
					break;
				
				// Read integer base
				Integer ibase = rtoi.get(polled);
				
				// Clear from both maps
				rtoi.remove(polled);
				itor.remove(ibase);
			}
			
			// Try to find object reference
			Reference<SpringObject> ref = itor.get(__p);
			
			// {@squirreljme.error BK3i Could not find object referenced at
			// the given pointer. (The requested address)}
			SpringObject rv = (ref != null ? ref.get() : null);
			if (rv == null)
				throw new SpringVirtualMachineException(
					String.format("BK3i @%08x", __p));
			
			return rv;
		}
	}
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































Deleted emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringPrimitiveReference.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

/**
 * This interface represents a base reference.
 *
 * @since 2018/09/23
 */
public abstract class SpringPrimitiveReference
	implements SpringObject
{
	/**
	 * Gets the object from this reference.
	 *
	 * @return The value of the reference.
	 * @since 2018/09/23
	 */
	public abstract SpringObject get();
	
	/**
	 * Sets the reference to the given object.
	 *
	 * @param __o The object to set.
	 * @since 2018/09/23
	 */
	public abstract void set(SpringObject __o);
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/23
	 */
	@Override
	public final SpringMonitor monitor()
	{
		// {@squirreljme.error BK1f Reference types are special and have no
		// monitor.}
		throw new SpringVirtualMachineException("BK1f");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final SpringPointerArea pointerArea()
	{
		throw new todo.TODO();
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/23
	 */
	@Override
	public final SpringClass type()
	{
		// {@squirreljme.error BK1g Reference types are special and have no
		// class.}
		throw new SpringVirtualMachineException("BK1g");
	}
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































































































Deleted emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringPrimitiveWeakReference.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This class stores information for weak references.
 *
 * @since 2018/09/23
 */
public final class SpringPrimitiveWeakReference
	extends SpringPrimitiveReference
{
	/** The reference used. */
	private Reference<SpringObject> _ref;
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/23
	 */
	@Override
	public final SpringObject get()
	{
		Reference<SpringObject> ref = this._ref;
		if (ref != null)
			return ref.get();
		return null;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/23
	 */
	@Override
	public final void set(SpringObject __o)
	{
		this._ref = new WeakReference<>(__o);
	}
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringSimpleObject.java.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;


import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This is a representation of an object within the virtual machine.
 *
 * @since 2018/09/08
 */
public final class SpringSimpleObject
	implements SpringObject
{
	/** The type of object this is. */
	protected final SpringClass type;
	
	/** The monitor for this object, every object has one. */
	protected final SpringMonitor monitor =
		new SpringMonitor();
	
	/** The pointer for this object. */
	protected final SpringPointerArea pointer;

	
	/** Field storage in the class. */
	private final SpringFieldStorage[] _fields;
	
	/** String representation. */
	private Reference<String> _string;
	
	/**
	 * Initializes the object.
	 *
	 * @param __cl The class of the object.
	 * @param __spm The manager for pointers.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/08
	 */
	public SpringSimpleObject(SpringClass __cl, SpringPointerManager __spm)
		throws NullPointerException
	{
		if (__cl == null || __spm == null)
			throw new NullPointerException("NARG");
		
		this.type = __cl;
		
		// Setup field array
		int n;
		SpringFieldStorage[] fields;
		this._fields = (fields =
			new SpringFieldStorage[(n = __cl.instanceFieldCount())]);
		
		// Initialize variable for all fields
		int i = 0;
		for (SpringField f : __cl.fieldTable())
			fields[i++] = new SpringFieldStorage(f);
		
		// Allocate pointer
		this.pointer = __spm.allocateAndBind(__cl.instancesize, this);
	}
	
	/**
	 * Returns the field by the given field.
	 *
	 * @param __f The field to get.
	 * @return The storage for the field.












>


















|
|
>











<



|


|














<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66



67
68
69
70
71
72
73
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.vm.springcoat.brackets.RefLinkHolder;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This is a representation of an object within the virtual machine.
 *
 * @since 2018/09/08
 */
public final class SpringSimpleObject
	implements SpringObject
{
	/** The type of object this is. */
	protected final SpringClass type;
	
	/** The monitor for this object, every object has one. */
	protected final SpringMonitor monitor =
		new SpringMonitor();
	
	/** The reference link holder. */
	protected final RefLinkHolder refLink =
		new RefLinkHolder();
	
	/** Field storage in the class. */
	private final SpringFieldStorage[] _fields;
	
	/** String representation. */
	private Reference<String> _string;
	
	/**
	 * Initializes the object.
	 *
	 * @param __cl The class of the object.

	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/08
	 */
	public SpringSimpleObject(SpringClass __cl)
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		this.type = __cl;
		
		// Setup field array
		int n;
		SpringFieldStorage[] fields;
		this._fields = (fields =
			new SpringFieldStorage[(n = __cl.instanceFieldCount())]);
		
		// Initialize variable for all fields
		int i = 0;
		for (SpringField f : __cl.fieldTable())
			fields[i++] = new SpringFieldStorage(f);



	}
	
	/**
	 * Returns the field by the given field.
	 *
	 * @param __f The field to get.
	 * @return The storage for the field.
92
93
94
95
96
97
98
















99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
	 * @return The storage for the field by the specified index.
	 * @since 2018/09/16
	 */
	public final SpringFieldStorage fieldByIndex(int __dx)
	{
		return this._fields[__dx];
	}
















	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override
	public final SpringMonitor monitor()
	{
		return this.monitor;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final SpringPointerArea pointerArea()
	{
		return this.pointer;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|


|

|







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
	 * @return The storage for the field by the specified index.
	 * @since 2018/09/16
	 */
	public final SpringFieldStorage fieldByIndex(int __dx)
	{
		return this._fields[__dx];
	}
	
	/**
	 * Returns the field by the name and type.
	 *
	 * @param __static Is this field static?
	 * @param __name The name of the field.
	 * @param __type The type of the field.
	 * @return The storage for the field.
	 * @since 2020/06/17
	 */
	public final SpringFieldStorage fieldByNameAndType(boolean __static,
		String __name, String __type)
	{
		return this.fieldByField(
			this.type().lookupField(__static, __name, __type));
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override
	public final SpringMonitor monitor()
	{
		return this.monitor;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/05/31
	 */
	@Override
	public RefLinkHolder refLink()
	{
		return this.refLink;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringTaskManager.java.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16

17
18
19
20
21
22
23
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.runtime.cldc.asm.TaskAccess;

import cc.squirreljme.runtime.swm.EntryPoints;
import cc.squirreljme.vm.VMClassLibrary;
import cc.squirreljme.emulator.vm.VMSuiteManager;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.microedition.swm.TaskStatus;
import cc.squirreljme.emulator.profiler.ProfilerSnapshot;
import net.multiphasicapps.tool.manifest.JavaManifest;













>



>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.runtime.cldc.asm.TaskAccess;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.swm.EntryPoints;
import cc.squirreljme.vm.VMClassLibrary;
import cc.squirreljme.emulator.vm.VMSuiteManager;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.microedition.swm.TaskStatus;
import cc.squirreljme.emulator.profiler.ProfilerSnapshot;
import net.multiphasicapps.tool.manifest.JavaManifest;
32
33
34
35
36
37
38



39
40
41
42
43
44
45
{
	/** The manager for suites. */
	protected final VMSuiteManager suites;
	
	/** The profiling information. */
	protected final ProfilerSnapshot profiler;
	



	/** Tasks that are used. */
	private final Map<Integer, SpringTask> _tasks =
		new HashMap<>();
	
	/** System properties. */
	private final Map<String, String> _sysprops;
	







>
>
>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{
	/** The manager for suites. */
	protected final VMSuiteManager suites;
	
	/** The profiling information. */
	protected final ProfilerSnapshot profiler;
	
	/** Global state. */
	protected final GlobalState globalState;
	
	/** Tasks that are used. */
	private final Map<Integer, SpringTask> _tasks =
		new HashMap<>();
	
	/** System properties. */
	private final Map<String, String> _sysprops;
	
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88



89
90
91
92
93
94
95
		if (__sm == null)
			throw new NullPointerException("NARG");
		
		this.suites = __sm;
		this.profiler = (__ps == null ? new ProfilerSnapshot() : __ps);
		this._sysprops = (__sp == null ? new HashMap<String, String>() :
			new HashMap<>(__sp));

	}
	
	/**
	 * Starts the specified task.
	 *
	 * @param __cp The class path to use.
	 * @param __entry The entry point.
	 * @param __args Arguments used.
	 * @param __gd The current guest depth.
	 * @return The ID of the created task.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/04
	 */
	public final int startTask(String[] __cp, String __entry, String[] __args,
		int __gd)
		throws NullPointerException
	{
		if (__cp == null || __entry == null || __args == null)
			throw new NullPointerException("NARG");
		



		VMSuiteManager suites = this.suites;
		
		// Load classpath libraries
		int cpn = __cp.length;
		VMClassLibrary[] scl = new VMClassLibrary[cpn];
		for (int i = 0; i < cpn; i++)
		{







>




















>
>
>







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
		if (__sm == null)
			throw new NullPointerException("NARG");
		
		this.suites = __sm;
		this.profiler = (__ps == null ? new ProfilerSnapshot() : __ps);
		this._sysprops = (__sp == null ? new HashMap<String, String>() :
			new HashMap<>(__sp));
		this.globalState = new GlobalState();
	}
	
	/**
	 * Starts the specified task.
	 *
	 * @param __cp The class path to use.
	 * @param __entry The entry point.
	 * @param __args Arguments used.
	 * @param __gd The current guest depth.
	 * @return The ID of the created task.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/04
	 */
	public final int startTask(String[] __cp, String __entry, String[] __args,
		int __gd)
		throws NullPointerException
	{
		if (__cp == null || __entry == null || __args == null)
			throw new NullPointerException("NARG");
		
		if (true)
			throw Debugging.todo("Tasks changed completely!!");
		
		VMSuiteManager suites = this.suites;
		
		// Load classpath libraries
		int cpn = __cp.length;
		VMClassLibrary[] scl = new VMClassLibrary[cpn];
		for (int i = 0; i < cpn; i++)
		{
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
		// Could not find the boot point
		if (bootdx < 0)
			return TaskAccess.ERROR_INVALID_ENTRY;
		
		// Build machine for the task
		SpringMachine machine = new SpringMachine(suites,
			new SpringClassLoader(scl), this, null,
			false, bootdx, __gd + 1,
			this.profiler, this._sysprops, __args);
		
		// Lock on tasks
		Map<Integer, SpringTask> tasks = this._tasks;
		synchronized (tasks)
		{
			// Next task ID
			int tid = ++this._nextid;







<
|







146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
		// Could not find the boot point
		if (bootdx < 0)
			return TaskAccess.ERROR_INVALID_ENTRY;
		
		// Build machine for the task
		SpringMachine machine = new SpringMachine(suites,
			new SpringClassLoader(scl), this, null,

			this.profiler, this._sysprops, this.globalState, __args);
		
		// Lock on tasks
		Map<Integer, SpringTask> tasks = this._tasks;
		synchronized (tasks)
		{
			// Next task ID
			int tid = ++this._nextid;

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringThread.java.

1
2
3
4
5
6
7
8
9
10
11
12
13





14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.SystemCallIndex;





import java.io.PrintStream;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import net.multiphasicapps.classfile.ByteCode;
import cc.squirreljme.emulator.profiler.ProfiledThread;













>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.runtime.cldc.debug.CallTraceElement;
import cc.squirreljme.runtime.cldc.debug.CallTraceUtils;
import cc.squirreljme.vm.springcoat.brackets.VMThreadObject;
import cc.squirreljme.vm.springcoat.exceptions.SpringNullPointerException;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.io.PrintStream;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import net.multiphasicapps.classfile.ByteCode;
import cc.squirreljme.emulator.profiler.ProfiledThread;
28
29
30
31
32
33
34



35
36
37
38
39
40
41
42
43
44
45
46
47
48






49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67



68
69
70
71

72
73
74
75
76

77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112





113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156





157
158
159
160
161
162
163
{
	/** Maximum depth of the stack. */
	public static final int MAX_STACK_DEPTH =
		64;
	
	/** The thread ID. */
	protected final int id;



	
	/** The name of this thread. */
	protected final String name;
	
	/** Profiler information. */
	protected final ProfiledThread profiler;
	
	/** System call errors. */
	final int[] _syscallerrors =
		new int[SystemCallIndex.NUM_SYSCALLS];
	
	/** The stack frames. */
	private final List<SpringThread.Frame> _frames =
		new ArrayList<>();






		
	/** String representation. */
	private Reference<String> _string;
	
	/** Ran at least one frame (was started)? */
	private volatile boolean _hadoneframe;
	
	/** Is this a daemon thread? */
	volatile boolean _daemon;
	
	/** Terminate the thread? */
	volatile boolean _terminate;
	
	/** Did we signal exit? */
	volatile boolean _signaledexit;
	
	/** The current worker for the thread. */
	volatile SpringThreadWorker _worker;
	



	/**
	 * Initializes the thread.
	 *
	 * @param __id The thread ID.

	 * @param __n The name of the thread.
	 * @param __profiler Profiled storage.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/01
	 */

	SpringThread(int __id, String __n, ProfiledThread __profiler)
		throws NullPointerException
	{
		if (__n == null)
			throw new NullPointerException("NARG");
		
		this.id = __id;

		this.name = __n;
		this.profiler = __profiler;
	}
	
	/**
	 * Returns the current frame of execution or {@code null} if there is none.
	 *
	 * @return The current frame of execution or {@code null} if there is none.
	 * @since 2018/09/03
	 */
	public final SpringThread.Frame currentFrame()
	{
		List<SpringThread.Frame> frames = this._frames;
		synchronized (frames)
		{
			if (frames.isEmpty())
				return null;
			return frames.get(frames.size() - 1);
		}
	}
	
	/**
	 * Enters a blank frame to store data.
	 *
	 * @return The
	 * @since 2018/09/20
	 */
	public final SpringThread.Frame enterBlankFrame()
	{





		// Setup blank frame
		SpringThread.Frame rv = new SpringThread.Frame();
		
		// {@squirreljme.error BK1j Stack overflow.}
		List<SpringThread.Frame> frames = this._frames;
		if (frames.size() >= SpringThread.MAX_STACK_DEPTH)
			throw new SpringVirtualMachineException("BK1j");
		
		// Lock on frames as a new one is added
		synchronized (frames)
		{
			frames.add(rv);
		}
		
		// Profile for this frame
		this.profiler.enterFrame("<blank>", "<blank>", "()V",
			System.nanoTime());
		
		// Had one frame (started)
		this._hadoneframe = true;
		
		// Undo termination
		this._terminate = false;
		
		return rv;
	}
	
	/**
	 * Enters the specified method and sets up a stack frame for it.
	 *
	 * @param __m The method to enter.
	 * @param __args Arguments to the frame entry (method arguments).
	 * @return The used stack frame.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringVirtualMachineException If the method is abstract.
	 * @since 2018/09/03
	 */
	public final SpringThread.Frame enterFrame(SpringMethod __m,
		Object... __args)
		throws NullPointerException, SpringVirtualMachineException
	{
		if (__m == null)
			throw new NullPointerException("NARG");
		





		if (__args == null)
			__args = new Object[0];
		
		// Debug
		/*todo.DEBUG.note("enterFrame(%s::%s, %s)", __m.inClass(),
			__m.nameAndType(), Arrays.<Object>asList(__args));*/
		







>
>
>







<
<
<
<



>
>
>
>
>
>










<
<
<






>
>
>




>





>
|






>













|















>
>
>
>
>









|











<
<
<




















>
>
>
>
>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49




50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
{
	/** Maximum depth of the stack. */
	public static final int MAX_STACK_DEPTH =
		64;
	
	/** The thread ID. */
	protected final int id;
	
	/** Is this a main thread? */
	protected final boolean main;
	
	/** The name of this thread. */
	protected final String name;
	
	/** Profiler information. */
	protected final ProfiledThread profiler;
	




	/** The stack frames. */
	private final List<SpringThread.Frame> _frames =
		new ArrayList<>();
	
	/** The thread's {@link Thread} instance. */
	private SpringObject _threadInstance;
	
	/** The thread's VM Thread instance. */
	private VMThreadObject _vmThread;
		
	/** String representation. */
	private Reference<String> _string;
	
	/** Ran at least one frame (was started)? */
	private volatile boolean _hadoneframe;
	
	/** Is this a daemon thread? */
	volatile boolean _daemon;
	



	/** Did we signal exit? */
	volatile boolean _signaledexit;
	
	/** The current worker for the thread. */
	volatile SpringThreadWorker _worker;
	
	/** Terminate the thread? */
	private volatile boolean _terminate;
	
	/**
	 * Initializes the thread.
	 *
	 * @param __id The thread ID.
	 * @param __main Is this a main thread.
	 * @param __n The name of the thread.
	 * @param __profiler Profiled storage.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/01
	 */
	SpringThread(int __id, boolean __main, String __n,
		ProfiledThread __profiler)
		throws NullPointerException
	{
		if (__n == null)
			throw new NullPointerException("NARG");
		
		this.id = __id;
		this.main = __main;
		this.name = __n;
		this.profiler = __profiler;
	}
	
	/**
	 * Returns the current frame of execution or {@code null} if there is none.
	 *
	 * @return The current frame of execution or {@code null} if there is none.
	 * @since 2018/09/03
	 */
	public final SpringThread.Frame currentFrame()
	{
		List<SpringThread.Frame> frames = this._frames;
		synchronized (this)
		{
			if (frames.isEmpty())
				return null;
			return frames.get(frames.size() - 1);
		}
	}
	
	/**
	 * Enters a blank frame to store data.
	 *
	 * @return The
	 * @since 2018/09/20
	 */
	public final SpringThread.Frame enterBlankFrame()
	{
		// Cannot enter frames when terminated
		if (this.isTerminated())
			throw new SpringVirtualMachineException(
				"Cannot enter frame on terminated thread.");
		
		// Setup blank frame
		SpringThread.Frame rv = new SpringThread.Frame();
		
		// {@squirreljme.error BK1j Stack overflow.}
		List<SpringThread.Frame> frames = this._frames;
		if (frames.size() >= SpringThread.MAX_STACK_DEPTH)
			throw new SpringVirtualMachineException("BK1j");
		
		// Lock on frames as a new one is added
		synchronized (this)
		{
			frames.add(rv);
		}
		
		// Profile for this frame
		this.profiler.enterFrame("<blank>", "<blank>", "()V",
			System.nanoTime());
		
		// Had one frame (started)
		this._hadoneframe = true;
		



		return rv;
	}
	
	/**
	 * Enters the specified method and sets up a stack frame for it.
	 *
	 * @param __m The method to enter.
	 * @param __args Arguments to the frame entry (method arguments).
	 * @return The used stack frame.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringVirtualMachineException If the method is abstract.
	 * @since 2018/09/03
	 */
	public final SpringThread.Frame enterFrame(SpringMethod __m,
		Object... __args)
		throws NullPointerException, SpringVirtualMachineException
	{
		if (__m == null)
			throw new NullPointerException("NARG");
		
		// Cannot enter frames when terminated
		if (this.isTerminated())
			throw new SpringVirtualMachineException(
				"Cannot enter frame on terminated thread.");
		
		if (__args == null)
			__args = new Object[0];
		
		// Debug
		/*todo.DEBUG.note("enterFrame(%s::%s, %s)", __m.inClass(),
			__m.nameAndType(), Arrays.<Object>asList(__args));*/
		
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
		// Profile for this frame
		this.profiler.enterFrame(__m.inClass().toString(),
			__m.nameAndType().name().toString(),
			__m.nameAndType().type().toString(), System.nanoTime());
		
		// Lock on frames as a new one is added
		List<SpringThread.Frame> frames = this._frames;
		synchronized (frames)
		{
			frames.add(rv);
		}
		
		// Had one frame (started)
		this._hadoneframe = true;
		
		// Undo termination
		this._terminate = false;
		
		// Handle synchronized method
		if (__m.flags().isSynchronized())
		{
			SpringObject monitor;
			
			// Monitor on the class object, needs the worker since we need to
			// load a class







|







<
<
<







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207



208
209
210
211
212
213
214
		// Profile for this frame
		this.profiler.enterFrame(__m.inClass().toString(),
			__m.nameAndType().name().toString(),
			__m.nameAndType().type().toString(), System.nanoTime());
		
		// Lock on frames as a new one is added
		List<SpringThread.Frame> frames = this._frames;
		synchronized (this)
		{
			frames.add(rv);
		}
		
		// Had one frame (started)
		this._hadoneframe = true;
		



		// Handle synchronized method
		if (__m.flags().isSynchronized())
		{
			SpringObject monitor;
			
			// Monitor on the class object, needs the worker since we need to
			// load a class
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269





































































































270
271
272
273
274
275
276
277
278
279
280

























281
282
283
284
285
286
287
	 *
	 * @since 2018/11/17
	 */
	public final void exitAllFrames()
	{
		// Lock on frames as a new one is added
		List<SpringThread.Frame> frames = this._frames;
		synchronized (frames)
		{
			frames.clear();
		}
	}
	
	/**
	 * Returns all of the frames which are available.
	 *
	 * @return All of the available stack frames.
	 * @since 2018/09/16
	 */
	public final SpringThread.Frame[] frames()
	{
		// Lock on frames
		List<SpringThread.Frame> frames = this._frames;
		synchronized (frames)
		{
			return frames.<SpringThread.Frame>toArray(
				new SpringThread.Frame[frames.size()]);
		}
	}





































































































	
	/**
	 * Is exiting the virtual machine okay?
	 *
	 * @return If it is okay to exit.
	 * @since 2018/11/17
	 */
	public final boolean isExitOkay()
	{
		return this._daemon || this._terminate;
	}

























	
	/**
	 * Returns the name of the thread.
	 *
	 * @return The name of the thread.
	 * @since 2018/09/03
	 */







|















|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
	 *
	 * @since 2018/11/17
	 */
	public final void exitAllFrames()
	{
		// Lock on frames as a new one is added
		List<SpringThread.Frame> frames = this._frames;
		synchronized (this)
		{
			frames.clear();
		}
	}
	
	/**
	 * Returns all of the frames which are available.
	 *
	 * @return All of the available stack frames.
	 * @since 2018/09/16
	 */
	public final SpringThread.Frame[] frames()
	{
		// Lock on frames
		List<SpringThread.Frame> frames = this._frames;
		synchronized (this)
		{
			return frames.<SpringThread.Frame>toArray(
				new SpringThread.Frame[frames.size()]);
		}
	}
	
	/**
	 * Returns the stack trace for this thread.
	 * 
	 * @return The stack trace for this thread.
	 * @since 2020/06/13
	 */
	public final CallTraceElement[] getStackTrace()
	{
		// Lock since the frames may change!
		List<SpringThread.Frame> frames = this._frames;
		synchronized (this)
		{
			// Setup target array
			int n = frames.size();
			CallTraceElement[] rv = new CallTraceElement[n];
			
			// The frames at the end are at the top
			for (int i = n - 1, write = 0; i >= 0; i--, write++)
			{
				SpringThread.Frame frame = frames.get(i);
				CallTraceElement trace;
				
				// Blanks are purely virtual standing points so they are
				// regarded as such
				if (frame.isBlank())
				{
					trace = new CallTraceElement(
						"<guard>", "<guard>", null,
						0L, null, -1);
				}
				
				// Print other parts
				else
				{
					SpringMethod inMethod = frame.method();
					int pc = frame.lastExecutedPc();
					
					trace = new CallTraceElement(
						inMethod.inClass().toString(),
						inMethod.name().toString(),
						inMethod.nameAndType().type().toString(),
						0,
						inMethod.infile,
						inMethod.byteCode().lineOfAddress(pc),
						inMethod.byteCode().getByAddress(pc).operation(),
						pc);
				}
				
				// Store trace in top-most order
				rv[write] = trace;
			}
			
			return rv;
		}
	}
	
	/**
	 * Interrupts this thread.
	 * 
	 * @since 2020/06/22
	 */
	public final void hardInterrupt()
	{
		SpringThreadWorker worker = this._worker;
		if (worker == null)
			throw new RuntimeException(
				"Cannot interrupt thread with no worker.");
		
		// Signal the other thread or something else?
		Thread signal = this._worker.signalinstead;
		if (signal != null)
			signal.interrupt();
		else
			worker.interrupt();
	}
	
	/**
	 * Returns whether or not this thread has an instance.
	 *
	 * @return If this thread has an instance.
	 * @since 2020/06/18
	 */
	public final boolean hasThreadInstance()
	{
		synchronized (this)
		{
			return this._threadInstance != null;
		}
	}
	
	/**
	 * Is this a daemon thread?
	 *
	 * @return If this is a daemon thread.
	 * @since 2020/06/17
	 */
	public final boolean isDaemon()
	{
		return this._daemon;
	}
	
	/**
	 * Is exiting the virtual machine okay?
	 *
	 * @return If it is okay to exit.
	 * @since 2018/11/17
	 */
	public final boolean isExitOkay()
	{
		return this._daemon || this._terminate;
	}
	
	/**
	 * If this is a main thread or not.
	 *
	 * @return If this is a main thread.
	 * @since 2020/06/17
	 */
	public final boolean isMain()
	{
		return this.main;
	}
	
	/**
	 * Returns if this thread has terminated.
	 * 
	 * @return If this thread has terminated.
	 * @since 2020/06/29
	 */
	public final boolean isTerminated()
	{
		synchronized (this)
		{
			return this._terminate;
		}
	}
	
	/**
	 * Returns the name of the thread.
	 *
	 * @return The name of the thread.
	 * @since 2018/09/03
	 */
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
	 *
	 * @return The number of available frames.
	 * @since 2018/09/03
	 */
	public final int numFrames()
	{
		List<SpringThread.Frame> frames = this._frames;
		synchronized (frames)
		{
			return frames.size();
		}
	}
	
	/**
	 * Pops a frame from the thread stack.







|







438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
	 *
	 * @return The number of available frames.
	 * @since 2018/09/03
	 */
	public final int numFrames()
	{
		List<SpringThread.Frame> frames = this._frames;
		synchronized (this)
		{
			return frames.size();
		}
	}
	
	/**
	 * Pops a frame from the thread stack.
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
	{
		// Exit the frame
		this.profiler.exitFrame(System.nanoTime());
		
		// Pop from the stack
		SpringThread.Frame rv;
		List<SpringThread.Frame> frames = this._frames;
		synchronized (frames)
		{
			// {@squirreljme.error BK1o No frames to pop.}
			int n;
			if ((n = frames.size()) <= 0)
				throw new SpringVirtualMachineException("BK1o");	
			
			rv = frames.remove(n - 1);







|







460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
	{
		// Exit the frame
		this.profiler.exitFrame(System.nanoTime());
		
		// Pop from the stack
		SpringThread.Frame rv;
		List<SpringThread.Frame> frames = this._frames;
		synchronized (this)
		{
			// {@squirreljme.error BK1o No frames to pop.}
			int n;
			if ((n = frames.size()) <= 0)
				throw new SpringVirtualMachineException("BK1o");	
			
			rv = frames.remove(n - 1);
348
349
350
351
352
353
354
355

356


357
358













359
360
361
362
363



364
365
366

367



368






369
370
371

372




373
374


375


376







377


378





379





380




381
382
383
384


385
386




387
388
389
390
391
392
393
	 */
	public final void printStackTrace(PrintStream __ps)
		throws NullPointerException
	{
		if (__ps == null)
			throw new NullPointerException("NARG");
		
		// Note the thread

		__ps.printf("Thread #%d: %s%n", this.id, this.name);


		
		// Lock since the frames may change!













		List<SpringThread.Frame> frames = this._frames;
		synchronized (frames)
		{
			// The frames at the end are at the top
			for (int n = frames.size(), i = n - 1; i >= 0; i--)



			{
				SpringThread.Frame frame = frames.get(i);
				

				// Do not print traces for blank frames



				if (frame.isBlank())






				{
					__ps.printf("    at <guard frame>%n");
					continue;

				}




				
				SpringMethod inmethod = frame.method();


				int pc = frame.lastExecutedPc();


				







				// Print information


				__ps.printf("    at %s.%s @ %d [%s] (%s:%d)%n",





					inmethod.inClass(),





					inmethod.nameAndType(),




					pc,
					inmethod.byteCode().getByAddress(pc).mnemonic(),
					inmethod.inFile(),
					inmethod.byteCode().lineOfAddress(pc));


			}
		}




	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override







|
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

<
<
>
>
>
|
|
|
>
|
>
>
>
|
>
>
>
>
>
>
|
<
|
>
|
>
>
>
>
|
|
>
>
|
>
>
|
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
<
|
<
>
>
|
|
>
>
>
>







491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520


521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539

540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582

583

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
	 */
	public final void printStackTrace(PrintStream __ps)
		throws NullPointerException
	{
		if (__ps == null)
			throw new NullPointerException("NARG");
		
		// Use standard SquirrelJME trace printing here
		CallTraceUtils.printStackTrace(__ps,
			String.format("Thread #%d: %s", this.id, this.name),
			this.getStackTrace(), null, null,
			0);
	}
	
	/**
	 * Sets the {@link Thread} instance.
	 *
	 * @param __object The object to set the instance to.
	 * @throws IllegalStateException If this thread already has an instance.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/17
	 */
	public final void setThreadInstance(SpringObject __object)
		throws IllegalStateException, NullPointerException
	{
		if (__object == null)
			throw new NullPointerException("NARG");
		
		synchronized (this)
		{


			// Only a single instance is permitted
			if (this._threadInstance != null)
				throw new IllegalStateException("Thread has an instance.");
			
			this._threadInstance = __object;
		}
	}
	
	/**
	 * Sets the virtual machine thread of this thread.
	 *
	 * @param __vmThread The thread to set.
	 * @throws IllegalStateException If this thread already has one.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/17
	 */
	public final void setVMThread(VMThreadObject __vmThread)
		throws IllegalStateException, NullPointerException
	{

		if (__vmThread == null)
			throw new NullPointerException("NARG");
		
		synchronized (this)
		{
			if (this._vmThread != null)
				throw new IllegalStateException("Thread has VM Thread.");
			
			this._vmThread = __vmThread;
		}
	}
	
	/**
	 * Terminates this thread.
	 * 
	 * @since 2020/06/29
	 */
	public final void terminate()
	{
		// Terminates this thread
		synchronized (this)
		{
			// Set as terminated
			this._terminate = true;
		}
		
		// Signal to the machine that this thread terminated
		SpringThreadWorker worker = this._worker;
		if (worker != null)
			worker.machine.signalThreadTerminate(this);
	}
	
	/**
	 * Returns the instance of the {@link Thread} object for this thread.
	 *
	 * @return The instance of {@link Thread}.
	 * @throws IllegalStateException If the thread has no instance.
	 * @since 2020/06/17
	 */
	public final SpringObject threadInstance()
		throws IllegalStateException
	{
		SpringObject rv;

		synchronized (this)

		{
			rv = this._threadInstance;
		}
		
		if (rv == null)
			throw new IllegalStateException("Thread has no state.");
		
		return rv;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/09/15
	 */
	@Override

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringThreadWorker.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


20

21
22
23

24
25
26
27
28
29
30
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.CallStackItem;
import cc.squirreljme.jvm.SystemCallError;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.runtime.cldc.asm.ConsoleOutput;
import cc.squirreljme.runtime.cldc.asm.SystemAccess;
import cc.squirreljme.runtime.cldc.asm.SystemProperties;
import cc.squirreljme.runtime.cldc.lang.ApiLevel;


import cc.squirreljme.runtime.cldc.lang.OperatingSystemType;

import cc.squirreljme.vm.VMClassLibrary;
import java.io.IOException;
import java.io.OutputStream;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.Map;
import net.multiphasicapps.classfile.ByteCode;
import net.multiphasicapps.classfile.ClassFlags;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.ConstantValue;












|
|
|
|
|
|
|
>
>
|
>
|
|
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.emulator.profiler.ProfiledFrame;
import cc.squirreljme.vm.springcoat.brackets.TypeObject;
import cc.squirreljme.vm.springcoat.exceptions.SpringArithmeticException;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassCastException;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassFormatException;
import cc.squirreljme.vm.springcoat.exceptions.SpringClassNotFoundException;
import cc.squirreljme.vm.springcoat.exceptions.SpringFatalException;
import cc.squirreljme.vm.springcoat.exceptions.SpringIllegalAccessException;
import cc.squirreljme.vm.springcoat.exceptions.SpringIncompatibleClassChangeException;
import cc.squirreljme.vm.springcoat.exceptions.SpringMachineExitException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNegativeArraySizeException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNoSuchFieldException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNoSuchMethodException;
import cc.squirreljme.vm.springcoat.exceptions.SpringNullPointerException;
import cc.squirreljme.vm.springcoat.exceptions.SpringVirtualMachineException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Map;
import net.multiphasicapps.classfile.ByteCode;
import net.multiphasicapps.classfile.ClassFlags;
import net.multiphasicapps.classfile.ClassName;
import net.multiphasicapps.classfile.ConstantValue;
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111

112
113
114
115
116



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
			throw new SpringVirtualMachineException("BK1x");
	}
	
	/**
	 * Allocates the memory needed to store an array of the given class and
	 * of the given length.
	 *
	 * @param __cl The component type.
	 * @param __l The length of the array.
	 * @return The allocated array.

	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/09/15
	 */
	public final SpringArrayObject allocateArray(SpringClass __cl, int __l)

		throws NullPointerException, SpringNegativeArraySizeException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		



		SpringClass dim = this.resolveClass(__cl.name().addDimensions(1));
		switch (__cl.name().toString())
		{
				// Boolean
			case "boolean":
				return new SpringArrayObjectBoolean(dim, __cl, __l);
			
				// Byte
			case "byte":
				return new SpringArrayObjectByte(dim, __cl, __l);
				
				// Short
			case "short":
				return new SpringArrayObjectShort(dim, __cl, __l);
				
				// Char
			case "char":
				return new SpringArrayObjectChar(dim, __cl, __l);
				
				// Int
			case "int":
				return new SpringArrayObjectInteger(dim, __cl, __l);
				
				// Long
			case "long":
				return new SpringArrayObjectLong(dim, __cl, __l);
				
				// Float
			case "float":
				return new SpringArrayObjectFloat(dim, __cl, __l);
				
				// Float
			case "double":
				return new SpringArrayObjectDouble(dim, __cl, __l);
			
				// Generic array
			default:
				return new SpringArrayObjectGeneric(dim, __cl, __l);
		}
		
	}
	
	/**
	 * Allocates the memory needed to store an object of the given class.
	 *
	 * @param __cl The object to allocate.
	 * @return The allocated instance of the object.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/08
	 */
	public final SpringObject allocateObject(SpringClass __cl)
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		// The called constructor will allocate the space needed to store
		// this object
		return new SpringSimpleObject(__cl, this.machine.pointers);
	}
	
	/**
	 * Converts the specified virtual machine object to a native object.
	 *
	 * @param __in The input object.
	 * @return The resulting native object.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringFatalException If the object cannot be translated.
	 * @since 2018/09/20
	 */
	public final Object asNativeObject(Object __in)
		throws NullPointerException, SpringFatalException
	{
		if (__in == null)
			throw new NullPointerException("NARG");
		
		// Is null refernece
		else if (__in == SpringNullObject.NULL)
			return null;
		
		// Boxed types remain the same
		else if (__in instanceof Integer || __in instanceof Long ||
			__in instanceof Float || __in instanceof Double)
			return __in;
		
		// Array type
		else if (__in instanceof SpringArrayObject)
		{
			SpringArrayObject sao = (SpringArrayObject)__in;
			
			int len = sao.length();
			
			// Depends on the array type
			SpringClass sscl = sao.type();
			ClassName type = sscl.name();
			switch (type.toString())
			{
					// Char array
				case "[C":
					{
						char[] rv = new char[len];
						
						for (int i = 0; i < len; i++)
							rv[i] = (char)(sao.<Integer>get(Integer.class, i).
								intValue());
						
						return rv;
					}
					
					// String
				case "[Ljava/lang/String;":
					{
						String[] rv = new String[len];
						
						for (int i = 0; i < len; i++)
							rv[i] = this.<String>asNativeObject(String.class,
								sao.<SpringObject>get(SpringObject.class, i));
						
						return rv;
					}
				
					// {@squirreljme.error BK1y Do not know how to convert the
					// given virtual machine array to a native machine array.
					// (The input class)}
				default:
					throw new RuntimeException(
						String.format("BK1y %s", type));
			}
		}
		
		// Class type
		else if (__in instanceof SpringSimpleObject)
		{
			SpringSimpleObject sso = (SpringSimpleObject)__in;
			
			// Depends on the class type







|


>





>
|




>
>
>
|
|



|



|



|



|



|



|



|



|



|




















|

















|









|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

213








































214
215
216
217
218
219
220
			throw new SpringVirtualMachineException("BK1x");
	}
	
	/**
	 * Allocates the memory needed to store an array of the given class and
	 * of the given length.
	 *
	 * @param __cl The array type.
	 * @param __l The length of the array.
	 * @return The allocated array.
	 * @throws IllegalArgumentException If the type is not an array.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringNegativeArraySizeException If the array size is negative.
	 * @since 2018/09/15
	 */
	public final SpringArrayObject allocateArray(SpringClass __cl, int __l)
		throws IllegalArgumentException, NullPointerException,
			SpringNegativeArraySizeException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		// This must be an array type
		if (!__cl.isArray())
			throw new IllegalArgumentException("Not an array: " + __cl);
		
		switch (__cl.componentType().name().toString())
		{
				// Boolean
			case "boolean":
				return new SpringArrayObjectBoolean(__cl, __l);
			
				// Byte
			case "byte":
				return new SpringArrayObjectByte(__cl, __l);
				
				// Short
			case "short":
				return new SpringArrayObjectShort(__cl, __l);
				
				// Char
			case "char":
				return new SpringArrayObjectChar(__cl, __l);
				
				// Int
			case "int":
				return new SpringArrayObjectInteger(__cl, __l);
				
				// Long
			case "long":
				return new SpringArrayObjectLong(__cl, __l);
				
				// Float
			case "float":
				return new SpringArrayObjectFloat(__cl, __l);
				
				// Float
			case "double":
				return new SpringArrayObjectDouble(__cl, __l);
			
				// Generic array
			default:
				return new SpringArrayObjectGeneric(__cl, __l);
		}
		
	}
	
	/**
	 * Allocates the memory needed to store an object of the given class.
	 *
	 * @param __cl The object to allocate.
	 * @return The allocated instance of the object.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/08
	 */
	public final SpringObject allocateObject(SpringClass __cl)
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		// The called constructor will allocate the space needed to store
		// this object
		return new SpringSimpleObject(__cl);
	}
	
	/**
	 * Converts the specified virtual machine object to a native object.
	 *
	 * @param __in The input object.
	 * @return The resulting native object.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringFatalException If the object cannot be translated.
	 * @since 2018/09/20
	 */
	public final Object asNativeObject(Object __in)
		throws NullPointerException, SpringFatalException
	{
		if (__in == null)
			throw new NullPointerException("NARG");
		
		// Is null reference
		else if (__in == SpringNullObject.NULL)
			return null;
		
		// Boxed types remain the same
		else if (__in instanceof Integer || __in instanceof Long ||
			__in instanceof Float || __in instanceof Double)
			return __in;
		
		// Array type
		if (__in instanceof SpringArrayObject)

			return ((SpringArrayObject)__in).array();








































		
		// Class type
		else if (__in instanceof SpringSimpleObject)
		{
			SpringSimpleObject sso = (SpringSimpleObject)__in;
			
			// Depends on the class type
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
		// {@squirreljme.error BK20 Do not know how to convert the given class
		// to a native machine object. (The input class)}
		else
			throw new SpringFatalException(
				String.format("BK20 %s", __in.getClass()));
	}
	
	/**
	 * Converts the specified object to a native object or unwraps an array
	 * for direct access.
	 *
	 * @param <C> The resulting class type.
	 * @param __cl The class to cast to.
	 * @param __in The input object.
	 * @return The resulting object.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/19
	 */
	public final <C> C asNativeObjectUnwrapArray(Class<C> __cl, Object __in)
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException();
		
		if (__in instanceof SpringArrayObject)
			return __cl.cast(((SpringArrayObject)__in).array());
		return this.<C>asNativeObject(__cl, __in);
	}
	
	/**
	 * Converts the specified virtual machine object to a native object.
	 *
	 * @param <C> The class type.
	 * @param __cl The class type.
	 * @param __in The input object.
	 * @return The resulting native object.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







246
247
248
249
250
251
252






















253
254
255
256
257
258
259
		// {@squirreljme.error BK20 Do not know how to convert the given class
		// to a native machine object. (The input class)}
		else
			throw new SpringFatalException(
				String.format("BK20 %s", __in.getClass()));
	}
	






















	/**
	 * Converts the specified virtual machine object to a native object.
	 *
	 * @param <C> The class type.
	 * @param __cl The class type.
	 * @param __in The input object.
	 * @return The resulting native object.
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372


373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
		else if (__in instanceof Integer || __in instanceof Long ||
			__in instanceof Float || __in instanceof Double ||
			__in instanceof SpringObject)
			return __in;
		
		// Boolean to integer
		else if (__in instanceof Boolean)
			return Integer.valueOf((Boolean.TRUE.equals(__in) ? 1 : 0));
		
		// Character to Integer
		else if (__in instanceof Character)
			return Integer.valueOf(((Character)__in).charValue());
		
		// Promoted to integer
		else if (__in instanceof Byte || __in instanceof Short)
			return Integer.valueOf(((Number)__in).intValue());
		
		// Character array
		else if (__in instanceof char[])
		{


			char[] in = (char[])__in;
			
			// Setup return array
			int n = in.length;
			SpringArrayObject rv = this.allocateArray(
				this.loadClass(new ClassName("char")), n);
			
			// Copy array values
			for (int i = 0; i < n; i++)
				rv.set(i, (int)in[i]);
			
			return rv;
		}
		
		// Integer array
		else if (__in instanceof int[])
		{
			int[] in = (int[])__in;
			
			// Setup return array
			int n = in.length;
			SpringArrayObject rv = this.allocateArray(
				this.loadClass(new ClassName("int")), n);
			
			// Copy array values
			for (int i = 0; i < n; i++)
				rv.set(i, (int)in[i]);
			
			return rv;
		}
		
		// String array
		else if (__in instanceof String[])
		{
			String[] in = (String[])__in;
			
			// Setup return array
			int n = in.length;
			SpringArrayObject rv = this.allocateArray(
				this.loadClass(new ClassName("java/lang/String")), n);
			
			// Copy array values
			for (int i = 0; i < n; i++)
				rv.set(i, this.asVMObject(in[i]));
			
			return rv;
		}
		
		// Convertable exception
		else if (__in instanceof SpringConvertableThrowable)
		{
			SpringConvertableThrowable e = (SpringConvertableThrowable)__in;
			
			// Initialize new instance with this type, use the input message
			return this.newInstance(new ClassName(e.targetClass()),
				new MethodDescriptor("(Ljava/lang/String;)V"),







|



|



|

|
|
<
>
>
|
|
<
|
<
<
|
<
<
<
|
|
|
|
<
|
<
<
<
<
<
|
|
|
<
<
<
<
<
<









|








|







299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

318
319
320
321

322


323



324
325
326
327

328





329
330
331






332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
		else if (__in instanceof Integer || __in instanceof Long ||
			__in instanceof Float || __in instanceof Double ||
			__in instanceof SpringObject)
			return __in;
		
		// Boolean to integer
		else if (__in instanceof Boolean)
			return (Boolean.TRUE.equals(__in) ? 1 : 0);
		
		// Character to Integer
		else if (__in instanceof Character)
			return (int)(Character)__in;
		
		// Promoted to integer
		else if (__in instanceof Byte || __in instanceof Short)
			return ((Number)__in).intValue();
		
		// An array type (not copied)
		else if (__in instanceof boolean[] ||

			__in instanceof byte[] ||
			__in instanceof short[] ||
			__in instanceof char[] ||
			__in instanceof int[] ||

			__in instanceof long[] ||


			__in instanceof float[] ||



			__in instanceof double[])
			return this.asWrappedArray(__in);
		
		// Object array type

		else if (__in instanceof SpringObject[])





			return new SpringArrayObjectGeneric(
				this.loadClass(new ClassName("java/lang/Object")),
				(SpringObject[])__in);






		
		// String array
		else if (__in instanceof String[])
		{
			String[] in = (String[])__in;
			
			// Setup return array
			int n = in.length;
			SpringArrayObject rv = this.allocateArray(
				this.loadClass(new ClassName("[Ljava/lang/String;")), n);
			
			// Copy array values
			for (int i = 0; i < n; i++)
				rv.set(i, this.asVMObject(in[i]));
			
			return rv;
		}
		
		// Convertible exception
		else if (__in instanceof SpringConvertableThrowable)
		{
			SpringConvertableThrowable e = (SpringConvertableThrowable)__in;
			
			// Initialize new instance with this type, use the input message
			return this.newInstance(new ClassName(e.targetClass()),
				new MethodDescriptor("(Ljava/lang/String;)V"),
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614

615



616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
			{
				// Pre-cached object already exists?
				SpringObject rv = com.get(name);
				if (rv != null)
					return rv;
				
				// Resolve the input class, so it is initialized
				SpringClass resclass = (__noclassres ? this.loadClass(name) :
					this.resolveClass(name));
				
				// Resolve the class object
				SpringClass classobj = this.resolveClass(
					new ClassName("java/lang/Class"));
				
				// Copy interfaces into a class array
				SpringClass[] interfaces = resclass.interfaceClasses();
				int ni = interfaces.length;
				SpringArrayObject ints = this.allocateArray(classobj, ni);
				for (int i = 0; i < ni; i++)
					ints.set(i, this.asVMObject(interfaces[i]));
				
				// See if there is a default constructor
				SpringMethod defconmeth = resclass.lookupDefaultConstructor();
				
				// Get static method for this constructor
				int defconflags;
				SpringObject defconsm;
				if (defconmeth != null)
				{
					defconflags = defconmeth.flags().toJavaBits();
					defconsm = new SpringVMStaticMethod(defconmeth);
				}
				
				// There is none
				else
				{
					defconflags = 0;
					defconsm = SpringNullObject.NULL;
				}
				
				// Get the static method for enumeration values
				ClassFlags classflags = resclass.flags();
				SpringObject enumsm;
				if (classflags.isEnum())
					try
					{
						enumsm = new SpringVMStaticMethod(
							resclass.lookupMethod(true,
							new MethodName("values"),
							new MethodDescriptor(name.addDimensions(1).
							field())));
					}
					catch (SpringIncompatibleClassChangeException e)
					{
						enumsm = SpringNullObject.NULL;
					}
				else
					enumsm = SpringNullObject.NULL;
				
				// Initialize V1 class data which is initialized with class
				// data
				SpringObject cdata = this.newInstance(new ClassName(
					"cc/squirreljme/runtime/cldc/lang/ClassDataV1"),
					new MethodDescriptor("(ILjava/lang/String;" +
						"Ljava/lang/Class;[Ljava/lang/Class;" +
						"Ljava/lang/Class;Ljava/lang/String;II" +
						"Lcc/squirreljme/runtime/cldc/asm/StaticMethod;" +
						"Lcc/squirreljme/runtime/cldc/asm/StaticMethod;)V"),
					resclass.specialIndex(),
					this.asVMObject(name.toString(), true),
					this.asVMObject(resclass.superClass(), true),
					ints,
					(!resclass.isArray() ? SpringNullObject.NULL :
						this.asVMObject(resclass.componentType(), true)),
					this.asVMObject(resclass.inJar()),
					classflags.toJavaBits(),
					defconflags, defconsm, enumsm);
				
				// Initialize class with special class index and some class
				// information
				rv = this.newInstance(classobj.name(),
					new MethodDescriptor(
					"(Lcc/squirreljme/runtime/cldc/lang/ClassData;)V"), cdata);

				
				// Cache and use it
				com.put(name, rv);
				ocm.put(rv, name);
				return rv;
			}
		}
		
		// {@squirreljme.error BK21 Do not know how to convert the given class
		// to a virtual machine object. (The input class)}
		else
			throw new RuntimeException(
				String.format("BK21 %s", __in.getClass()));
	}
	
	/**
	 * As VM object, but boxed if a primitive.
	 *
	 * @param __in The object to convert.

	 * @return The converted object.



	 * @since 2018/11/19
	 */
	public final Object asVMObjectBoxed(Object __in)
	{
		// Null is converted to null
		if (__in == null)
			return SpringNullObject.NULL;
		
		// Box these
		else if (__in instanceof Integer)
			return this.newInstance(new ClassName("java/lang/Integer"),
				new MethodDescriptor("(I)V"), __in);
		else if (__in instanceof Long)
			return this.newInstance(new ClassName("java/lang/Long"),
				new MethodDescriptor("(J)V"), __in);
		else if (__in instanceof Float)
			return this.newInstance(new ClassName("java/lang/Float"),
				new MethodDescriptor("(F)V"), __in);
		else if (__in instanceof Double)
			return this.newInstance(new ClassName("java/lang/Double"),
				new MethodDescriptor("(D)V"), __in);
		
		// As-is
		else if (__in instanceof SpringObject)
			return __in;
		
		else
			return this.asVMObject(__in);
	}
	
	/**
	 * As VM object, if it is an array it is wrapped otherwise if the object is
	 * a primitive type it becomes boxed.
	 *
	 * @param __in The object to convert.
	 * @return The converted object.
	 * @since 2018/12/03
	 */
	public final Object asVMObjectBoxedOrWrappedArray(Object __in)
	{
		if (__in == null)
			return SpringNullObject.NULL;
		
		// Array types
		else if (__in instanceof boolean[] ||
			__in instanceof byte[] ||
			__in instanceof short[] ||
			__in instanceof char[] ||
			__in instanceof int[] ||
			__in instanceof long[] ||
			__in instanceof float[] ||
			__in instanceof double[])
			return this.asWrappedArray(__in);
		
		// As boxed type instead
		else
			return this.asVMObjectBoxed(__in);
	}
	
	/**
	 * Wraps the native array so that it is directly read and written in
	 * the VM code.
	 *
	 * @param __a The object to convert.







|



|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
<
|
>
















|

|
>
|
>
>
>
|

|
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
|
<
<
|
|
<
<
|
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<

<
<
|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
































































456
457
458

459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487



488
489













490

491

492


493
494


495









496
497









498


499
500
501
502
503
504
505
506
			{
				// Pre-cached object already exists?
				SpringObject rv = com.get(name);
				if (rv != null)
					return rv;
				
				// Resolve the input class, so it is initialized
				SpringClass resClass = (__noclassres ? this.loadClass(name) :
					this.resolveClass(name));
				
				// Resolve the class object
				SpringClass classClass = this.resolveClass(
					new ClassName("java/lang/Class"));
				
































































				// Initialize class with special class index and some class
				// information
				rv = this.newInstance(classClass.name(), new MethodDescriptor(

					"(Lcc/squirreljme/jvm/mle/brackets/TypeBracket;)V"),
					new TypeObject(resClass));
				
				// Cache and use it
				com.put(name, rv);
				ocm.put(rv, name);
				return rv;
			}
		}
		
		// {@squirreljme.error BK21 Do not know how to convert the given class
		// to a virtual machine object. (The input class)}
		else
			throw new RuntimeException(
				String.format("BK21 %s", __in.getClass()));
	}
	
	/**
	 * Creates an array from the given elements.
	 *
	 * @param __type The array type.
	 * @param __elements The elements to be in the array.
	 * @return The array.
	 * @throws IllegalArgumentException If the type is not an array that is
	 * compatible with objects.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/12
	 */
	public final SpringArrayObjectGeneric asVMObjectArray(SpringClass __type,



		SpringObject... __elements)
		throws IllegalArgumentException, NullPointerException













	{

		if (__type == null)

			throw new NullPointerException("NARG");


		
		// Prevent invalid arrays from being wrapped


		if (!__type.isArray() || __type.componentType().name().isPrimitive())









			throw new IllegalArgumentException("Cannot have object array " +
				"that is not an array or primitive type: " + __type);









		


		return new SpringArrayObjectGeneric(__type, __elements);
	}
	
	/**
	 * Wraps the native array so that it is directly read and written in
	 * the VM code.
	 *
	 * @param __a The object to convert.
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
		if (__a == null)
			return SpringNullObject.NULL;
		
		// Boolean
		else if (__a instanceof boolean[])
			return new SpringArrayObjectBoolean(
				this.loadClass(new ClassName("[Z")),
				this.loadClass(new ClassName("boolean")),
				(boolean[])__a);
		
		// Byte
		else if (__a instanceof byte[])
			return new SpringArrayObjectByte(
				this.loadClass(new ClassName("[B")),
				this.loadClass(new ClassName("byte")),
				(byte[])__a);
		
		// Short
		else if (__a instanceof short[])
			return new SpringArrayObjectShort(
				this.loadClass(new ClassName("[S")),
				this.loadClass(new ClassName("short")),
				(short[])__a);
		
		// Character
		else if (__a instanceof char[])
			return new SpringArrayObjectChar(
				this.loadClass(new ClassName("[C")),
				this.loadClass(new ClassName("char")),
				(char[])__a);
		
		// Integer
		else if (__a instanceof int[])
			return new SpringArrayObjectInteger(
				this.loadClass(new ClassName("[I")),
				this.loadClass(new ClassName("int")),
				(int[])__a);
		
		// Long
		else if (__a instanceof long[])
			return new SpringArrayObjectLong(
				this.loadClass(new ClassName("[J")),
				this.loadClass(new ClassName("long")),
				(long[])__a);
		
		// Float
		else if (__a instanceof float[])
			return new SpringArrayObjectFloat(
				this.loadClass(new ClassName("[F")),
				this.loadClass(new ClassName("float")),
				(float[])__a);
		
		// Double
		else if (__a instanceof double[])
			return new SpringArrayObjectDouble(
				this.loadClass(new ClassName("[D")),
				this.loadClass(new ClassName("double")),
				(double[])__a);
		
		// {@squirreljme.error BK22 Cannot wrap this as a native array.
		// (The input class type)}
		else
			throw new RuntimeException("BK22 " + __a.getClass());
	}







<






<






<






<






<






<






<






<







514
515
516
517
518
519
520

521
522
523
524
525
526

527
528
529
530
531
532

533
534
535
536
537
538

539
540
541
542
543
544

545
546
547
548
549
550

551
552
553
554
555
556

557
558
559
560
561
562

563
564
565
566
567
568
569
		if (__a == null)
			return SpringNullObject.NULL;
		
		// Boolean
		else if (__a instanceof boolean[])
			return new SpringArrayObjectBoolean(
				this.loadClass(new ClassName("[Z")),

				(boolean[])__a);
		
		// Byte
		else if (__a instanceof byte[])
			return new SpringArrayObjectByte(
				this.loadClass(new ClassName("[B")),

				(byte[])__a);
		
		// Short
		else if (__a instanceof short[])
			return new SpringArrayObjectShort(
				this.loadClass(new ClassName("[S")),

				(short[])__a);
		
		// Character
		else if (__a instanceof char[])
			return new SpringArrayObjectChar(
				this.loadClass(new ClassName("[C")),

				(char[])__a);
		
		// Integer
		else if (__a instanceof int[])
			return new SpringArrayObjectInteger(
				this.loadClass(new ClassName("[I")),

				(int[])__a);
		
		// Long
		else if (__a instanceof long[])
			return new SpringArrayObjectLong(
				this.loadClass(new ClassName("[J")),

				(long[])__a);
		
		// Float
		else if (__a instanceof float[])
			return new SpringArrayObjectFloat(
				this.loadClass(new ClassName("[F")),

				(float[])__a);
		
		// Double
		else if (__a instanceof double[])
			return new SpringArrayObjectDouble(
				this.loadClass(new ClassName("[D")),

				(double[])__a);
		
		// {@squirreljme.error BK22 Cannot wrap this as a native array.
		// (The input class type)}
		else
			throw new RuntimeException("BK22 " + __a.getClass());
	}
988
989
990
991
992
993
994






















995
996
997
998

999
1000
1001
1002
1003
1004
1005
	/**
	 * Loads the specified class, potentially performing initialization on it
	 * if it has not been initialized.
	 *
	 * @param __cn The class to load.
	 * @return The loaded class.
	 * @throws NullPointerException On null arguments.






















	 * @since 2018/09/08
	 */
	public final SpringClass loadClass(ClassName __cn)
		throws NullPointerException

	{
		if (__cn == null)
			throw new NullPointerException("NARG");
		
		// Use the class loading lock to prevent other threads from loading or
		// initializing classes while this thread does such things
		SpringClassLoader classloader = this.machine.classLoader();







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
>







807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
	/**
	 * Loads the specified class, potentially performing initialization on it
	 * if it has not been initialized.
	 *
	 * @param __cn The class to load.
	 * @return The loaded class.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringClassFormatException If the class is not formatted
	 * properly.
	 * @throws SpringClassNotFoundException If the class was not found.
	 * @since 2020/06/17
	 */
	public final SpringClass loadClass(String __cn)
		throws NullPointerException, SpringClassFormatException,
			SpringClassNotFoundException
	{
		return this.loadClass(new ClassName(__cn));
	}
	
	/**
	 * Loads the specified class, potentially performing initialization on it
	 * if it has not been initialized.
	 *
	 * @param __cn The class to load.
	 * @return The loaded class.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringClassFormatException If the class is not formatted
	 * properly.
	 * @throws SpringClassNotFoundException If the class was not found.
	 * @since 2018/09/08
	 */
	public final SpringClass loadClass(ClassName __cn)
		throws NullPointerException, SpringClassFormatException,
			SpringClassNotFoundException
	{
		if (__cn == null)
			throw new NullPointerException("NARG");
		
		// Use the class loading lock to prevent other threads from loading or
		// initializing classes while this thread does such things
		SpringClassLoader classloader = this.machine.classLoader();
1101
1102
1103
1104
1105
1106
1107

1108
1109
1110
1111
1112
1113
1114

1115
1116
1117
1118





















1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
	
	/**
	 * Handles a native action within the VM.
	 *
	 * Note that the return value should be a native type, it is translated
	 * as needed.
	 *

	 * @param __func The function to call.
	 * @param __args The arguments to the function.
	 * @return The result from the call.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/16
	 */
	public final Object nativeMethod(String __func, Object... __args)

		throws NullPointerException
	{
		if (__func == null || __args == null)
			throw new NullPointerException("NARG");





















		
		// Debug
		/*todo.DEBUG.note("Call native %s", __func);*/
		
		// Depends on the function
		switch (__func)
		{
				// Return the length of the array
			case "cc/squirreljme/jvm/Assembly::" +
				"arrayLength:(Ljava/lang/Object;)I":
				return ((SpringArrayObject)__args[0]).length();
				
				// Pack double together
			case "cc/squirreljme/jvm/Assembly::" +
				"doublePack:(II)D":
				return Double.longBitsToDouble(
					((((Integer)__args[0]).longValue() << 32L) |
					((((Integer)__args[1]).longValue()) & 0xFFFFFFFFL)));
				
				// Gets the raw bits for the given double value
			case "cc/squirreljme/jvm/Assembly::" +
				"doubleToRawLongBits:(D)J":
				return Double.doubleToRawLongBits((Double)__args[0]);
				
				// Float to raw int bits
			case "cc/squirreljme/jvm/Assembly::" +
				"floatToRawIntBits:(F)I":
				return Float.floatToRawIntBits((Float)__args[0]);
				
				// Int bits to float
			case "cc/squirreljme/jvm/Assembly::" +
				"intBitsToFloat:(I)F":
				return Float.intBitsToFloat((Integer)__args[0]);
				
				// Convert long bits to double
			case "cc/squirreljme/jvm/Assembly::" +
				"longBitsToDouble:(J)D":
				return Double.longBitsToDouble((Long)__args[0]);
				
				// Pack long together
			case "cc/squirreljme/jvm/Assembly::" +
				"longPack:(II)J":
				return ((((Integer)__args[0]).longValue() << 32L) |
					((((Integer)__args[1]).longValue()) & 0xFFFFFFFFL));
				
				// Unpack high long
			case "cc/squirreljme/jvm/Assembly::" +
				"longUnpackHigh:(L)I":
				return (int)((((Long)__args[0]).longValue()) >>> 32L);
				
				// Unpack low long
			case "cc/squirreljme/jvm/Assembly::" +
				"longUnpackLow:(L)I":
				return (int)(((Long)__args[0]).longValue());
				
				// Object to pointer
			case "cc/squirreljme/jvm/Assembly::" +
				"objectToPointer:(Ljava/lang/Object;)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"objectToPointerRefQueue:(Ljava/lang/Object;)I":
				return this.uniqueObjectToPointer((SpringObject)__args[0]);
				
				// Pointer to object
			case "cc/squirreljme/jvm/Assembly::" +
				"pointerToObject:(I)Ljava/lang/Object;":
				return this.uniquePointerToObject((Integer)__args[0]);
				
				// System calls (no return value)
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(S)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(SI)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(SII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(SIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(SIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(SIIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(SIIIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(SIIIIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCall:(SIIIIIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(S)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(SI)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(SII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(SIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(SIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(SIIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(SIIIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(SIIIIIII)V":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallP:(SIIIIIIII)V":
				{
					// System call index and number of arguments used
					int si = (Integer)__args[0],
						na = __args.length - 1;
					
					// Copy argument values to integers
					int[] ta = new int[na];
					for (int i = 1, o = 0; o < na; i++, o++)
						ta[o] = (Integer)__args[i];
					
					// Do system call handler
					this.systemCall((short)si, ta);
					return null;
				}
				
				// System calls (returns value)
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(S)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(SI)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(SII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(SIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(SIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(SIIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(SIIIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(SIIIIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallV:(SIIIIIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(S)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(SI)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(SII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(SIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(SIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(SIIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(SIIIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(SIIIIIII)I":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPV:(SIIIIIIII)I":
				{
					// System call index and number of arguments used
					int si = (Integer)__args[0],
						na = __args.length - 1;
					
					// Copy argument values to integers
					int[] ta = new int[na];
					for (int i = 1, o = 0; o < na; i++, o++)
						ta[o] = (Integer)__args[i];
					
					// Do system call handler
					return (int)this.systemCall((short)si, ta);
				}
				
				// System calls (returns long value)
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(S)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(SI)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(SII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(SIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(SIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(SIIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(SIIIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(SIIIIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallVL:(SIIIIIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(S)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(SI)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(SII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(SIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(SIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(SIIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(SIIIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(SIIIIIII)J":
			case "cc/squirreljme/jvm/Assembly::" +
				"sysCallPVL:(SIIIIIIII)J":
				{
					// System call index and number of arguments used
					int si = (Integer)__args[0],
						na = __args.length - 1;
					
					// Copy argument values to integers
					int[] ta = new int[na];
					for (int i = 1, o = 0; o < na; i++, o++)
						ta[o] = (Integer)__args[i];
					
					// Do system call handler
					return (long)this.systemCall((short)si, ta);
				}
			
				// Read console buffer
			case "cc/squirreljme/runtime/cldc/asm/ConsoleOutput::" +
				"displayRead:([I[BII)I":
				return 0;
				
				// Flush the console
			case "cc/squirreljme/runtime/cldc/asm/ConsoleOutput::" +
				"flush:(I)I":
				{
					int fd = (Integer)__args[0];
					PrintStream to = (fd == ConsoleOutput.OUTPUT ?
						System.out : (fd == ConsoleOutput.ERROR ?
						System.err : null));
					
					// Flush if valid
					if (to != null)
					{
						to.flush();
						return 0;
					}
					else
						return ConsoleOutput.ERROR_INVALIDFD;
				}
			
				// Write to the console
			case "cc/squirreljme/runtime/cldc/asm/ConsoleOutput::" +
				"write:(II)I":
				{
					int fd = (Integer)__args[0];
					PrintStream to = (fd == ConsoleOutput.OUTPUT ?
						System.out : (fd == ConsoleOutput.ERROR ?
						System.err : null));
					
					// Write if it exists
					if (to != null)
					{
						to.write((Integer)__args[1]);
						return 0;
					}
					else
						return ConsoleOutput.ERROR_INVALIDFD;
				}
				
				// Write to the console (bulk)
			case "cc/squirreljme/runtime/cldc/asm/ConsoleOutput::" +
				"write:(I[BII)I":
				{
					int fd = (Integer)__args[0];
					PrintStream to = (fd == ConsoleOutput.OUTPUT ?
						System.out : (fd == ConsoleOutput.ERROR ?
						System.err : null));
					
					// Write if it exists
					if (to != null)
					{
						to.write(
							(byte[])((SpringArrayObjectByte)__args[1]).array(),
							(Integer)__args[2],
							(Integer)__args[3]);
						return 0;
					}
					else
						return ConsoleOutput.ERROR_INVALIDFD;
				}
				
				// Allocate object but do not construct it
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"allocateObject:(Ljava/lang/String;)Ljava/lang/Object;":
				return this.allocateObject(this.loadClass(
					new ClassName(this.<String>asNativeObject(
					String.class, ((SpringObject)__args[0])))));
			
				// Allocate array of a given class
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"arrayNew:(Ljava/lang/Class;I)Ljava/lang/Object;":
				{
					// Cannot do a reverse lookup
					SpringMachine machine = this.machine;
					Map<SpringObject, ClassName> ocm = machine.
						__classObjectToNameMap();
					synchronized (machine.classLoader().classLoadingLock())
					{
						// {@squirreljme.error BK24 Could not reverse class
						// object to class name.}
						ClassName cn = ocm.get((SpringObject)__args[0]);
						if (cn == null)
							throw new SpringVirtualMachineException("BK24");
						
						// Lookup class for the component type, we need it
						SpringClass cl = this.loadClass(cn.componentType());
						
						// Allocate array for the component type
						return this.allocateArray(cl,
							(Integer)__args[1]);
					}
				}
			
				// Get the class by the name of whatever is input
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"classByName:(Ljava/lang/String;)Ljava/lang/Class;":
				try
				{
					return this.asVMObject(new ClassName(
						this.<String>asNativeObject(String.class,
						(SpringObject)__args[0])), true);
				}
				catch (SpringClassNotFoundException e)
				{
					return this.asVMObject(null);
				}
				
				// Returns the class data for a class object
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"classData:(Ljava/lang/Class;)Lcc/squirreljme/" +
				"runtime/cldc/lang/ClassData;":
				return this.invokeMethod(false,
					new ClassName("java/lang/Class"),
					new MethodNameAndType("__classData",
					"()Lcc/squirreljme/runtime/cldc/lang/ClassData;"),
					(SpringObject)__args[0]);
				
				// Get the class object for an object
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"classOf:(Ljava/lang/Object;)Ljava/lang/Class;":
				{
					// Just use the input class of the type
					SpringObject so = (SpringObject)__args[0];
					return so.type();
				}
				
				// Check if thread holds the given lock
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"holdsLock:(ILjava/lang/Object;)Z":
				{
					SpringThread owner =
						((SpringObject)__args[1]).monitor()._owner;
					return (owner == null ? false :
						((Integer)__args[0]).intValue() == owner.id);
				}
				
				// Identity hash code
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"identityHashCode:(Ljava/lang/Object;)I":
				return System.identityHashCode(((SpringObject)__args[0]));
				
				// Invoke static method
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"invokeStatic:(Lcc/squirreljme/runtime/cldc/asm/" +
				"StaticMethod;[Ljava/lang/Object;)Ljava/lang/Object;":
				{
					// We will need this to pass object arguments
					SpringArrayObject vargs = (SpringArrayObject)__args[1];
					
					// Copy object values
					int n = vargs.length();
					Object[] xargs = new Object[n];
					for (int i = 0; i < n; i++)
						xargs[i] = vargs.get(Object.class, i);
					
					// The method to execute
					SpringMethod m = ((SpringVMStaticMethod)__args[0]).method;
					
					// Enter the frame for this method
					this.thread.enterFrame(m, xargs);
					
					// If the method has no return value, just push a null to
					// the stack
					if (!m.nameAndType().type().hasReturnValue())
						return SpringNullObject.NULL;
					
					// No return value, sort of
					return null;
				}
				
				// Monitor notify
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"monitorNotify:(Ljava/lang/Object;Z)I":
				return ((SpringObject)__args[0]).monitor().
					monitorNotify(this.thread,
					((Integer)__args[1]).intValue() != 0);
			
				// Monitor notify
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"monitorWait:(Ljava/lang/Object;JI)I":
				return ((SpringObject)__args[0]).monitor().
					monitorWait(this.thread, (Long)__args[1],
						(Integer)__args[2]);
				
				// Create new primitive weak reference
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"newWeakReference:" +
				"()Lcc/squirreljme/runtime/cldc/ref/PrimitiveReference;":
				{
					return new SpringPrimitiveWeakReference();
				}
				
				// Get reference
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"referenceGet:(Lcc/squirreljme/runtime/cldc/ref/" +
				"PrimitiveReference;)Ljava/lang/Object;":
				return ((SpringPrimitiveReference)__args[0]).get();
				
				// Set reference
			case "cc/squirreljme/runtime/cldc/asm/ObjectAccess::" +
				"referenceSet:(Lcc/squirreljme/runtime/cldc/ref/" +
				"PrimitiveReference;Ljava/lang/Object;)V":
				((SpringPrimitiveReference)__args[0]).set(
					(SpringObject)__args[1]);
				return null;
				
				// Returns the number of bytes available in the resource.
			case "cc/squirreljme/runtime/cldc/asm/ResourceAccess::" +
				"available:(I)I":
				return this.machine.resourceAccess().available(
					(Integer)__args[0]);
				
				// Close resource in JAR
			case "cc/squirreljme/runtime/cldc/asm/ResourceAccess::" +
				"close:(I)I":
				return this.machine.resourceAccess().close(
					(Integer)__args[0]);
				
				// Open resource in JAR
			case "cc/squirreljme/runtime/cldc/asm/ResourceAccess::" +
				"open:(Ljava/lang/String;Ljava/lang/String;)I":
				return this.machine.resourceAccess().open(
					this.<String>asNativeObject(String.class, __args[0]),
					this.<String>asNativeObject(String.class, __args[1]));
				
				// Read resource in JAR
			case "cc/squirreljme/runtime/cldc/asm/ResourceAccess::" +
				"read:(I[BII)I":
				return this.machine.resourceAccess().read(
					(Integer)__args[0],
					(byte[])((SpringArrayObjectByte)__args[1]).array(),
					(Integer)__args[2],
					(Integer)__args[3]);
			
				// List suites that are available
			case "cc/squirreljme/runtime/cldc/asm/SuiteAccess::" +
				"availableSuites:()[Ljava/lang/String;":
				return this.machine.suiteManager().listLibraryNames();
			
				// List current class path
			case "cc/squirreljme/runtime/cldc/asm/SuiteAccess::" +
				"currentClassPath:()[Ljava/lang/String;":
				{
					VMClassLibrary[] vp = this.machine.classloader.classPath();
					int n = vp.length;
					String[] rv = new String[n];
					for (int i = 0; i < n; i++)
						rv[i] = vp[i].name();
					return this.asVMObject(rv);
				}
				
				// Get environment variable
			case "cc/squirreljme/runtime/cldc/asm/SystemAccess::" +
				"getEnv:(Ljava/lang/String;)Ljava/lang/String;":
				return this.asVMObject(SystemAccess.getEnv(
					this.<String>asNativeObject(String.class, __args[0])));
			
				// Approximated executable path
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"executablePath:()Ljava/lang/String;":
				// Just use the one of the host VM, if it is known anyway
				return this.asVMObject(SystemProperties.executablePath());
				
				// The guest depth of this virtual machine
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"guestDepth:()I":
				return this.machine.guestdepth;
				
				// The class to use for an implementation of something, by
				// default
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"implementationClass:(Ljava/lang/String;)Ljava/lang/String;":
				return SpringNullObject.NULL;
				
				// VM e-mail
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"javaVMEmail:()Ljava/lang/String;":
				return "xerthesquirrel@gmail.com";
				
				// VM name
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"javaVMName:()Ljava/lang/String;":
				return "SquirrelJME SpringCoat";
				
				// VM URL
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"javaVMURL:()Ljava/lang/String;":
				return "http://squirreljme.cc/";
				
				// VM vendor
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"javaVMVendor:()Ljava/lang/String;":
				return "Stephanie Gawroriski";
				
				// VM Version
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"javaVMVersion:()Ljava/lang/String;":
				return "0.2.0";
				
				// Get the operating system type
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"operatingSystemType:()I":
				return OperatingSystemType.UNKNOWN;
				
				// Get system property
			case "cc/squirreljme/runtime/cldc/asm/SystemProperties::" +
				"systemProperty:(Ljava/lang/String;)Ljava/lang/String;":
				String pk = this.<String>asNativeObject(String.class,
					__args[0]),
					pv = this.machine._sysproperties.get(pk);
				if (pv != null)
					return pv;
				return System.getProperty(pk);
				
				// Current thread ID
			case "cc/squirreljme/runtime/cldc/asm/TaskAccess::" +
				"currentThread:()I":
				return this.thread.id;
				
				// Set thread priority
			case "cc/squirreljme/runtime/cldc/asm/TaskAccess::" +
				"setThreadPriority:(II)V":
				{
					SpringThread st = this.machine.getThread(
						(Integer)__args[0]);
					if (st != null)
					{
						SpringThreadWorker stw = st._worker;
						if (stw != null)
						{
							Thread signal = stw.signalinstead;
							if (signal != null)
								signal.setPriority((Integer)__args[1]);
							else
								stw.setPriority((Integer)__args[1]);
						}
					}
					
					return null;
				}
				
				// Interrupt the given thread
			case "cc/squirreljme/runtime/cldc/asm/TaskAccess::" +
				"signalInterrupt:(I)V":
				{
					SpringThread st = this.machine.getThread(
						(Integer)__args[0]);
					if (st != null)
					{
						SpringThreadWorker stw = st._worker;
						if (stw != null)
						{
							Thread signal = stw.signalinstead;
							if (signal != null)
								signal.interrupt();
							else
								stw.interrupt();
						}
					}
					
					return null;
				}
				
				// Sleep
			case "cc/squirreljme/runtime/cldc/asm/TaskAccess::" +
				"sleep:(JI)Z":
				try
				{
					long ms = (Long)__args[0];
					int ns = (Integer)__args[1];
					
					// Zero time is a yield
					if (ms == 0 && ns == 0)
						Thread.yield();
					
					// Otherwise sleep for given time
					else
						Thread.sleep(ms, ns);
					return 0;
				}
				catch (InterruptedException e)
				{
					return 1;
				}
				
				// Start Task
			case "cc/squirreljme/runtime/cldc/asm/TaskAccess::" +
				"startTask:([Ljava/lang/String;Ljava/lang/String;" +
				"[Ljava/lang/String;)I":
			case "cc/squirreljme/runtime/cldc/asm/TaskAccess::" +
				"startTask:([Ljava/lang/String;Ljava/lang/String;" +
				"[Ljava/lang/String;[Ljava/lang/String;" +
				"Lcc/squirreljme/runtime/cldc/asm/ConsoleCallback;" +
				"Lcc/squirreljme/runtime/cldc/asm/ConsoleCallback;)I":
				return this.machine.taskManager().startTask(
					this.<String[]>asNativeObject(String[].class, __args[0]),
					this.<String>asNativeObject(String.class, __args[1]),
					this.<String[]>asNativeObject(String[].class, __args[2]),
					this.machine.guestdepth);
				
				// Start Thread
			case "cc/squirreljme/runtime/cldc/asm/TaskAccess::" +
				"startThread:(Ljava/lang/Thread;Ljava/lang/String;)I":
				{
					// Create thread
					String name;
					SpringThread thread = this.machine.createThread(
						(name = this.<String>asNativeObject(String.class,
							__args[1])));
					
					// Enter Thread's `__start()`
					SpringObject throbj = (SpringObject)__args[0];
					thread.enterFrame(this.resolveClass(
						new ClassName("java/lang/Thread")).lookupMethod(false,
						new MethodNameAndType("__start", "()V")), throbj);
					
					// Create worker for this thread
					SpringThreadWorker worker = new SpringThreadWorker(
						this.machine, thread, false);
					worker.start();
					
					// Return this thread ID
					return thread.id;
				}
				
				// Task status
			case "cc/squirreljme/runtime/cldc/asm/TaskAccess::" +
				"taskStatus:(I)I":
				return this.machine.taskManager().taskStatus(
					(Integer)__args[0]);
				
				// {@squirreljme.error BK25 Unknown native function. (The
				// native function)}
			default:
				throw new SpringVirtualMachineException(
					String.format("BK25 %s", __func));
		}
	}
	
	/**
	 * Creates a new instance of the given class and initializes it using the
	 * given arguments. Access checks are ignored.
	 *
	 * @param __cl The class to initialize.







>
|





|
>


|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987

















































































































































































































































































































































988








989























































































































































































































































































































990
991
992
993
994
995
996
	
	/**
	 * Handles a native action within the VM.
	 *
	 * Note that the return value should be a native type, it is translated
	 * as needed.
	 *
	 * @param __class The class the function is in.
	 * @param __method The method being called.
	 * @param __args The arguments to the function.
	 * @return The result from the call.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/16
	 */
	public final Object nativeMethod(ClassName __class,
		MethodNameAndType __method, Object... __args)
		throws NullPointerException
	{
		if (__class == null || __method == null || __args == null)
			throw new NullPointerException("NARG");
		
		// All low-level calls are considered invalid in SpringCoat because
		// it does not have the given functionality.
		if (__class.toString().startsWith("cc/squirreljme/jvm/Assembly") ||
			__class.toString().startsWith("cc/squirreljme/jvm/mle/lle/"))
			throw new SpringVirtualMachineException(String.format(
				"Invalid LLE native call: %s %s", __class,
				Arrays.asList(__args)));
		
		// Do not allow the older SpringCoat "asm" classes to be called as
		// the interfaces are very different with the MLE layer.
		if (__class.toString().startsWith("cc/squirreljme/runtime/cldc/asm/"))
			throw new SpringVirtualMachineException(String.format(
				"Old-SpringCoat native call: %s %s", __class,
				Arrays.asList(__args)));
		
		// Only allow mid-level native calls
		if (!__class.toString().startsWith("cc/squirreljme/jvm/mle/"))
			throw new SpringVirtualMachineException(String.format(
				"Non-MLE native call: %s %s", __class,
				Arrays.asList(__args)));
		
		// Debug
		/*Debugging.debugNote("Call native %s::%s %s", __class, __method,
			Arrays.asList(__args));*/

















































































































































































































































































































































		








		return MLEDispatcher.dispatch(this, __class, __method, __args);























































































































































































































































































































	}
	
	/**
	 * Creates a new instance of the given class and initializes it using the
	 * given arguments. Access checks are ignored.
	 *
	 * @param __cl The class to initialize.
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
		if (__cl == null || __desc == null || __args == null)
			throw new NullPointerException("NARG");
		
		// Make sure this class is loaded
		__cl = this.loadClass(__cl);
		
		// Lookup constructor to this method
		SpringMethod cons = __cl.lookupMethod(false, new MethodName("<init>"),
			__desc);
		
		// Allocate the object
		SpringObject rv = this.allocateObject(__cl);
			
		// Stop execution when the constructor exits
		SpringThread thread = this.thread;
		int framelimit = thread.numFrames();







|
|







1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
		if (__cl == null || __desc == null || __args == null)
			throw new NullPointerException("NARG");
		
		// Make sure this class is loaded
		__cl = this.loadClass(__cl);
		
		// Lookup constructor to this method
		SpringMethod cons = __cl.lookupMethod(false,
			new MethodName("<init>"), __desc);
		
		// Allocate the object
		SpringObject rv = this.allocateObject(__cl);
			
		// Stop execution when the constructor exits
		SpringThread thread = this.thread;
		int framelimit = thread.numFrames();
1845
1846
1847
1848
1849
1850
1851















1852
1853
1854
1855
1856
1857
1858
		
		// Execute until it finishes
		this.run(framelimit);
		
		// Return the resulting object
		return rv;
	}















	
	/**
	 * Resolves the given class, checking access.
	 *
	 * @param __cl The class to resolve.
	 * @return The resolved class.
	 * @throws NullPointerException On null arguments.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
		
		// Execute until it finishes
		this.run(framelimit);
		
		// Return the resulting object
		return rv;
	}
	
	/**
	 * Resolves the given class, checking access.
	 *
	 * @param __cl The class to resolve.
	 * @return The resolved class.
	 * @throws NullPointerException On null arguments.
	 * @throws SpringIllegalAccessException If the class cannot be accessed.
	 * @since 2020/06/17
	 */
	public final SpringClass resolveClass(String __cl)
		throws NullPointerException, SpringIllegalAccessException
	{
		return this.resolveClass(new ClassName(__cl));
	}
	
	/**
	 * Resolves the given class, checking access.
	 *
	 * @param __cl The class to resolve.
	 * @return The resolved class.
	 * @throws NullPointerException On null arguments.
1916
1917
1918
1919
1920
1921
1922
1923



1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943



1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977



1978








1979



1980























1981
1982
1983
1984
1985
1986
1987
				this.__singleStep();
			}
		}
		
		// If the VM is exiting then clear the execution stack before we go
		// away
		catch (SpringMachineExitException e)
		{



			// Thread is okay to exit!
			thread._terminate = true;
			thread._signaledexit = true;
			
			// Exit all frames
			thread.exitAllFrames();
			
			// Exit profiler stack
			thread.profiler.exitAll(System.nanoTime());
			
			// Do not rethrow though
			return;
		}
		
		// Caught exception
		catch (RuntimeException e)
		{
			// Frame limit is zero, so kill the thread
			if (__framelimit == 0)
			{



				PrintStream err = System.err;
				
				err.println("****************************");
				
				// Print the real stack trace
				err.println("*** EXTERNAL STACK TRACE ***");
				e.printStackTrace(err);
				err.println();
				
				// Print the VM seen stack trace
				err.println("*** INTERNAL STACK TRACE ***");
				thread.printStackTrace(err);
				err.println();
				
				err.println("****************************");
				
				// Terminate the thread
				thread._terminate = true;
				
				// Exit all frames
				thread.exitAllFrames();
				
				// Exit from all profiler threads
				thread.profiler.exitAll(System.nanoTime());
			}
			
			// Re-toss
			throw e;
		}
		
		// Terminate if the last frame
		finally
		{
			if (__framelimit == 0)



				thread._terminate = true;








		}



	}























	
	/**
	 * Checks if an exception is being thrown and sets up the state from it.
	 *
	 * @return True if an exception was detected.
	 * @since 2018/12/06
	 */







|
>
>
>

<


















>
>
>
















<
<
<















>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188



1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
				this.__singleStep();
			}
		}
		
		// If the VM is exiting then clear the execution stack before we go
		// away
		catch (SpringMachineExitException e)
		{	
			// Terminate the thread
			thread.terminate();
			
			// Thread is okay to exit!

			thread._signaledexit = true;
			
			// Exit all frames
			thread.exitAllFrames();
			
			// Exit profiler stack
			thread.profiler.exitAll(System.nanoTime());
			
			// Do not rethrow though
			return;
		}
		
		// Caught exception
		catch (RuntimeException e)
		{
			// Frame limit is zero, so kill the thread
			if (__framelimit == 0)
			{
				// Terminate the thread
				thread.terminate();
				
				PrintStream err = System.err;
				
				err.println("****************************");
				
				// Print the real stack trace
				err.println("*** EXTERNAL STACK TRACE ***");
				e.printStackTrace(err);
				err.println();
				
				// Print the VM seen stack trace
				err.println("*** INTERNAL STACK TRACE ***");
				thread.printStackTrace(err);
				err.println();
				
				err.println("****************************");
				



				// Exit all frames
				thread.exitAllFrames();
				
				// Exit from all profiler threads
				thread.profiler.exitAll(System.nanoTime());
			}
			
			// Re-toss
			throw e;
		}
		
		// Terminate if the last frame
		finally
		{
			if (__framelimit == 0)
				thread.terminate();
		}
	}
	
	/**
	 * Run the main process for this thread.
	 *
	 * @since 2020/06/17
	 */
	public final void runProcessMain()
	{
		SpringMachine machine = this.machine;
		
		// Locate the main class
		SpringClass bootClass = this.loadClass(
			machine.bootClass.replace('.', '/'));
		
		// Lookup the main method
		SpringMethod main = bootClass.lookupMethod(true,
			new MethodNameAndType("main", "([Ljava/lang/String;)V"));
		
		// Setup main arguments
		String[] args = machine.getMainArguments();
		int argsLen = args.length;
		
		// Allocate in VM
		SpringArrayObject vmArgs = this.allocateArray(
			this.resolveClass("[Ljava/lang/String;"), argsLen);
		
		// Copy everything over
		for (int i = 0; i < argsLen; i++)
			vmArgs.set(i, this.asVMObject(args[i]));
		
		// Enter the main method with all the passed arguments
		int deepness = this.thread.numFrames();
		this.thread.enterFrame(main, vmArgs);
		
		// Run until it finishes execution
		this.run(deepness);
	}
	
	/**
	 * Checks if an exception is being thrown and sets up the state from it.
	 *
	 * @return True if an exception was detected.
	 * @since 2018/12/06
	 */
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
			// Pop our current frame from the call stack
			thread.popFrame();
			
			// Did we run out of stack frames?
			SpringThread.Frame cf = thread.currentFrame();
			if (cf == null)
			{
				// Send our throwable to a special handler
				this.invokeMethod(true, new ClassName("cc/squirreljme/" +
					"runtime/cldc/lang/UncaughtExceptionHandler"),
					new MethodNameAndType("handle",
					"(Ljava/lang/Throwable;)V"), __o);
				
				// Just stop execution here
				return -1;
			}
			
			// Toss onto the new current frame
			cf.tossException(__o);
			







<
<
<
<
<
<







1329
1330
1331
1332
1333
1334
1335






1336
1337
1338
1339
1340
1341
1342
			// Pop our current frame from the call stack
			thread.popFrame();
			
			// Did we run out of stack frames?
			SpringThread.Frame cf = thread.currentFrame();
			if (cf == null)
			{






				// Just stop execution here
				return -1;
			}
			
			// Toss onto the new current frame
			cf.tossException(__o);
			
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
		}
		
		// If the VM is exiting then clear the execution stack before we go
		// away
		catch (SpringMachineExitException e)
		{
			// Thread is okay to exit!
			thread._terminate = true;
			
			// Exit profiler stack
			thread.profiler.exitAll(System.nanoTime());
			
			throw e;
		}
		







|







1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
		}
		
		// If the VM is exiting then clear the execution stack before we go
		// away
		catch (SpringMachineExitException e)
		{
			// Thread is okay to exit!
			thread.terminate();
			
			// Exit profiler stack
			thread.profiler.exitAll(System.nanoTime());
			
			throw e;
		}
		
2306
2307
2308
2309
2310
2311
2312
2313

2314
2315
2316
2317
2318
2319
2320
					frame.loadToStack(SpringObject.class,
						opid - InstructionIndex.ALOAD_0);
					break;
				
					// Allocate new array
				case InstructionIndex.ANEWARRAY:
					frame.pushToStack(this.allocateArray(this.resolveClass(
						inst.<ClassName>argument(0, ClassName.class)),

						frame.<Integer>popFromStack(Integer.class)));
					break;
					
					// Return reference
				case InstructionIndex.ARETURN:
					this.__vmReturn(thread,
						frame.<SpringObject>popFromStack(SpringObject.class));







|
>







1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
					frame.loadToStack(SpringObject.class,
						opid - InstructionIndex.ALOAD_0);
					break;
				
					// Allocate new array
				case InstructionIndex.ANEWARRAY:
					frame.pushToStack(this.allocateArray(this.resolveClass(
						inst.<ClassName>argument(0, ClassName.class)
						.addDimensions(1)),
						frame.<Integer>popFromStack(Integer.class)));
					break;
					
					// Return reference
				case InstructionIndex.ARETURN:
					this.__vmReturn(thread,
						frame.<SpringObject>popFromStack(SpringObject.class));
2372
2373
2374
2375
2376
2377
2378

2379
2380
2381
2382
2383
2384
2385
						SpringObject pop = frame.<SpringObject>popFromStack(
							SpringObject.class);
						
						// {@squirreljme.error BK2d Cannot cast object to the
						// target type. (The type to cast to; The type of the
						// object)}
						if (pop != SpringNullObject.NULL &&

							!as.isAssignableFrom(pop.type()))
							throw new SpringClassCastException(String.format(
								"BK2d %s %s", as, pop.type()));
						
						// Return the popped value
						else
							frame.pushToStack(pop);







>







1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
						SpringObject pop = frame.<SpringObject>popFromStack(
							SpringObject.class);
						
						// {@squirreljme.error BK2d Cannot cast object to the
						// target type. (The type to cast to; The type of the
						// object)}
						if (pop != SpringNullObject.NULL &&
							!(pop instanceof AbstractGhostObject) &&
							!as.isAssignableFrom(pop.type()))
							throw new SpringClassCastException(String.format(
								"BK2d %s %s", as, pop.type()));
						
						// Return the popped value
						else
							frame.pushToStack(pop);
3759
3760
3761
3762
3763
3764
3765
3766

3767
3768
3769
3770
3771
3772
3773
					this.__vmNew(inst, frame);
					break;
				
					// Allocate new primitive array
				case InstructionIndex.NEWARRAY:
					frame.pushToStack(this.allocateArray(this.resolveClass(
						ClassName.fromPrimitiveType(
						inst.<PrimitiveType>argument(0, PrimitiveType.class))),

						frame.<Integer>popFromStack(Integer.class)));
					break;
					
					// Return from method with no return value
				case InstructionIndex.RETURN:
					thread.popFrame();
					break;







|
>







3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
					this.__vmNew(inst, frame);
					break;
				
					// Allocate new primitive array
				case InstructionIndex.NEWARRAY:
					frame.pushToStack(this.allocateArray(this.resolveClass(
						ClassName.fromPrimitiveType(
						inst.<PrimitiveType>argument(0,
							PrimitiveType.class)).addDimensions(1)),
						frame.<Integer>popFromStack(Integer.class)));
					break;
					
					// Return from method with no return value
				case InstructionIndex.RETURN:
					thread.popFrame();
					break;
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
		// because it is of the wrong type. (The reference class; The class
		// of the target object; The first argument)}
		SpringClass objclass = onthis.type();
		if (objclass == null || !refclass.isAssignableFrom(objclass))
			throw new SpringClassCastException(
				String.format("BK32 %s %s %s", refclass, objclass, args[0]));
		
		// Relookup the method since we need to the right one! Then invoke it
		__t.enterFrame(objclass.lookupMethod(false, ref.memberNameAndType()),
			args);
	}
	
	/**
	 * Internal system call handling.
	 *
	 * @param __si System call index.
	 * @param __args Arguments.
	 * @return The result.
	 * @since 2019/05/23
	 */
	public final long systemCall(short __si, int... __args)
	{
		// Make at least 8!
		if (__args == null)
			__args = new int[8];
		if (__args.length < 8)
			__args = Arrays.copyOf(__args, 8);
		
		// Error state for the last call of this type
		int[] errors = this.thread._syscallerrors;
		
		// Return value with error value, to set if any
		long rv;
		int err;
		
		// Depends on the system call type
		switch (__si)
		{
				// Check if system call is supported
			case SystemCallIndex.QUERY_INDEX:
				{
					err = 0;
					switch (__args[0])
					{
						case SystemCallIndex.API_LEVEL:
						case SystemCallIndex.CALL_STACK_HEIGHT:
						case SystemCallIndex.CALL_STACK_ITEM:
						case SystemCallIndex.ERROR_GET:
						case SystemCallIndex.ERROR_SET:
						case SystemCallIndex.EXIT:
						case SystemCallIndex.FATAL_TODO:
						case SystemCallIndex.GARBAGE_COLLECT:
						case SystemCallIndex.LOAD_STRING:
						case SystemCallIndex.PD_OF_STDERR:
						case SystemCallIndex.PD_OF_STDIN:
						case SystemCallIndex.PD_OF_STDOUT:
						case SystemCallIndex.PD_WRITE_BYTE:
						case SystemCallIndex.SLEEP:
						case SystemCallIndex.TIME_MILLI_WALL:
						case SystemCallIndex.TIME_NANO_MONO:
						case SystemCallIndex.VMI_MEM_FREE:
						case SystemCallIndex.VMI_MEM_MAX:
						case SystemCallIndex.VMI_MEM_USED:
							rv = 1;
							break;
						
						default:
							rv = 0;
							break;
					}
				}
				break;
				
				// Returns the height of the call stack
			case SystemCallIndex.CALL_STACK_HEIGHT:
				{
					rv = this.thread.frames().length;
					err = 0;
				}
				break;
				
				// Returns the given call stack item
			case SystemCallIndex.CALL_STACK_ITEM:
				{
					// Need to get all the stack frames first
					SpringThread.Frame[] frames = this.thread.frames();
					int numframes = frames.length;
					int curf = (numframes - __args[0]) - 1;
					
					// Out of range item
					if (curf < 0 || curf >= numframes)
					{
						rv = -1;
						err = SystemCallError.VALUE_OUT_OF_RANGE;
					}
					
					// Depends on the item
					else
					{
						// Reset
						rv = err = 0;
						
						// Get method we are in
						SpringMethod inmethod = frames[curf].method();
						
						// Depends on the item
						switch (__args[1])
						{
								// Class name
							case CallStackItem.CLASS_NAME:
								if (inmethod == null)
									err = SystemCallError.VALUE_OUT_OF_RANGE;
								else
									rv = this.uniqueStringId(
										inmethod.inClass().toString());
								break;

								// The method name.
							case CallStackItem.METHOD_NAME:
								if (inmethod == null)
									err = SystemCallError.VALUE_OUT_OF_RANGE;
								else
									rv = this.uniqueStringId(inmethod.
										nameAndType().name().toString());
								break;

								// The method type.
							case CallStackItem.METHOD_TYPE:
								if (inmethod == null)
									err = SystemCallError.VALUE_OUT_OF_RANGE;
								else
									rv = this.uniqueStringId(inmethod.
										nameAndType().type().toString());
								break;

								// The current file.
							case CallStackItem.SOURCE_FILE:
								if (inmethod == null)
									err = SystemCallError.VALUE_OUT_OF_RANGE;
								else
									rv = this.uniqueStringId(
										inmethod.inFile());
								break;

								// Source line.
							case CallStackItem.SOURCE_LINE:
								rv = frames[curf].lastExecutedPcSourceLine();
								break;

								// The PC address.
							case CallStackItem.PC_ADDRESS:
							case CallStackItem.JAVA_PC_ADDRESS:
								rv = frames[curf].lastExecutedPc();
								break;

							default:
								err = SystemCallError.VALUE_OUT_OF_RANGE;
								break;
						}
					}
				}
				break;
				
				// Get error
			case SystemCallIndex.ERROR_GET:
				{
					// If the ID is valid then a bad array access will be used
					int dx = __args[0];
					if (dx < 0 || dx >= SystemCallIndex.NUM_SYSCALLS)
						dx = SystemCallIndex.QUERY_INDEX;
					
					// Return the stored error code
					synchronized (errors)
					{
						rv = errors[dx];
					}
					
					// Always succeeds
					err = 0;
				}
				break;
				
				// Set error
			case SystemCallIndex.ERROR_SET:
				{
					// If the ID is valid then a bad array access will be used
					int dx = __args[0];
					if (dx < 0 || dx >= SystemCallIndex.NUM_SYSCALLS)
						dx = SystemCallIndex.QUERY_INDEX;
					
					// Return last error code, and set new one
					synchronized (errors)
					{
						rv = errors[dx];
						errors[dx] = __args[0];
					}
					
					// Always succeeds
					err = 0;
				}
				break;
				
				// Exit the VM
			case SystemCallIndex.EXIT:
				{
					// Tell everything to cleanup and exit
					this.thread.profiler.exitAll(System.nanoTime());
					this.machine.exit((Integer)__args[0]);
					
					rv = 0;
					err = 0;
				}
				break;
				
				// Fatal ToDo
			case SystemCallIndex.FATAL_TODO:
				// {@squirreljme.error BK33 Virtual machine code executed
				// a fatal Todo. (The To Do code)}
				rv = err = 0;
				throw new SpringVirtualMachineException("BK33 " + __args[1]);
				
				// Invoke the garbage collector
			case SystemCallIndex.GARBAGE_COLLECT:
				{
					Runtime.getRuntime().gc();
					
					rv = 0;
					err = 0;
				}
				break;
				
				// Loads a string
			case SystemCallIndex.LOAD_STRING:
				{
					rv = (__args[0] == 0 ? 0 :
						this.uniqueObjectToPointer((SpringObject)
						this.asVMObject(new ConstantValueString(
						this.uniqueString(__args[0])))));
					err = 0;
				}
				break;
			
				// Current wall clock milliseconds (low).
			case SystemCallIndex.TIME_MILLI_WALL:
				{
					rv = System.currentTimeMillis();
					err = 0;
				}
				break;

				// Current monotonic clock nanoseconds (low).
			case SystemCallIndex.TIME_NANO_MONO:
				{
					rv = System.nanoTime();
					err = 0;
				}
				break;
			
				// VM information: Memory free bytes
			case SystemCallIndex.VMI_MEM_FREE:
				{
					rv = (int)Math.min(Integer.MAX_VALUE,
						Runtime.getRuntime().freeMemory());
					err = 0;
				}
				break;
			
				// VM information: Memory used bytes
			case SystemCallIndex.VMI_MEM_USED:
				{
					rv = (int)Math.min(Integer.MAX_VALUE,
						Runtime.getRuntime().totalMemory());
					err = 0;
				}
				break;
			
				// VM information: Memory max bytes
			case SystemCallIndex.VMI_MEM_MAX:
				{
					rv = (int)Math.min(Integer.MAX_VALUE,
						Runtime.getRuntime().maxMemory());
					err = 0;
				}
				break;
				
				// API level
			case SystemCallIndex.API_LEVEL:
				{
					rv = ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV;
					err = 0;
				}
				break;
				
				// Pipe descriptor of standard input
			case SystemCallIndex.PD_OF_STDIN:
				{
					rv = 0;
					err = 0;
				}
				break;
				
				// Pipe descriptor of standard output
			case SystemCallIndex.PD_OF_STDOUT:
				{
					rv = 1;
					err = 0;
				}
				break;
				
				// Pipe descriptor of standard error
			case SystemCallIndex.PD_OF_STDERR:
				{
					rv = 1;
					err = 0;
				}
				break;
				
				// Write single byte to PD
			case SystemCallIndex.PD_WRITE_BYTE:
				{
					// Depends on the stream
					int pd = __args[0];
					OutputStream os = (pd == 1 ? System.out :
						(pd == 2 ? System.err : null));
					
					// Write
					if (os != null)
					{
						try
						{
							os.write(__args[1]);
							
							// Okay
							rv = 1;
							err = 0;
						}
						
						// Failed
						catch (IOException e)
						{
							rv = -1;
							err = SystemCallError.PIPE_DESCRIPTOR_BAD_WRITE;
						}
					}
					
					// Failed
					else
					{
						rv = -1;
						err = SystemCallError.PIPE_DESCRIPTOR_INVALID;
					}
				}
				break;
				
				// Sleep
			case SystemCallIndex.SLEEP:
				try
				{
					Thread.sleep(__args[0], __args[1]);
					
					rv = 0;
					err = SystemCallError.NO_ERROR;
				}
				catch (InterruptedException e)
				{
					rv = 1;
					err = SystemCallError.INTERRUPTED;
				}
				break;
			
			default:
				// Returns no value but sets an error
				rv = -1;
				err = SystemCallError.UNSUPPORTED_SYSTEM_CALL;
				
				// If the ID is valid then a bad array access will be used
				if (__si < 0 || __si >= SystemCallIndex.NUM_SYSCALLS)
					__si = SystemCallIndex.QUERY_INDEX;
				break;
		}
		
		// Set error state as needed
		synchronized (errors)
		{
			errors[__si] = err;
		}
		
		// Use returning value
		return rv;
	}
	
	/**
	 * Converts an object to a unique pointer.
	 *
	 * @param __p The object to convert.
	 * @return The resulting pointer.
	 * @since 2019/06/16
	 */
	public final int uniqueObjectToPointer(SpringObject __p)
	{
		// Null reference?
		if (__p == SpringNullObject.NULL)
			return 0;
		
		// Return the base of the pointer area
		return __p.pointerArea().base;
	}
	
	/**
	 * Converts an object to a unique pointer.
	 *
	 * @param __p The object to convert.
	 * @return The resulting pointer.
	 * @since 2019/06/16
	 */
	public final SpringObject uniquePointerToObject(int __p)
	{
		// Null reference?
		if (__p == 0)
			return SpringNullObject.NULL;
		
		return this.machine.pointers.findObject(__p);
	}
	
	/**
	 * Returns the string of the given ID.
	 *
	 * @param __id The ID to get.
	 * @return The resulting string.
	 * @since 2019/06/16
	 */
	public final String uniqueString(int __id)
	{
		if (__id == 0)
			return null;
		return this.machine.debugResolveString((int)__id);
	}
	
	/**
	 * Returns a unique ID for the given string.
	 *
	 * @param __s The String to get the ID of.
	 * @return The unique string ID.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/06/16
	 */
	public final int uniqueStringId(String __s)
		throws NullPointerException
	{
		if (__s == null)
			return 0;
		
		return (int)this.machine.debugUnresolveString(__s);
	}
	
	/**
	 * Performs a special invoke.
	 *
	 * @param __i The instruction.
	 * @param __t The current thread.







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







3266
3267
3268
3269
3270
3271
3272
3273






























































































































































































































3274










3275



















































































































































































































3276
3277
3278
3279
3280
3281
3282
		// because it is of the wrong type. (The reference class; The class
		// of the target object; The first argument)}
		SpringClass objclass = onthis.type();
		if (objclass == null || !refclass.isAssignableFrom(objclass))
			throw new SpringClassCastException(
				String.format("BK32 %s %s %s", refclass, objclass, args[0]));
		
		// Re-lookup the method since we need to the right one! Then invoke it






























































































































































































































		__t.enterFrame(objclass.lookupMethod(false,










			ref.memberNameAndType()), args);



















































































































































































































	}
	
	/**
	 * Performs a special invoke.
	 *
	 * @param __i The instruction.
	 * @param __t The current thread.
4563
4564
4565
4566
4567
4568
4569









4570
4571
4572
4573
4574
4575
4576
4577








4578
4579
4580
4581
4582
4583
4584
		Object[] args = new Object[nargs];
		for (int i = nargs - 1; i >= 0; i--)
			args[i] = __f.popFromStack();
		
		// Virtualized native call, depends on what it is
		if (refmethod.flags().isNative())
		{









			// Calculate result of method
			MethodDescriptor type = ref.memberType();
			Object rv = this.nativeMethod(ref.className() + "::" +
				ref.memberName() + ":" + type, args);
			
			// Push native object to the stack
			if (type.hasReturnValue())
				__f.pushToStack(this.asVMObject(rv, true));








		}
		
		// Real code that exists in class file format
		else
			__t.enterFrame(refmethod, args);
	}
	







>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>







3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
		Object[] args = new Object[nargs];
		for (int i = nargs - 1; i >= 0; i--)
			args[i] = __f.popFromStack();
		
		// Virtualized native call, depends on what it is
		if (refmethod.flags().isNative())
		{
			// Add profiler point for native calls to track them there along
			// with being able to handle that
			ProfiledFrame pFrame = this.thread.profiler.enterFrame(
				ref.className().toString(),
				ref.memberName().toString(), ref.memberType().toString());
			
			// Now perform the actual call
			try
			{
				// Calculate result of method
				MethodDescriptor type = ref.memberType();
				Object rv = this.nativeMethod(ref.className(),
					ref.memberNameAndType(), args);
				
				// Push native object to the stack
				if (type.hasReturnValue())
					__f.pushToStack(this.asVMObject(rv, true));
			}
			
			// Exit the profiler frame to it is no longer tracked
			finally
			{
				if (pFrame.inCallCount() > 0)
					this.thread.profiler.exitFrame();
			}
		}
		
		// Real code that exists in class file format
		else
			__t.enterFrame(refmethod, args);
	}
	

Changes to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringVMStaticMethod.java.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
 * This is a virtual machine representation of a static method.
 *
 * @since 2018/11/20
 */
@Deprecated
public final class SpringVMStaticMethod
	implements SpringObject
{
	/** The method to execute. */
	protected final SpringMethod method;
	
	/**
	 * Initializes the static method.
	 *
	 * @param __m The method to execute.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/20
	 */
	public SpringVMStaticMethod(SpringMethod __m)
		throws NullPointerException
	{
		if (__m == null)
			throw new NullPointerException("NARG");
		
		this.method = __m;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/20
	 */
	@Override
	public final SpringMonitor monitor()
	{
		// {@squirreljme.error BK3b StaticMethod does not have a monitor.}
		throw new SpringFatalException("BK3b");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/12/21
	 */
	@Override
	public final SpringPointerArea pointerArea()
	{
		throw new todo.TODO();
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/20
	 */
	@Override
	public final SpringClass type()
	{
		// {@squirreljme.error BK3c StaticMethod does not have a type.}
		throw new SpringFatalException("BK3c");
	}
}








|



















|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40






41


























/**
 * This is a virtual machine representation of a static method.
 *
 * @since 2018/11/20
 */
@Deprecated
public final class SpringVMStaticMethod
	extends AbstractGhostObject
{
	/** The method to execute. */
	protected final SpringMethod method;
	
	/**
	 * Initializes the static method.
	 *
	 * @param __m The method to execute.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/20
	 */
	public SpringVMStaticMethod(SpringMethod __m)
		throws NullPointerException
	{
		if (__m == null)
			throw new NullPointerException("NARG");
		
		this.method = __m;
	}
}

































Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/brackets/JarPackageObject.java.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.brackets;

import cc.squirreljme.vm.VMClassLibrary;
import cc.squirreljme.vm.springcoat.AbstractGhostObject;

/**
 * Not Described.
 *
 * @since 2020/06/17
 */
public class JarPackageObject
	extends AbstractGhostObject
{
	/** The class library. */
	private final VMClassLibrary library;
	
	/**
	 * Initializes the package object.
	 *
	 * @param __lib The library.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/17
	 */
	public JarPackageObject(VMClassLibrary __lib)
		throws NullPointerException
	{
		if (__lib == null)
			throw new NullPointerException("NARG");
		
		this.library = __lib;
	}
	
	/**
	 * Returns the library.
	 *
	 * @return The library.
	 * @since 2020/06/17
	 */
	public VMClassLibrary library()
	{
		return this.library;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/brackets/RefLinkHolder.java.























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.brackets;

/**
 * Contains the holder for reference links.
 *
 * @since 2020/05/31
 */
public final class RefLinkHolder
{
	/** The associated link. */
	RefLinkObject _link;
	
	/**
	 * Returns the ref link.
	 *
	 * @return The link.
	 * @since 2020/05/31
	 */
	public RefLinkObject get()
	{
		return this._link;
	}
	
	/**
	 * Sets the ref link.
	 *
	 * @param __link The link.
	 * @since 2020/05/31
	 */
	public void set(RefLinkObject __link)
	{
		this._link = __link;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/brackets/RefLinkObject.java.







































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.brackets;

import cc.squirreljme.jvm.mle.brackets.RefLinkBracket;
import cc.squirreljme.vm.springcoat.AbstractGhostObject;
import cc.squirreljme.vm.springcoat.SpringObject;

/**
 * This contains the storage for reference links, these chain to each other.
 *
 * @see RefLinkBracket
 * @since 2020/05/30
 */
public final class RefLinkObject
	extends AbstractGhostObject
{
	/** The object this links. */
	volatile SpringObject _object;
	
	/** The next link in the chain. */
	volatile RefLinkObject _next;
	
	/** The previous link in the chain. */
	volatile RefLinkObject _prev;
	
	/**
	 * Gets the next link.
	 * 
	 * @return The link.
	 * @since 2020/06/29
	 */
	public RefLinkObject getNext()
	{
		return this._next;
	}
	
	/**
	 * Returns the object that this points to.
	 *
	 * @return The object.
	 * @since 2020/06/13
	 */
	public final SpringObject getObject()
	{
		return this._object;
	}
	
	/**
	 * Gets the previous link.
	 * 
	 * @return The link.
	 * @since 2020/06/29
	 */
	public RefLinkObject getPrev()
	{
		return this._prev;
	}
	
	/**
	 * Sets the next link.
	 * 
	 * @param __next The new link.
	 * @since 2020/06/29
	 */
	public void setNext(RefLinkObject __next)
	{
		this._next = __next;
	}
	
	/**
	 * Sets the object of this holder.
	 *
	 * @param __o The object to set.
	 * @since 2020/06/13
	 */
	public void setObject(SpringObject __o)
	{
		this._object = __o;
	}
	
	/**
	 * Sets the previous link.
	 * 
	 * @param __prev The new link.
	 * @since 2020/06/29
	 */
	public void setPrev(RefLinkObject __prev)
	{
		this._prev = __prev;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/brackets/TracePointObject.java.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.brackets;

import cc.squirreljme.runtime.cldc.debug.CallTraceElement;
import cc.squirreljme.vm.springcoat.AbstractGhostObject;

/**
 * This class stores anything that is within trace points and such.
 *
 * @since 2020/06/12
 */
public final class TracePointObject
	extends AbstractGhostObject
{
	/** The trace for the call. */
	protected final CallTraceElement trace;
	
	/**
	 * Initializes the trace point.
	 *
	 * @param __trace The trace to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/14
	 */
	public TracePointObject(CallTraceElement __trace)
		throws NullPointerException
	{
		if (__trace == null)
			throw new NullPointerException("NARG");
		
		this.trace = __trace;
	}
	
	/**
	 * Returns the trace.
	 *
	 * @return The trace.
	 * @since 2020/06/16
	 */
	public final CallTraceElement getTrace()
	{
		return this.trace;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/brackets/TypeObject.java.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.brackets;

import cc.squirreljme.vm.springcoat.AbstractGhostObject;
import cc.squirreljme.vm.springcoat.SpringClass;

/**
 * Represents a type from within the VM.
 *
 * @since 2020/06/02
 */
public class TypeObject
	extends AbstractGhostObject
{
	/** The class this provides. */
	protected final SpringClass classy;
	
	/**
	 * Initializes the type object.
	 *
	 * @param __cl The class to use.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/04
	 */
	public TypeObject(SpringClass __cl)
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		this.classy = __cl;
	}
	
	/**
	 * Returns the class this refers to.
	 *
	 * @return The class this refers to.
	 * @since 2020/06/13
	 */
	public final SpringClass getSpringClass()
	{
		return this.classy;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/brackets/VMThreadObject.java.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.brackets;

import cc.squirreljme.vm.springcoat.AbstractGhostObject;
import cc.squirreljme.vm.springcoat.SpringThread;

/**
 * This represents the "thread" object.
 *
 * @since 2020/06/17
 */
public final class VMThreadObject
	extends AbstractGhostObject
{
	/** The thread to target. */
	protected final SpringThread thread;
	
	/**
	 * Initializes the thread.
	 *
	 * @param __thread The thread to target.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/17
	 */
	public VMThreadObject(SpringThread __thread)
		throws NullPointerException
	{
		if (__thread == null)
			throw new NullPointerException("NARG");
		
		this.thread = __thread;
	}
	
	/**
	 * Returns the thread this is bound to.
	 *
	 * @return The thread this is bound to.
	 * @since 2020/06/17
	 */
	public SpringThread getThread()
	{
		return this.thread;
	}
}

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/brackets/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * The package contains the brackets used for SpringCoat.
 *
 * @since 2020/06/12
 */

package cc.squirreljme.vm.springcoat.brackets;

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArithmeticException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringArithmeticException.java.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;




/**
 * This is thrown when a divide by zero occurs.
 *
 * @since 2018/12/04
 */
public class SpringArithmeticException










|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringConvertableThrowable;
import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when a divide by zero occurs.
 *
 * @since 2018/12/04
 */
public class SpringArithmeticException

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayIndexOutOfBoundsException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringArrayIndexOutOfBoundsException.java.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;




/**
 * This is thrown when an invalid out of bounds index was accessed in an
 * array.
 *
 * @since 2018/09/16
 */










|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringConvertableThrowable;
import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when an invalid out of bounds index was accessed in an
 * array.
 *
 * @since 2018/09/16
 */

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringArrayStoreException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringArrayStoreException.java.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;




/**
 * This is thrown when an invalid value was attempted to be stored into an
 * array.
 *
 * @since 2018/09/16
 */










|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringConvertableThrowable;
import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when an invalid value was attempted to be stored into an
 * array.
 *
 * @since 2018/09/16
 */

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringClassCastException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringClassCastException.java.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;




/**
 * This is thrown when an attempt is made to cast from one class type to
 * another.
 *
 * @since 2018/09/15
 */










|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringConvertableThrowable;
import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when an attempt is made to cast from one class type to
 * another.
 *
 * @since 2018/09/15
 */

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringClassFormatException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringClassFormatException.java.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;


import net.multiphasicapps.classfile.ClassName;

/**
 * This is thrown when the format of a class is not correct, it is invalid.
 *
 * @since 2018/08/05
 */










|

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringException;
import net.multiphasicapps.classfile.ClassName;

/**
 * This is thrown when the format of a class is not correct, it is invalid.
 *
 * @since 2018/08/05
 */

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringClassNotFoundException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringClassNotFoundException.java.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;


import net.multiphasicapps.classfile.ClassName;

/**
 * This is thrown when the specified class could not be found.
 *
 * @since 2018/08/05
 */










|

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringException;
import net.multiphasicapps.classfile.ClassName;

/**
 * This is thrown when the specified class could not be found.
 *
 * @since 2018/08/05
 */

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringFatalException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringFatalException.java.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



/**
 * This is an exception which describes something that is very fatal within
 * the virtual machine.
 *
 * @since 2018/09/20
 */










|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is an exception which describes something that is very fatal within
 * the virtual machine.
 *
 * @since 2018/09/20
 */

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringIllegalAccessException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringIllegalAccessException.java.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



/**
 * This is thrown when a class or member of a class cannot be accessed.
 *
 * @since 2018/09/15
 */
public class SpringIllegalAccessException










|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when a class or member of a class cannot be accessed.
 *
 * @since 2018/09/15
 */
public class SpringIllegalAccessException

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringIllegalMonitorStateException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringIllegalMonitorStateException.java.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;




/**
 * This is thrown when the state of a monitor is not valid.
 *
 * @since 2018/09/15
 */
public class SpringIllegalMonitorStateException










|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringConvertableThrowable;
import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when the state of a monitor is not valid.
 *
 * @since 2018/09/15
 */
public class SpringIllegalMonitorStateException

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringIncompatibleClassChangeException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringIncompatibleClassChangeException.java.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



/**
 * This is thrown when a class refers to another reference and it differs
 * than what was expected at run-time.
 *
 * @since 2018/09/09
 */










|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when a class refers to another reference and it differs
 * than what was expected at run-time.
 *
 * @since 2018/09/09
 */

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringMLECallError.java.



























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.jvm.mle.exceptions.MLECallError;
import cc.squirreljme.vm.springcoat.SpringConvertableThrowable;
import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is SpringCoat's variant of {@link MLECallError}.
 *
 * @since 2020/06/22
 */
public class SpringMLECallError
	extends SpringException
	implements SpringConvertableThrowable
{
	/**
	 * Initialize the exception with no message or cause.
	 *
	 * @since 2020/06/22
	 */
	public SpringMLECallError()
	{
	}
	
	/**
	 * Initialize the exception with a message and no cause.
	 *
	 * @param __m The message.
	 * @since 2020/06/22
	 */
	public SpringMLECallError(String __m)
	{
		super(__m);
	}
	
	/**
	 * Initialize the exception with a message and cause.
	 *
	 * @param __m The message.
	 * @param __c The cause.
	 * @since 2020/06/22
	 */
	public SpringMLECallError(String __m, Throwable __c)
	{
		super(__m, __c);
	}
	
	/**
	 * Initialize the exception with no message and with a cause.
	 *
	 * @param __c The cause.
	 * @since 2020/06/22
	 */
	public SpringMLECallError(Throwable __c)
	{
		super(__c);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public String targetClass()
	{
		return "cc/squirreljme/jvm/mle/exceptions/MLECallError";
	}
}

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringMachineExitException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringMachineExitException.java.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



/**
 * This is thrown when the virtual machine is exiting.
 *
 * @since 2018/10/13
 */
public class SpringMachineExitException










|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when the virtual machine is exiting.
 *
 * @since 2018/10/13
 */
public class SpringMachineExitException

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringNegativeArraySizeException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringNegativeArraySizeException.java.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;




/**
 * This is thrown when an attempt was made to allocate an array of a negative
 * size.
 *
 * @since 2018/09/15
 */










|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringConvertableThrowable;
import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when an attempt was made to allocate an array of a negative
 * size.
 *
 * @since 2018/09/15
 */

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringNoSuchFieldException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringNoSuchFieldException.java.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



/**
 * This is thrown when a field in a class does not exist.
 *
 * @since 2018/09/09
 */
public class SpringNoSuchFieldException










|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.exceptions.SpringIncompatibleClassChangeException;

/**
 * This is thrown when a field in a class does not exist.
 *
 * @since 2018/09/09
 */
public class SpringNoSuchFieldException

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringNoSuchMethodException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringNoSuchMethodException.java.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



/**
 * This is thrown when a method in a class does not exist.
 *
 * @since 2018/09/03
 */
public class SpringNoSuchMethodException










|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.exceptions.SpringIncompatibleClassChangeException;

/**
 * This is thrown when a method in a class does not exist.
 *
 * @since 2018/09/03
 */
public class SpringNoSuchMethodException

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringNullPointerException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringNullPointerException.java.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;




/**
 * This is thrown when a null reference has been detected.
 *
 * @since 2018/09/09
 */
public class SpringNullPointerException










|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringConvertableThrowable;
import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when a null reference has been detected.
 *
 * @since 2018/09/09
 */
public class SpringNullPointerException

Name change from emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/SpringVirtualMachineException.java to emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/SpringVirtualMachineException.java.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;



/**
 * This is thrown when the virtual machine has been detected to not be
 * operating properly, this is an error.
 *
 * @since 2018/09/01
 */










|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat.exceptions;

import cc.squirreljme.vm.springcoat.SpringException;

/**
 * This is thrown when the virtual machine has been detected to not be
 * operating properly, this is an error.
 *
 * @since 2018/09/01
 */

Added emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/exceptions/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This package contains all of the exception types used within SpringCoat.
 *
 * @since 2020/06/12
 */

package cc.squirreljme.vm.springcoat.exceptions;

Changes to emulators/summercoat-vm/build.gradle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
plugins
{
	id "java-library"
}

description = "This is the SummerCoat VM which is a more " +
	"optimized register based virtual machine which should result in faster" +
	"code execution."

dependencies
{
	api project(":emulators:emulator-base")

	api project(":modules:cldc-compact")
	api project(":modules:collections")
	api project(":modules:common-vm")
	api project(":modules:io")
	api project(":modules:meep-midlet")
	api project(":modules:meep-swm")
	api project(":modules:tool-classfile")
	api project(":modules:tool-jarfile")
	api project(":modules:tool-manifest-reader")
	api project(":modules:tool-packfile")
}












|

<

<
<
<


<


1
2
3
4
5
6
7
8
9
10
11
12
13
14

15



16
17

18
19
plugins
{
	id "java-library"
}

description = "This is the SummerCoat VM which is a more " +
	"optimized register based virtual machine which should result in faster" +
	"code execution."

dependencies
{
	api project(":emulators:emulator-base")
	
	api project(":modules:cldc-compact")

	api project(":modules:common-vm")



	api project(":modules:tool-classfile")
	api project(":modules:tool-jarfile")

	api project(":modules:tool-packfile")
}

Changes to gradle/wrapper/gradle-wrapper.properties.

1
2
3
4
5
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists


|


1
2
3
4
5
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Added language.mkd.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Language Information

# Pronunciation

 * IPA
   * `[ˈskwərəl] [ʤeɪ] [ɛm] [i]`
 * Phonetics
   * `skwUHR-ruhl jAY-Em-EE`

# Translation/Transliterations

The _Squirrel_ in _SquirrelJME_ may be translated or not, if it is translated
and not transliterated then **Both** with be specified, otherwise it will
be **Transliteration**.

 * Bosnian
   * Both: `VjevericaDŽMI`, `ВјеверицаЏМЕ`
   * Transliteration: `SkvrlDŽMI`, `СкврлЏМI`
 * Japanese
   * Transliteration: `スクアルジェエムイ`, `sukuaru je'emui`

Changes to license.mkd.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 * Assets which are not fonts, includes the mascot, logo, and icons:
   * **Creative Commons CC-BY-SA 4.0**
 * Fonts:
   * **SIL Open Font License Version 1.1**

[Commercial licenses are available under the commercial terms](commercial.mkd).

Contributors must agree to the [contributor license](contibuting.mkd) before
their code may be accepted.

Additionally, if the **GNU GPLv3** and **CC-BY-SA 4.0** are not desirable a
proprietary license may be purchased for a negotiable fee. The terms of the
contract are to be negotiated.

Note that there is no linking exception to the **GNU GPLv3**, this is because:







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 * Assets which are not fonts, includes the mascot, logo, and icons:
   * **Creative Commons CC-BY-SA 4.0**
 * Fonts:
   * **SIL Open Font License Version 1.1**

[Commercial licenses are available under the commercial terms](commercial.mkd).

Contributors must agree to the [contributor license](contributing.mkd) before
their code may be accepted.

Additionally, if the **GNU GPLv3** and **CC-BY-SA 4.0** are not desirable a
proprietary license may be purchased for a negotiable fee. The terms of the
contract are to be negotiated.

Note that there is no linking exception to the **GNU GPLv3**, this is because:

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/jvm/ClassInfo.java.

11
12
13
14
15
16
17

18
19
20
21
22
23
24

/**
 * This contains class information which is used to define the information
 * that is needed to parse it properly.
 *
 * @since 2019/05/25
 */

public final class ClassInfo
{
	/** The magic number which should be used. */
	public static final int MAGIC_NUMBER =
		0x4C6F7665;
	
	/** Self pointer. */







>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

/**
 * This contains class information which is used to define the information
 * that is needed to parse it properly.
 *
 * @since 2019/05/25
 */
@Deprecated
public final class ClassInfo
{
	/** The magic number which should be used. */
	public static final int MAGIC_NUMBER =
		0x4C6F7665;
	
	/** Self pointer. */

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/jvm/config/BuiltInLocale.java.

10
11
12
13
14
15
16

17
18
19
20
21
22
23
package cc.squirreljme.jvm.config;

/**
 * This represents a built-in locale.
 *
 * @since 2020/05/12
 */

public interface BuiltInLocale
{
	/** Unknown, will be treated as US English. */
	byte UNKNOWN =
		0;
	
	/** English: United States of America. */







>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package cc.squirreljme.jvm.config;

/**
 * This represents a built-in locale.
 *
 * @since 2020/05/12
 */
@Deprecated
public interface BuiltInLocale
{
	/** Unknown, will be treated as US English. */
	byte UNKNOWN =
		0;
	
	/** English: United States of America. */

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/jvm/config/ConfigRomKey.java.

1
2
3
4
5
6
7
8
9
10
11



12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.config;




/**
 * This represents an option in the configuration ROM.
 *
 * @since 2019/06/14
 */
public interface ConfigRomKey
{











>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.config;

import cc.squirreljme.jvm.mle.constants.BuiltInEncodingType;
import cc.squirreljme.jvm.mle.constants.LineEndingType;

/**
 * This represents an option in the configuration ROM.
 *
 * @since 2019/06/14
 */
public interface ConfigRomKey
{
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
	 * @squirreljme.configtype {@link ConfigRomType#LONG}
	 * @since 2019/06/14
	 */
	byte SYSCALL_POOL_POINTER =
		14;
	
	/**
	 * The built-in encoding to use, see {@link BuiltInEncoding}.
	 *
	 * @squirreljme.configtype {@link ConfigRomType#INTEGER}
	 * @since 2019/06/14
	 */
	byte BUILT_IN_ENCODING =
		15;
	







|







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
	 * @squirreljme.configtype {@link ConfigRomType#LONG}
	 * @since 2019/06/14
	 */
	byte SYSCALL_POOL_POINTER =
		14;
	
	/**
	 * The built-in encoding to use, see {@link BuiltInEncodingType}.
	 *
	 * @squirreljme.configtype {@link ConfigRomType#INTEGER}
	 * @since 2019/06/14
	 */
	byte BUILT_IN_ENCODING =
		15;
	

Deleted modules/cldc-compact/src/main/java/cc/squirreljme/jvm/config/LineEndingType.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.config;

/**
 * The type of line ending used.
 *
 * @since 2020/04/09
 */
public interface LineEndingType
{
	/** Unspecified. */
	byte UNSPECIFIED =
		0;
	
	/** LF. */
	byte LF =
		1;
	
	/** CR. */
	byte CR =
		2;
	
	/** CRLF. */
	byte CRLF =
		3;
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/AtomicShelf.java.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

/**
 * This shelf provides helpers for atomic operations.
 *
 * @since 2020/05/30
 */
public final class AtomicShelf
{
	/**
	 * Not used.
	 *
	 * @since 2020/05/30
	 */
	private AtomicShelf()
	{
	}
	
	/**
	 * Lock for garbage collection operations.
	 *
	 * @return The locking key if locked, otherwise {@code 0} when busy.
	 * @since 2020/05/30
	 */
	public static native int gcLock();
	
	/**
	 * Unlocks the garbage collector provided that the previous locking key
	 * matches.
	 *
	 * @param __key The key that was previously used to lock the garbage
	 * collector.
	 * @since 2020/05/30
	 */
	public static native void gcUnlock(int __key);
	
	/**
	 * For constant lock spins, this provides a consistent means of counting
	 * and then potentially fire-spinning or resting depending on the
	 * situation. This may cause a thread to preempt.
	 *
	 * On cooperatively tasked systems, this may switch to another thread.
	 *
	 * @param __count The number of times the lock has spun.
	 * @since 2020/05/30
	 */
	public static native void spinLock(int __count);
	
	/**
	 * Returns a "unique" atomic tick value. The value returned should be
	 * unique enough but the actual value that is returned should not be used
	 * in any way for comparisons other than equality.
	 *
	 * @return The tick value, note that it should not be used for comparisons
	 * other than equality.
	 * @since 2020/05/03
	 */
	public static native int tick();
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/DebugShelf.java.

















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

import cc.squirreljme.jvm.mle.brackets.TracePointBracket;

/**
 * This is the shelf used for accessing the debugging features of SquirrelJME
 * along with miscellaneous debugging utilities.
 *
 * @since 2020/06/11
 */
public final class DebugShelf
{
	/**
	 * Not used.
	 *
	 * @since 2020/06/11
	 */
	private DebugShelf()
	{
	}
	
	/**
	 * Returns the trace that is part of the given throwable.
	 *
	 * @param __t The throwable to gets it's trace of.
	 * @return The trace that was within the given throwable.
	 * @since 2020/06/11
	 */
	public static native TracePointBracket[] getThrowableTrace(Throwable __t);
	
	/**
	 * Resolves the address from the given point.
	 *
	 * @param __point The point to resolve.
	 * @return The address.
	 * @since 2020/06/16
	 */
	public static native long pointAddress(TracePointBracket __point);
	
	/**
	 * Resolves the class from the given point.
	 *
	 * @param __point The point to resolve.
	 * @return The class.
	 * @since 2020/06/16
	 */
	public static native String pointClass(TracePointBracket __point);
	
	/**
	 * Resolves the file from the given point.
	 *
	 * @param __point The point to resolve.
	 * @return The file.
	 * @since 2020/06/16
	 */
	public static native String pointFile(TracePointBracket __point);
	
	/**
	 * Resolves the Java address from the given point.
	 *
	 * @param __point The point to resolve.
	 * @return The Java address.
	 * @since 2020/06/16
	 */
	public static native int pointJavaAddress(TracePointBracket __point);
	
	/**
	 * Resolves the Java operation from the given point.
	 *
	 * @param __point The point to resolve.
	 * @return The Java operation.
	 * @since 2020/06/16
	 */
	public static native int pointJavaOperation(TracePointBracket __point);
	
	/**
	 * Resolves the line from the given point.
	 *
	 * @param __point The point to resolve.
	 * @return The line.
	 * @since 2020/06/16
	 */
	public static native int pointLine(TracePointBracket __point);
	
	/**
	 * Resolves the method name from the given point.
	 *
	 * @param __point The point to resolve.
	 * @return The method name.
	 * @since 2020/06/16
	 */
	public static native String pointMethodName(TracePointBracket __point);
	
	/**
	 * Resolves the method type from the given point.
	 *
	 * @param __point The point to resolve.
	 * @return The method type.
	 * @since 2020/06/16
	 */
	public static native String pointMethodType(TracePointBracket __point);
	
	/**
	 * Traces the entire stack, the top-most trace point in the stack is always
	 * first.
	 *
	 * @return The stack trace.
	 * @since 2020/06/11
	 */
	public static native TracePointBracket[] traceStack();
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/JarPackageShelf.java.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

import cc.squirreljme.jvm.mle.brackets.JarPackageBracket;
import java.io.InputStream;

/**
 * This allows access to the library class path and resources.
 *
 * @since 2020/06/07
 */
public final class JarPackageShelf
{
	/**
	 * Returns the classpath of the current program.
	 *
	 * @return The classpath of the current program.
	 * @since 2020/06/07
	 */
	public static native JarPackageBracket[] classPath();
	
	/**
	 * Opens the resource from the input stream.
	 *
	 * @param __jar The JAR to open.
	 * @param __rc The resource to load from the given JAR.
	 * @return Input stream to the resource.
	 * @since 2020/06/07
	 */
	public static native InputStream openResource(JarPackageBracket __jar,
		String __rc);
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/MathShelf.java.































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

/**
 * This contains various math functions.
 *
 * @since 2020/06/18
 */
public final class MathShelf
{
	/**
	 * Not used.
	 *
	 * @since 2020/06/18
	 */
	private MathShelf()
	{
	}
	
	/**
	 * Extracts the raw bits of the given value.
	 *
	 * @param __v The value to extract.
	 * @return The raw bits.
	 * @since 2020/06/18
	 */
	public static native long rawDoubleToLong(double __v);
	
	/**
	 * Extracts the raw bits of the given value.
	 *
	 * @param __v The value to extract.
	 * @return The raw bits.
	 * @since 2020/06/18
	 */
	public static native int rawFloatToInt(float __v);
	
	/**
	 * Composes the value from the given bits
	 *
	 * @param __b The raw bits.
	 * @return The value.
	 * @since 2020/06/18
	 */
	public static native float rawIntToFloat(int __b);
	
	/**
	 * Composes the value from the given bits
	 *
	 * @param __b The raw bits.
	 * @return The value.
	 * @since 2020/06/18
	 */
	public static native double rawLongToDouble(long __b);
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/ObjectShelf.java.



























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

import cc.squirreljme.jvm.mle.brackets.TypeBracket;
import cc.squirreljme.jvm.mle.constants.MonitorResultType;

/**
 * This shelf supports object anything that has to do with objects.
 *
 * @since 2020/06/09
 */
public final class ObjectShelf
{
	/**
	 * Not used.
	 *
	 * @since 2020/06/09
	 */
	private ObjectShelf()
	{
	}
	
	/**
	 * Copies the given arrays.
	 * 
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The elements to copy.
	 * @since 2020/06/22
	 */
	public static native void arrayCopy(boolean[] __src, int __srcOff,
		boolean[] __dest, int __destOff, int __len);
	
	/**
	 * Copies the given arrays.
	 * 
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The elements to copy.
	 * @since 2020/06/22
	 */
	public static native void arrayCopy(byte[] __src, int __srcOff,
		byte[] __dest, int __destOff, int __len);
	
	/**
	 * Copies the given arrays.
	 * 
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The elements to copy.
	 * @since 2020/06/22
	 */
	public static native void arrayCopy(short[] __src, int __srcOff,
		short[] __dest, int __destOff, int __len);
	
	/**
	 * Copies the given arrays.
	 * 
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The elements to copy.
	 * @since 2020/06/22
	 */
	public static native void arrayCopy(char[] __src, int __srcOff,
		char[] __dest, int __destOff, int __len);
	
	/**
	 * Copies the given arrays.
	 * 
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The elements to copy.
	 * @since 2020/06/22
	 */
	public static native void arrayCopy(int[] __src, int __srcOff,
		int[] __dest, int __destOff, int __len);
	
	/**
	 * Copies the given arrays.
	 * 
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The elements to copy.
	 * @since 2020/06/22
	 */
	public static native void arrayCopy(long[] __src, int __srcOff,
		long[] __dest, int __destOff, int __len);
	
	/**
	 * Copies the given arrays.
	 * 
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The elements to copy.
	 * @since 2020/06/22
	 */
	public static native void arrayCopy(float[] __src, int __srcOff,
		float[] __dest, int __destOff, int __len);
	
	/**
	 * Copies the given arrays.
	 * 
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __len The elements to copy.
	 * @since 2020/06/22
	 */
	public static native void arrayCopy(double[] __src, int __srcOff,
		double[] __dest, int __destOff, int __len);
	
	/**
	 * Returns the length of the array if this object is an array.
	 *
	 * @param __object The object to get the length of.
	 * @return The length of the array or a negative value if this is not an
	 * array.
	 * @since 2020/06/09
	 */
	public static native int arrayLength(Object __object);
	
	/**
	 * Allocates a new array.
	 *
	 * @param <T> The resultant type of the array.
	 * @param __type The type to allocate the array for.
	 * @param __len The length of the array.
	 * @return The newly allocated array as the given object.
	 * @since 2020/06/09
	 */
	public static native <T> T arrayNew(TypeBracket __type, int __len);
	
	/**
	 * Checks if the given thread holds the lock on the given method.
	 *
	 * @param __javaThread The Java thread to check if it holds the lock.
	 * @param __o The object to check.
	 * @return If the given thread holds the lock.
	 * @since 2020/06/17
	 */
	public static native boolean holdsLock(Thread __javaThread, Object __o);
	
	/**
	 * Returns the identity hashcode of the object.
	 *
	 * @param __o The object to get the hashcode of.
	 * @return The identity hashcode of the object.
	 * @since 2020/06/18
	 */
	public static native int identityHashCode(Object __o);
	
	/**
	 * Creates a new instance of the given type.
	 *
	 * @param __type The type to instantiate.
	 * @return The newly created object or {@code null} if there was no
	 * memory left.
	 * @since 2020/06/17
	 */
	public static native Object newInstance(TypeBracket __type);
	
	/**
	 * Notifies the monitors holding onto this object.
	 * 
	 * @param __object The object to signal.
	 * @param __all Notify all threads?
	 * @return The {@link MonitorResultType}.
	 * @since 2020/06/22
	 */
	public static native int notify(Object __object, boolean __all);
	
	/**
	 * Waits on the given monitor.
	 * 
	 * @param __object The object to wait on.
	 * @param __ms The milliseconds to wait.
	 * @param __ns The nanoseconds to wait.
	 * @return The {@link MonitorResultType}.
	 * @since 2020/06/22
	 */
	public static native int wait(Object __object, long __ms, int __ns);
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/ReferenceShelf.java.





















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

import cc.squirreljme.jvm.mle.brackets.RefLinkBracket;

/**
 * This provides the interface for references which are used to weakly refer
 * to them, so that they may be collected or act as a cache.
 *
 * @see RefLinkBracket
 * @since 2020/05/30
 */
public final class ReferenceShelf
{
	/**
	 * Not used.
	 *
	 * @since 2020/05/30
	 */
	private ReferenceShelf()
	{
	}
	
	/**
	 * Deletes the reference link, freeing any associated memory.
	 *
	 * @param __link The link to delete.
	 * @since 2020/05/30
	 */
	public static native void deleteLink(RefLinkBracket __link);
	
	/**
	 * Returns the link after the specified one.
	 *
	 * @param __link The link.
	 * @return The next link or {@code null} if there is none.
	 * @since 2020/05/30
	 */
	public static native RefLinkBracket linkGetNext(RefLinkBracket __link);
	
	/**
	 * Gets the object this points to.
	 *
	 * @param __link The link to get the object of.
	 * @return The object that this points to, or {@code null} if there
	 * is no pointed object.
	 * @since 2020/05/30
	 */
	public static native Object linkGetObject(RefLinkBracket __link);
	
	/**
	 * Returns the link before the specified one.
	 *
	 * @param __link The link.
	 * @return The previous link or {@code null} if there is none.
	 * @since 2020/05/30
	 */
	public static native RefLinkBracket linkGetPrev(RefLinkBracket __link);
	
	/**
	 * Sets the link that is after this one
	 *
	 * @param __link The link.
	 * @param __next The new link to set, may be {@code null} to clear.
	 * @since 2020/05/30
	 */
	public static native void linkSetNext(RefLinkBracket __link,
		RefLinkBracket __next);
	
	/**
	 * Sets the object that this points to.
	 *
	 * @param __link The link to be given the object.
	 * @param __v The object to set to, may be {@code null}.
	 * @since 2020/05/30
	 */
	public static native void linkSetObject(RefLinkBracket __link, Object __v);
	
	/**
	 * Sets the link that is before this one.
	 *
	 * @param __link The link.
	 * @param __prev The new link to set, may be {@code null} to clear.
	 * @since 2020/05/30
	 */
	public static native void linkSetPrev(RefLinkBracket __link,
		RefLinkBracket __prev);
	
	/**
	 * Creates a new reference link.
	 *
	 * @return The newly created reference link.
	 * @since 2020/05/30
	 */
	public static native RefLinkBracket newLink();
	
	/**
	 * Gets the link of an object.
	 *
	 * @param __o The object to get the link of.
	 * @return The link of the object or {@code null} if there is none.
	 * @since 2020/05/30
	 */
	public static native RefLinkBracket objectGet(Object __o);
	
	/**
	 * Sets the link of the object.
	 *
	 * @param __o The object to set the link of.
	 * @param __link The link to set to it.
	 * @since 2020/05/30
	 */
	public static native void objectSet(Object __o, RefLinkBracket __link);
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/RuntimeShelf.java.

































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

import cc.squirreljme.jvm.mle.constants.LineEndingType;
import cc.squirreljme.jvm.mle.constants.BuiltInEncodingType;
import cc.squirreljme.jvm.mle.constants.BuiltInLocaleType;
import cc.squirreljme.jvm.mle.constants.VMDescriptionType;
import cc.squirreljme.jvm.mle.constants.VMStatisticType;
import cc.squirreljme.jvm.mle.constants.VMType;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Run-time shelf which contains system information.
 *
 * @since 2020/06/09
 */
public final class RuntimeShelf
{
	/**
	 * Not used.
	 *
	 * @since 2020/06/09
	 */
	private RuntimeShelf()
	{
	}
	
	/**
	 * Returns the current time in milliseconds since UTC.
	 *
	 * @return The current time in milliseconds since UTC.
	 * @since 2020/06/18
	 */
	public static native long currentTimeMillis();
	
	/**
	 * Returns the encoding of the system.
	 *
	 * @return The encoding of the system, see {@link BuiltInEncodingType}.
	 * @see BuiltInEncodingType
	 * @since 2020/06/11
	 */
	public static native int encoding();
	
	/**
	 * Exits the virtual machine.
	 *
	 * @param __code The exit code.
	 * @since 2020/06/16
	 */
	public static native void exit(int __code);
	
	/**
	 * Returns the line ending type of the system.
	 *
	 * @return The line ending type of the system, see {@link LineEndingType}.
	 * @see LineEndingType
	 * @since 2020/06/09
	 */
	public static native int lineEnding();
	
	/**
	 * The built-in locate to use.
	 *
	 * @return The built-in locale, see {@link BuiltInLocaleType}.
	 * @see BuiltInLocaleType
	 * @since 2020/06/11
	 */
	public static native int locale();
	
	/**
	 * Returns the number of monotonic nanoseconds that have elapsed.
	 *
	 * @return The monotonic nanosecond clock.
	 * @since 2020/06/18
	 */
	public static native long nanoTime();
	
	/**
	 * Returns the system property for the given key, if there is one.
	 *
	 * @param __key The property key.
	 * @return The value of the system property or {@code null}.
	 * @throws MLECallError If {@code __key} is {@code null}.
	 * @since 2020/06/17
	 */
	public static native String systemProperty(String __key)
		throws MLECallError;
	
	/**
	 * Returns a special virtual machine description.
	 *
	 * @param __type The {@link VMDescriptionType}.
	 * @return The string for the given description or {@code null} if not
	 * set.
	 * @throws MLECallError If {@code __type} is not valid.
	 * @since 2020/06/17
	 */
	public static native String vmDescription(int __type)
		throws MLECallError;
	
	/**
	 * Returns a statistic of the virtual machine.
	 *
	 * @param __type The {@link VMStatisticType}.
	 * @return The value of the statistic, or {@code 0L} if not set.
	 * @throws MLECallError If {@code __type} is not valid.
	 * @since 2020/06/17
	 */
	public static native long vmStatistic(int __type)
		throws MLECallError;
	
	/**
	 * Returns the current {@link VMType}.
	 *
	 * @return The current {@link VMType}.
	 * @since 2020/06/16
	 */
	public static native int vmType();
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/TerminalShelf.java.





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

import cc.squirreljme.jvm.mle.constants.StandardPipeType;
import cc.squirreljme.runtime.cldc.annotation.Api;
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * This contains the shell for printing to the console and otherwise.
 *
 * @since 2020/06/14
 */
public final class TerminalShelf
{
	/**
	 * Not used.
	 *
	 * @since 2002/06/14
	 */
	private TerminalShelf()
	{
	}
	
	/**
	 * Flushes the stream.
	 *
	 * @param __fd The {@link StandardPipeType} to flush.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/12/08
	 */
	public static native int flush(int __fd);
	
	/**
	 * Writes the character to the console output.
	 *
	 * @param __fd The {@link StandardPipeType} to write to.
	 * @param __c The byte to write, only the lowest 8-bits are used.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/09/21
	 */
	public static native int write(int __fd, int __c);
	
	/**
	 * Writes the given bytes to the console output.
	 *
	 * @param __fd The {@link StandardPipeType} to write to.
	 * @param __b The bytes to write.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/12/05
	 */
	public static native int write(int __fd, byte[] __b, int __o, int __l);
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/ThreadShelf.java.













































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

import cc.squirreljme.jvm.mle.brackets.VMThreadBracket;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * This shelf handles everything regarding threading and otherwise.
 *
 * @see VMThreadBracket
 * @since 2020/06/17
 */
public final class ThreadShelf
{
	/**
	 * Returns the number of alive threads.
	 *
	 * @param __includeMain Include main threads?
	 * @param __includeDaemon Include daemon threads?
	 * @return The number of alive threads.
	 * @since 2020/06/17
	 */
	public static native int aliveThreadCount(boolean __includeMain,
		boolean __includeDaemon);
	
	/**
	 * Creates a virtual machine thread for the given Java thread.
	 *
	 * @param __javaThread The Java thread to create under.
	 * @return The virtual machine thread.
	 * @throws MLECallError If {@code __javaThread} is null.
	 * @since 2020/06/17
	 */
	public static native VMThreadBracket createVMThread(Thread __javaThread)
		throws MLECallError;
	
	/**
	 * Returns the current Java thread.
	 *
	 * @return The current {@link Thread}.
	 * @since 2020/06/17
	 */
	public static native Thread currentJavaThread();
	
	/**
	 * Returns the exit code for the current process.
	 *
	 * @return The exit code for the current process.
	 * @since 2020/06/17
	 */
	public static native int currentExitCode();
	
	/**
	 * Returns whether the interrupt flag was raised and clears it.
	 *
	 * @param __javaThread The Java thread.
	 * @return If the thread was interrupted.
	 * @throws MLECallError If {@code __javaThread} is null.
	 * @since 2020/06/17
	 */
	public static native boolean javaThreadClearInterrupt(Thread __javaThread)
		throws MLECallError;
	
	/**
	 * Marks the thread as being started.
	 *
	 * @param __javaThread The thread to mark started.
	 * @throws MLECallError If {@code __javaThread} is null.
	 * @since 2020/06/17
	 */
	public static native void javaThreadFlagStarted(Thread __javaThread)
		throws MLECallError;
	
	/**
	 * Has this Java thread been started?
	 *
	 * @param __javaThread The Java thread.
	 * @return If this thread has been started.
	 * @throws MLECallError If {@code __javaThread} is null.
	 * @since 2020/06/17
	 */
	public static native boolean javaThreadIsStarted(Thread __javaThread)
		throws MLECallError;
	
	/**
	 * Returns the runnable for the given Java thread.
	 *
	 * @param __javaThread The Java thread.
	 * @return The {@link Runnable} for the given thread.
	 * @throws MLECallError If {@code __javaThread} is null.
	 * @since 2020/06/17
	 */
	public static native Runnable javaThreadRunnable(Thread __javaThread)
		throws MLECallError;
	
	/**
	 * Sets if the thread is alive or not.
	 *
	 * @param __javaThread The Java thread.
	 * @param __set If this is to be alive or not. If this is {@code true}
	 * then the active count goes up, otherwise it shall go down.
	 * @throws MLECallError If {@code __javaThread} is null.
	 * @since 2020/06/17
	 */
	public static native void javaThreadSetAlive(Thread __javaThread,
		boolean __set)
		throws MLECallError;
	
	/**
	 * Runs the main entry point for the current process and gives it all of
	 * the arguments that were specified on program initialization.
	 *
	 * @since 2020/06/17
	 */
	public static native void runProcessMain();
	
	/**
	 * Sets the current process exit code.
	 *
	 * @param __code The exit code to use.
	 * @since 2020/06/17
	 */
	public static native void setCurrentExitCode(int __code);
	
	/**
	 * Sleeps the current thread for the given amount of time.
	 *
	 * If both times are zero, this means to yield the thread (give up its
	 * current execution context).
	 *
	 * @param __ms The number of milliseconds.
	 * @param __ns The number of nanoseconds.
	 * @return {@code true} if the thread was interrupted.
	 * @throws MLECallError If either value is negative or the nanoseconds is
	 * out of range.
	 * @since 2020/06/17
	 */
	public static native boolean sleep(int __ms, int __ns)
		throws MLECallError;
	
	/**
	 * Returns the Java thread for the VM thread.
	 *
	 * @param __vmThread The VM thread.
	 * @return The Java thread which belongs to this thread.
	 * @throws MLECallError If {@code __thread} is null.
	 * @since 2020/06/17
	 */
	public static native Thread toJavaThread(VMThreadBracket __vmThread)
		throws MLECallError;
	
	/**
	 * Returns the virtual machine thread from the given Java thread.
	 *
	 * @param __thread The Java thread.
	 * @return The VM thread for this thread.
	 * @throws MLECallError If {@code __thread} is null.
	 * @since 2020/06/17
	 */
	public static native VMThreadBracket toVMThread(Thread __thread)
		throws MLECallError;
	
	/**
	 * Returns the thread ID for the given thread.
	 *
	 * @param __vmThread The virtual machine thread.
	 * @return The thread ID.
	 * @throws MLECallError If {@code __vmThread} is null.
	 * @since 2020/06/17
	 */
	public static native int vmThreadId(VMThreadBracket __vmThread)
		throws MLECallError;
	
	/**
	 * Performs a hardware interrupt on the thread.
	 *
	 * @param __vmThread The virtual machine thread.
	 * @throws MLECallError If {@code __vmThread} is null.
	 * @since 2020/06/17
	 */
	public static native void vmThreadInterrupt(VMThreadBracket __vmThread)
		throws MLECallError;
	
	/**
	 * Checks if the given thread is a main thread.
	 *
	 * @param __vmThread The thread to check.
	 * @return {@code true} if the given thread is a main thread.
	 * @throws MLECallError If {@code __vmThread} is null.
	 * @since 2020/06/17
	 */
	public static native boolean vmThreadIsMain(VMThreadBracket __vmThread)
		throws MLECallError;
	
	/**
	 * Sets the thread priority in the same manner as
	 * {@link Thread#setPriority(int)} if this is supported by the hardware.
	 * 
	 * This may or may not be supported and should only be used as a hint and
	 * not a guarantee.
	 *
	 * @param __vmThread The virtual machine thread.
	 * @param __p The priority to set, this will be the same as
	 * {@link Thread#setPriority(int)}.
	 * @throws MLECallError If {@code __vmThread} is null or {@code __p} is
	 * not within {@link Thread#MIN_PRIORITY} and {@link Thread#MAX_PRIORITY}
	 * inclusive.
	 * @since 2020/06/17
	 */
	public static native void vmThreadSetPriority(VMThreadBracket __vmThread,
		int __p)
		throws MLECallError;
	
	/**
	 * Performs the actual start of the given thread.
	 *
	 * @param __vmThread The thread to start.
	 * @return If the start of the thread succeeded.
	 * @throws MLECallError If {@code __vmThread} is null.
	 * @since 2020/06/17
	 */
	public static native boolean vmThreadStart(VMThreadBracket __vmThread)
		throws MLECallError;
	
	/**
	 * Waits for the state of threads to be updated, or just times out.
	 *
	 * A thread update is when another thread becomes alive, becomes dead,
	 * or is started.
	 *
	 * @param __ms The amount of time to wait for.
	 * @return If the thread was interrupted while waiting.
	 * @throws MLECallError If {@code __ms} is negative.
	 * @since 2020/06/17
	 */
	public static native boolean waitForUpdate(int __ms)
		throws MLECallError;
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/TypeShelf.java.





































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle;

import cc.squirreljme.jvm.mle.brackets.JarPackageBracket;
import cc.squirreljme.jvm.mle.brackets.TypeBracket;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Provides the shelf for types that exist within the JVM.
 *
 * @since 2020/05/30
 */
public final class TypeShelf
{
	/**
	 * Returns the binary name of the given class.
	 *
	 * @param __type The type to get the binary name of.
	 * @return The binary name of this class.
	 * @since 2020/06/07
	 */
	public static native String binaryName(TypeBracket __type);
	
	/**
	 * Returns the name of the package the class is within.
	 *
	 * @param __type The type to get the binary package of.
	 * @return The binary name of the package the class is in.
	 * @since 2020/06/07
	 */
	public static native String binaryPackageName(TypeBracket __type);
	
	/**
	 * Returns the type that is used within the given class.
	 *
	 * @param __cl The class to get the type of.
	 * @return The type of the given class.
	 * @since 2020/06/07
	 */
	public static native TypeBracket classToType(Class<?> __cl);
	
	/**
	 * Returns the component type of the class.
	 *
	 * @param __type The type to get the component of.
	 * @return The component type of the class.
	 * @throws MLECallError If {@code __type} is {@code null} or is not an
	 * array type.
	 * @since 2020/06/07
	 */
	public static native TypeBracket component(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Returns the root component of this type, this is essentially calling
	 * {@link #component(TypeBracket)} over until the type is no longer an
	 * array type.
	 *
	 * @param __type The type to get the root component of.
	 * @return The root component of the type.
	 * @since 2020/06/07
	 */
	public static native TypeBracket componentRoot(TypeBracket __type);
	
	/**
	 * Returns the number of dimensions this type has.
	 *
	 * @param __type The type to get the dimension count for.
	 * @return The number of dimensions for the type, this will be {@code 0}
	 * if this is not an array.
	 * @throws MLECallError If {@code __type} is {@code null}.
	 * @since 2020/07/06
	 */
	public static native int dimensions(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Gets the enumeration values for the given type.
	 * 
	 * @param __type The type to get the enumerated values from.
	 * @return The enumeration values for the given type.
	 * @throws MLECallError If {@code __type} is {@code null} or is not an
	 * enumeration.
	 * @since 2020/06/28
	 */
	@SuppressWarnings("rawtypes")
	public static native Enum[] enumValues(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Since types are virtual objects that do not have a true base off
	 * {@link Object}, this method is used to compare two types with each
	 * other.
	 *
	 * @param __a The first type.
	 * @param __b The second type.
	 * @return If these two types are the same.
	 * @since 2020/06/04
	 */
	public static native boolean equals(TypeBracket __a, TypeBracket __b);
	
	/**
	 * Finds a type by it's name.
	 *
	 * @param __name The name of the type.
	 * @return The type bracket for the type or {@code null} if none was
	 * found.
	 * @since 2020/06/02
	 */
	public static native TypeBracket findType(String __name);
	
	/**
	 * Returns the JAR that the type is within.
	 *
	 * @param __type The type to get the JAR of.
	 * @return The JAR that the type is within or {@code null} if this type
	 * is not within any JAR.
	 * @since 2020/06/07
	 */
	public static native JarPackageBracket inJar(TypeBracket __type);
	
	/**
	 * Returns the interfaces of the type.
	 *
	 * @param __type The type to get the interfaces of.
	 * @return The interfaces of the class.
	 * @throws MLECallError If {@code __type} is null. 
	 * @since 2020/06/07
	 */
	public static native TypeBracket[] interfaces(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Returns true if this type is an array.
	 *
	 * @param __type The type to check.
	 * @return If this is an array.
	 * @throws MLECallError If {@code __type} is {@code null}.
	 * @since 2020/06/07
	 */
	public static native boolean isArray(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Checks if this is an enumeration.
	 * 
	 * @param __type The type to check.
	 * @return If this is an enumeration.
	 * @throws MLECallError If {@code __type} is {@code null}.
	 * @since 2020/06/28
	 */
	public static native boolean isEnum(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Returns true if this type is an interface.
	 *
	 * @param __type The type to check.
	 * @return If this is an interface.
	 * @throws MLECallError If {@code __type} is {@code null}.
	 * @since 2020/06/07
	 */
	public static native boolean isInterface(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Returns true if this is a primitive type.
	 *
	 * @param __type The type to check.
	 * @return If this is a primitive.
	 * @throws MLECallError If {@code __type} is {@code null}.
	 * @since 2020/06/07
	 */
	public static native boolean isPrimitive(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Returns the type of the given object.
	 *
	 * @param __o The object to get the type of.
	 * @return The type of the given object.
	 * @since 2020/06/02
	 */
	public static native TypeBracket objectType(Object __o);
	
	/**
	 * Returns the run-time name of a type as it would be if
	 * {@link Class#getName()} were called.
	 *
	 * @param __type The type to get the name of.
	 * @return The runtime name of the class.
	 * @throws MLECallError If {@code __type} is {@code null}.
	 * @since 2020/06/07
	 */
	public static native String runtimeName(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Returns the super class of this class.
	 *
	 * @param __type The super class of this type.
	 * @return Return the super class or {@code null} on null arguments.
	 * @throws MLECallError If {@code __type} is {@code null}.
	 * @since 2020/06/07
	 */
	public static native TypeBracket superClass(TypeBracket __type)
		throws MLECallError;
	
	/**
	 * Returns the type holder for the {@code boolean} primitive type.
	 *
	 * @return The type for the primitive type.
	 * @since 2020/05/30
	 */
	public static native TypeBracket typeOfBoolean();
	
	/**
	 * Returns the type holder for the {@code byte} primitive type.
	 *
	 * @return The type for the primitive type.
	 * @since 2020/05/30
	 */
	public static native TypeBracket typeOfByte();
	
	/**
	 * Returns the type holder for the {@code short} primitive type.
	 *
	 * @return The type for the primitive type.
	 * @since 2020/05/30
	 */
	public static native TypeBracket typeOfShort();
	
	/**
	 * Returns the type holder for the {@code char} primitive type.
	 *
	 * @return The type for the primitive type.
	 * @since 2020/05/30
	 */
	public static native TypeBracket typeOfCharacter();
	
	/**
	 * Returns the type holder for the {@code int} primitive type.
	 *
	 * @return The type for the primitive type.
	 * @since 2020/05/30
	 */
	public static native TypeBracket typeOfInteger();
	
	/**
	 * Returns the type holder for the {@code long} primitive type.
	 *
	 * @return The type for the primitive type.
	 * @since 2020/05/30
	 */
	public static native TypeBracket typeOfLong();
	
	/**
	 * Returns the type holder for the {@code float} primitive type.
	 *
	 * @return The type for the primitive type.
	 * @since 2020/05/30
	 */
	public static native TypeBracket typeOfFloat();
	
	/**
	 * Returns the type holder for the {@code double} primitive type.
	 *
	 * @return The type for the primitive type.
	 * @since 2020/05/30
	 */
	public static native TypeBracket typeOfDouble();
	
	/**
	 * Gets the class type of the given bracket.
	 *
	 * @param <T> Ignored.
	 * @param __type The type to get the class object of.
	 * @return The class type for the given type.
	 * @since 2020/05/30
	 */
	public static native <T> Class<T> typeToClass(TypeBracket __type);
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/annotation/GhostObject.java.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * When used with an interface this represents that the object has no real
 * backing to it and is treated as a special object.
 *
 * @since 2020/05/30
 */
@Documented
@Retention(value=RetentionPolicy.CLASS)
@Target(value={ElementType.TYPE})
public @interface GhostObject
{
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/annotation/package-info.java.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This package contains annotations which are used to potentially modify
 * or signal information about a class or otherwise.
 *
 * @since 2020/05/30
 */

package cc.squirreljme.jvm.mle.annotation;

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/brackets/JarPackageBracket.java.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.brackets;

import cc.squirreljme.jvm.mle.annotation.GhostObject;

/**
 * This represents a bracket which is a reference to a JAR file that is on
 * the library ROM or classpath.
 *
 * @since 2020/06/07
 */
@GhostObject
public interface JarPackageBracket
{
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/brackets/JarResourceBracket.java.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.brackets;

import cc.squirreljme.jvm.mle.annotation.GhostObject;

/**
 * This represents a resource within a JAR file.
 *
 * @since 2020/06/07
 */
@GhostObject
public interface JarResourceBracket
{
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/brackets/RefLinkBracket.java.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.brackets;

import cc.squirreljme.jvm.mle.annotation.GhostObject;

/**
 * This contains a reference to an object that is not bound strongly to a
 * reference.
 *
 * This class is effectively a linked list of references.
 *
 * @since 2020/05/30
 */
@GhostObject
public interface RefLinkBracket
{
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/brackets/TracePointBracket.java.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.brackets;

import cc.squirreljme.jvm.mle.annotation.GhostObject;

/**
 * This represents a single point of tracing within the virtual machine.
 *
 * @since 2020/06/11
 */
@GhostObject
public interface TracePointBracket
{
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/brackets/TypeBracket.java.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.brackets;

import cc.squirreljme.jvm.mle.annotation.GhostObject;

/**
 * This represents a type's internal information, for example how to handle it
 * from within the VM.
 *
 * @since 2020/05/30
 */
@GhostObject
public interface TypeBracket
{
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/brackets/VMThreadBracket.java.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.brackets;

import cc.squirreljme.jvm.mle.ThreadShelf;
import cc.squirreljme.jvm.mle.annotation.GhostObject;

/**
 * This bracket represents extra information regarding threads and otherwise.
 *
 * @see ThreadShelf
 * @since 2020/06/17
 */
@GhostObject
public interface VMThreadBracket
{
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/brackets/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This package contains special brackets which are used by the shelf layers.
 *
 * @since 2020/05/30
 */

package cc.squirreljme.jvm.mle.brackets;

Name change from modules/cldc-compact/src/main/java/cc/squirreljme/jvm/config/BuiltInEncoding.java to modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/BuiltInEncodingType.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.config;

/**
 * Encoding IDs which are built-in to SquirrelJME.
 *
 * @since 2020/04/07
 */
public interface BuiltInEncoding
{
	/** Unspecified, use defined property or assume UTF-8. */
	byte UNSPECIFIED =
		0;
	
	/** UTF-8. */
	byte UTF8 =









|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * Encoding IDs which are built-in to SquirrelJME.
 *
 * @since 2020/04/07
 */
public interface BuiltInEncodingType
{
	/** Unspecified, use defined property or assume UTF-8. */
	byte UNSPECIFIED =
		0;
	
	/** UTF-8. */
	byte UTF8 =

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/BuiltInLocaleType.java.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * Represents a locale which is built-in.
 *
 * @since 2020/06/11
 */
public interface BuiltInLocaleType
{
	/** Unspecified. */
	byte UNSPECIFIED =
		0;
	
	/** English, US. */
	byte ENGLISH_US =
		1;
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/LineEndingType.java.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * Constants for line ending.
 *
 * @since 2020/06/09
 */
public interface LineEndingType
{
	/** Unknown. */
	byte UNSPECIFIED =
		0;
	
	/** LF. */
	byte LF =
		1;
	
	/** CR. */
	byte CR =
		2;
	
	/** CRLF. */
	byte CRLF =
		3;
		
	/** Number of line types. */
	byte NUM_LINE_ENDINGS =
		4;
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/MonitorResultType.java.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * The type of signal generated from the monitor.
 *
 * @since 2020/06/22
 */
public interface MonitorResultType
{
	/** NOT_INTERRUPTED. */
	byte NOT_INTERRUPTED =
		1;
	
	/** Interrupted. */
	byte INTERRUPTED =
		0;
	
	/** The object is not owned. */
	byte NOT_OWNED =
		-1;
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/ProtectedPackages.java.











































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * This class contains all of the packages which are protected and are not
 * permitted to have additional classes added within.
 *
 * @since 2020/06/21
 */
public final class ProtectedPackages
{
	/**
	 * Not used.
	 * 
	 * @since 2020/06/21
	 */
	private ProtectedPackages()
	{
	}
	
	/**
	 * Checks to see if the package is protected, if it is then no other
	 * JAR may add to it. This will be recursively checked so any package
	 * under a given one will not be permitted.
	 * 
	 * @param __name The package name, must be in binary name form.
	 * @return If this package is protected.
	 * @throws IllegalArgumentException If the name contains a period as this
	 * means it potentially is being called incorrectly.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/21
	 */
	public static boolean isProtectedPackage(String __name)
		throws IllegalArgumentException, NullPointerException
	{
		if (__name == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ37 Package contains a period. (The name)}
		if (__name.indexOf('.') >= 0)
			throw new IllegalArgumentException("ZZ37 " + __name);
		
		// Try these
		switch (__name)
		{
				// These packages must never be changed
			case "cc/squirreljme/jvm":
			case "java/lang":
				return true;
		}
		
		// No more packages to check
		int lastSlash = __name.lastIndexOf('/');
		if (lastSlash < 0)
			return false;
		
		// Recurse into parent packages
		return ProtectedPackages.isProtectedPackage(
			__name.substring(0, lastSlash));
	}
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/StandardPipeType.java.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * Standard pipe descriptor identifiers.
 *
 * @since 2020/06/14
 */
public interface StandardPipeType
{
	/** Standard output. */
	byte STDOUT =
		1;
	
	/** Standard error. */
	byte STDERR =
		2;
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/VMDescriptionType.java.





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * Represents the type of description used for the VM.
 *
 * @since 2020/06/17
 */
public interface VMDescriptionType
{
	/** Unspecified. */
	byte UNSPECIFIED =
		0;
	
	/** The VM version. */
	byte VM_VERSION =
		1;
	
	/** The VM name. */
	byte VM_NAME =
		2;
	
	/** The VM Vendor. */
	byte VM_VENDOR =
		3;
	
	/** The VM E-mail. */
	byte VM_EMAIL =
		4;
	
	/** The VM URL. */
	byte VM_URL =
		5;
	
	/** The executable path of the VM. */
	byte EXECUTABLE_PATH =
		6;
	
	/** The operating system name. */
	byte OS_NAME =
		7;
	
	/** The operating system version. */
	byte OS_VERSION =
		8;
	
	/** The operating system architecture. */
	byte OS_ARCH =
		9;
	
	/** The current number of properties. */
	byte NUM_TYPES =
		10;
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/VMStatisticType.java.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * Used to get a statistic from the VM.
 *
 * @since 2020/06/17
 */
public interface VMStatisticType
{
	/** Unspecified. */
	byte UNSPECIFIED =
		0;
	
	/** The amount of free memory. */
	byte MEM_FREE =
		1;
	
	/** The maximum amount of memory. */
	byte MEM_MAX =
		2;
	
	/** The amount of used memory. */
	byte MEM_USED =
		3;
	
	/** The number of statistics. */
	byte NUM_STATISTICS =
		4;
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/VMType.java.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.constants;

/**
 * This represents the type of SquirrelJME virtual machine that is currently
 * being used, this is used for example to see which set of MLE calls are
 * valid and otherwise.
 *
 * @since 2020/06/16
 */
public interface VMType
{
	/** Not known. */
	byte UNKNOWN =
		0;
	
	/** Running on Standard Java SE. */
	byte JAVA_SE =
		1;
	
	/** Running on SpringCoat. */
	byte SPRINGCOAT =
		2;
	
	/** Running on SummerCoat. */
	byte SUMMERCOAT =
		3;
	
	/** The number of VM types. */
	byte NUM_VMTYPES =
		4;
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/constants/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This package contains constants.
 *
 * @since 2020/06/09
 */

package cc.squirreljme.jvm.mle.constants;

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/exceptions/MLECallError.java.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm.mle.exceptions;

/**
 * This is thrown when there was an error made during a MLE call.
 *
 * @since 2020/06/22
 */
public class MLECallError
	extends VirtualMachineError
{
	/**
	 * Initializes the exception with no message or cause.
	 *
	 * @since 2020/06/22
	 */
	public MLECallError()
	{
	}
	
	/**
	 * Initializes the exception with the given message and no cause.
	 *
	 * @param __m The message.
	 * @since 2020/06/22
	 */
	public MLECallError(String __m)
	{
		super(__m);
	}
	
	/**
	 * Initializes the exception with the given message and cause.
	 *
	 * @param __m The message.
	 * @param __t The cause.
	 * @since 2020/06/22
	 */
	public MLECallError(String __m, Throwable __t)
	{
		super(__m);
		
		this.initCause(__t);
	}
	
	/**
	 * Initializes the exception with the given cause and no message.
	 *
	 * @param __t The cause.
	 * @since 2020/06/22
	 */
	public MLECallError(Throwable __t)
	{
		this.initCause(__t);
	}
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/exceptions/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * Contains exceptions for the MLE layer.
 *
 * @since 2020/06/22
 */

package cc.squirreljme.jvm.mle.exceptions;

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/lle/package-info.java.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This package contains the low-level layer implementation of the middle-level
 * layer and is intended to be used by SummerCoat to perform the as-needed
 * executions of functions. This essentially acts as the virtual machine for
 * SummerCoat.
 *
 * @since 2020/05/29
 */

package cc.squirreljme.jvm.mle.lle;

Added modules/cldc-compact/src/main/java/cc/squirreljme/jvm/mle/package-info.java.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This package contains the middle-level emulation layer which provides
 * native methods which perform a specific function that has specific logic
 * that might be executed low-level in SummerCoat or high-level as in
 * SpringCoat.
 *
 * @since 2020/05/29
 */

package cc.squirreljme.jvm.mle;

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/Poking.java.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
		// NativeBinding class so that way our native calls can be initialized
		try
		{
			Class.forName("cc.squirreljme.emulator.NativeBinding")
				.newInstance();
		}
		catch (ClassNotFoundException|IllegalAccessException|
			InstantiationException e)
		{
			// Ignore
			e.printStackTrace(System.err);
		}
	}
}







|

<
<



36
37
38
39
40
41
42
43
44


45
46
47
		// NativeBinding class so that way our native calls can be initialized
		try
		{
			Class.forName("cc.squirreljme.emulator.NativeBinding")
				.newInstance();
		}
		catch (ClassNotFoundException|IllegalAccessException|
			InstantiationException ignored)
		{


		}
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/SquirrelJME.java.

16
17
18
19
20
21
22




23
24
 * @since 2018/12/05
 */
public interface SquirrelJME
{
	/** The version of this SquirrelJME runtime. */
	String RUNTIME_VERSION =
		"0.3.0";




}








>
>
>
>


16
17
18
19
20
21
22
23
24
25
26
27
28
 * @since 2018/12/05
 */
public interface SquirrelJME
{
	/** The version of this SquirrelJME runtime. */
	String RUNTIME_VERSION =
		"0.3.0";
	
	/** The microedition platform. */
	String MICROEDITION_PLATFORM =
		"SquirrelJME/0.3.0";
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/ConsoleCallback.java.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46

47
48
import java.io.IOException;

/**
 * This is the callback used for the console.
 *
 * @since 2019/02/02
 */

public interface ConsoleCallback
{
	/**
	 * This is called when the stream has been closed.
	 *
	 * @return {@code false} if an {@link IOException} occurred.
	 * @since 2019/02/02
	 */

	boolean close();
	
	/**
	 * This is called when the callback is flushed.
	 *
	 * @return {@code false} if an {@link IOException} occurred.
	 * @since 2019/02/02
	 */

	boolean flush();
	
	/**
	 * Writes the specified bytes to the output.
	 *
	 * @param __b The bytes to write.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return {@code false} if an {@link IOException} occurred.
	 * @since 2019/02/02
	 */

	boolean write(byte[] __b, int __o, int __l);
}







>








>








>











>


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import java.io.IOException;

/**
 * This is the callback used for the console.
 *
 * @since 2019/02/02
 */
@Deprecated
public interface ConsoleCallback
{
	/**
	 * This is called when the stream has been closed.
	 *
	 * @return {@code false} if an {@link IOException} occurred.
	 * @since 2019/02/02
	 */
	@Deprecated
	boolean close();
	
	/**
	 * This is called when the callback is flushed.
	 *
	 * @return {@code false} if an {@link IOException} occurred.
	 * @since 2019/02/02
	 */
	@Deprecated
	boolean flush();
	
	/**
	 * Writes the specified bytes to the output.
	 *
	 * @param __b The bytes to write.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return {@code false} if an {@link IOException} occurred.
	 * @since 2019/02/02
	 */
	@Deprecated
	boolean write(byte[] __b, int __o, int __l);
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/ConsoleOutput.java.

14
15
16
17
18
19
20

21
22
23

24
25
26
27

28
29
30
31

32
33
34
35

36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * Used for printing to the console.
 *
 * @since 2018/09/21
 */

public final class ConsoleOutput
{
	/** Standard output. */

	public static final int OUTPUT =
		1;
	
	/** Standard error. */

	public static final int ERROR =
		2;
	
	/** End of file. */

	public static final int ERROR_EOF =
		-1;
	
	/** Invalid file descriptor. */

	public static final int ERROR_INVALIDFD =
		-2;
	
	/**
	 * Not used.
	 *
	 * @since 2018/09/21
	 */

	private ConsoleOutput()
	{
	}
	
	/**
	 * Reads the display console, that is anything which was output to the
	 * console itself.
	 *
	 * @param __dim The output dimensions of the console, columns and rows.
	 * This array must always have a length of at least two.
	 * @param __b The output byte array.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return The number of bytes which were read, this will be the minimum
	 * of either {@code __dim[0] * __dim[1]} or {@code __l}. Zero may be
	 * returned if this is not supported.
	 * @since 2018/12/16
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int displayRead(int[] __dim,
		byte[] __b, int __o, int __l);
	
	/**
	 * Flushes the stream.
	 *
	 * @param __fd The file descriptor to flush.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/12/08
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int flush(int __fd);
	
	/**
	 * Writes the character to the console output.
	 *
	 * @param __fd The file descriptor to write to.
	 * @param __c The byte to write, only the lowest 8-bits are used.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/09/21
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int write(int __fd, int __c);
	
	/**
	 * Writes the given bytes to the console output.
	 *
	 * @param __fd The file descriptor to write to.
	 * @param __b The bytes to write.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/12/05
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int write(int __fd,
		byte[] __b, int __o, int __l);
}








>



>




>




>




>








>


















>











>











>













>





14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * Used for printing to the console.
 *
 * @since 2018/09/21
 */
@Deprecated
public final class ConsoleOutput
{
	/** Standard output. */
	@Deprecated
	public static final int OUTPUT =
		1;
	
	/** Standard error. */
	@Deprecated
	public static final int ERROR =
		2;
	
	/** End of file. */
	@Deprecated
	public static final int ERROR_EOF =
		-1;
	
	/** Invalid file descriptor. */
	@Deprecated
	public static final int ERROR_INVALIDFD =
		-2;
	
	/**
	 * Not used.
	 *
	 * @since 2018/09/21
	 */
	@Deprecated
	private ConsoleOutput()
	{
	}
	
	/**
	 * Reads the display console, that is anything which was output to the
	 * console itself.
	 *
	 * @param __dim The output dimensions of the console, columns and rows.
	 * This array must always have a length of at least two.
	 * @param __b The output byte array.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return The number of bytes which were read, this will be the minimum
	 * of either {@code __dim[0] * __dim[1]} or {@code __l}. Zero may be
	 * returned if this is not supported.
	 * @since 2018/12/16
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int displayRead(int[] __dim,
		byte[] __b, int __o, int __l);
	
	/**
	 * Flushes the stream.
	 *
	 * @param __fd The file descriptor to flush.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/12/08
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int flush(int __fd);
	
	/**
	 * Writes the character to the console output.
	 *
	 * @param __fd The file descriptor to write to.
	 * @param __c The byte to write, only the lowest 8-bits are used.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/09/21
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int write(int __fd, int __c);
	
	/**
	 * Writes the given bytes to the console output.
	 *
	 * @param __fd The file descriptor to write to.
	 * @param __b The bytes to write.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return Zero on success, negative values for failure.
	 * @since 2018/12/05
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int write(int __fd,
		byte[] __b, int __o, int __l);
}

Deleted modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/ObjectAccess.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.asm;

import cc.squirreljme.runtime.cldc.annotation.Api;
import cc.squirreljme.runtime.cldc.lang.ApiLevel;
import cc.squirreljme.runtime.cldc.lang.ClassData;
import cc.squirreljme.runtime.cldc.ref.PrimitiveReference;

/**
 * This contains accessors for object information.
 *
 * @since 2018/09/22
 */
@Deprecated
public final class ObjectAccess
{
	/** Monitor is not owned by this thread. */
	@Deprecated
	public static final int MONITOR_NOT_OWNED =
		-1;
	
	/** Monitor did not interrupt. */
	@Deprecated
	public static final int MONITOR_NOT_INTERRUPTED =
		0;
	
	/** Monitor did interrupt. */
	@Deprecated
	public static final int MONITOR_INTERRUPTED =
		1;
	
	/**
	 * Not used.
	 *
	 * @since 2018/09/22
	 */
	private ObjectAccess()
	{
	}
	
	/**
	 * Allocates an object but does not construct it
	 *
	 * @param __cl The class to allocate.
	 * @return An object for the class, it is not initialized with a
	 * constructor. Returns {@code null} if no more memory is available.
	 * @since 2018/12/04
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native Object allocateObject(String __cl);
	
	/**
	 * Creates a new array of the given type, this is the actual array and
	 * not the component.
	 *
	 * @param __t The array type, not the component type.
	 * @param __l The array length.
	 * @return An array allocated to the given length.
	 * @since 2018/09/25
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native Object arrayNew(Class<?> __t, int __l);
	
	/**
	 * Returns the class object for the specified class by its binary name.
	 *
	 * @param __s The class to lookup, the binary name is used.
	 * @return The class for the given binary name, or {@code null} if it
	 * does not exist.
	 * @since 2018/09/23 
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native Class<?> classByName(String __s);
	
	/**
	 * Returns the class data which is attached to the given class object.
	 *
	 * @param __cl The class to get the data from.
	 * @return The resulting class data.
	 * @since 2018/12/04
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native ClassData classData(Class<?> __cl);
	
	/**
	 * Returns the class object for the given object.
	 *
	 * @param __v The object to get the class of.
	 * @return The class of the given object, or {@code null} if it has no
	 * class.
	 * @since 2018/09/22
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native Class<?> classOf(Object __v);
	
	/**
	 * Checks if the given thread holds the given object in a lock.
	 *
	 * @param __ntid The native thread ID.
	 * @param __o The object to check.
	 * @return If the lock is held.
	 * @since 2018/11/21
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native boolean holdsLock(int __ntid, Object __o);
	
	/**
	 * Returns the identity hashcode of the object.
	 *
	 * @param __o The object to get the hashCode for.
	 * @return The identity hashcode.
	 * @since 2018/10/14
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int identityHashCode(Object __o);
	
	/**
	 * Invokes the specified static method.
	 *
	 * @param __m The method to invoke.
	 * @param __args Arguments to the method, the parameters will be passed
	 * as-is and will not be unboxed, so the method must accept boxed values.
	 * @return The value to return from the method, {@code void} will return
	 * {@code null}.
	 * @since 2018/11/20
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native Object invokeStatic(StaticMethod __m,
		Object... __args);
	
	/**
	 * Notifies threads waiting on the monitor.
	 *
	 * @param __o The object to notify.
	 * @param __all Notify all threads?
	 * @return If the monitor was a success or not.
	 * @since 2018/11/20
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int monitorNotify(Object __o, boolean __all);
	
	/**
	 * Waits for a notification on a monitor.
	 *
	 * @param __o The object to wait on.
	 * @param __ms The milliseconds.
	 * @param __ns The nanoseconds.
	 * @return The wait status.
	 * @since 2018/11/21
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int monitorWait(Object __o, long __ms,
		int __ns);
	
	/**
	 * Creates a new primitive weak reference. Note that it is not valid to
	 * operate on this object as a normal object, it is a special
	 * representation.
	 *
	 * @return The primitive weak reference.
	 * @since 2018/09/23
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native PrimitiveReference newWeakReference();
	
	/**
	 * Gets the given reference.
	 *
	 * @param __r The reference to read from.
	 * @return The reference value, may be {@code null} if the input reference
	 * is not valid, it was garbage collected, or it was never set.
	 * @since 2018/09/23
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native Object referenceGet(PrimitiveReference __r);
	
	/**
	 * Sets the given reference to the given value.
	 *
	 * @param __r The reference to set.
	 * @param __v The value to set.
	 * @since 2018/09/23
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native void referenceSet(PrimitiveReference __r,
		Object __v);
	
	/**
	 * Returns the class object for the specified class by its binary name.
	 *
	 * @param <C> The class to type this as.
	 * @param __s The class to lookup, the binary name is used.
	 * @return The class for the given binary name, or {@code null} if it
	 * does not exist.
	 * @since 2018/09/23 
	 */
	@SuppressWarnings({"unchecked"})
	@Deprecated
	public static final <C> Class<C> classByNameType(String __s)
	{
		return (Class<C>)((Object)ObjectAccess.classByName(__s));
	}
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































































































































































Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/ResourceAccess.java.

17
18
19
20
21
22
23

24
25
26

27
28
29
30

31
32
33
34

35
36
37
38

39
40
41
42

43
44
45
46

47
48
49
50

51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
 * This class provides access to resources and their raw data streams.
 *
 * Access to resources relies on the suites, so the correct suite must be
 * specified. {@link Class#getResourceAsStream(String)} should handle this.
 *
 * @since 2018/10/07
 */

public final class ResourceAccess
{
	/** Resource does not exist. */

	public static final int OPEN_STATUS_NO_RESOURCE =
		-1;
	
	/** JAR does not exist. */

	public static final int OPEN_STATUS_NO_JAR =
		-2;
	
	/** IOException. */

	public static final int OPEN_STATUS_IOEXCEPTION =
		-3;
	
	/** Read returned EOF. */

	public static final int READ_STATUS_EOF =
		-1;
	
	/** Read returned unknown file descriptor. */

	public static final int READ_STATUS_UNKNOWN_FD =
		-2;
	
	/** Read returned IOException. */

	public static final int READ_STATUS_IOEXCEPTION =
		-3;
	
	/** Descriptor was not found. */

	public static final int CLOSE_STATUS_UNKNOWN_FD =
		-2;
	
	/** Close resulted in any IOException. */

	public static final int CLOSE_STATUS_IOEXCEPTION =
		-3;
	
	/**
	 * Returns the number of bytes which are known to be available. This is
	 * not required to be supported but is available for usage if it would
	 * result in optimization.
	 *
	 * If this is not supported by a resource then zero or a negative value
	 * may be returned.
	 *
	 * @param __fd The file descriptor to check.
	 * @return The number of available bytes.
	 * @since 2018/10/07
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int available(int __fd);
	
	/**
	 * Closes the given resource.
	 *
	 * @param __fd The resource descriptor to close.
	 * @return A negative value indicating the reason for the failure.
	 * @since 2018/10/07
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int close(int __fd);
	
	/**
	 * Opens the specified resource in the given JAR.
	 *
	 * @param __jar The JAR the resource is in, this specifies the name of a
	 * suite.
	 * @param __res The name of the resource to load.
	 * @return The file descriptor or a negative value if it does not exist.
	 * If {@code -2} is returned that means there was an exception trying to
	 * load the resource.
	 * @since 2018/10/07
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int open(String __jar, String __res);
	
	/**
	 * Reads data from the given resource.
	 *
	 * @param __fd The file descriptor to read from.
	 * @param __b The output byte array.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return The number of bytes read or a negative value if the end of
	 * stream was reached.
	 * @since 2018/10/07
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int read(int __fd, byte[] __b, int __o,
		int __l);
}








>



>




>




>




>




>




>




>




>















>










>














>














>





17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 * This class provides access to resources and their raw data streams.
 *
 * Access to resources relies on the suites, so the correct suite must be
 * specified. {@link Class#getResourceAsStream(String)} should handle this.
 *
 * @since 2018/10/07
 */
@Deprecated
public final class ResourceAccess
{
	/** Resource does not exist. */
	@Deprecated
	public static final int OPEN_STATUS_NO_RESOURCE =
		-1;
	
	/** JAR does not exist. */
	@Deprecated
	public static final int OPEN_STATUS_NO_JAR =
		-2;
	
	/** IOException. */
	@Deprecated
	public static final int OPEN_STATUS_IOEXCEPTION =
		-3;
	
	/** Read returned EOF. */
	@Deprecated
	public static final int READ_STATUS_EOF =
		-1;
	
	/** Read returned unknown file descriptor. */
	@Deprecated
	public static final int READ_STATUS_UNKNOWN_FD =
		-2;
	
	/** Read returned IOException. */
	@Deprecated
	public static final int READ_STATUS_IOEXCEPTION =
		-3;
	
	/** Descriptor was not found. */
	@Deprecated
	public static final int CLOSE_STATUS_UNKNOWN_FD =
		-2;
	
	/** Close resulted in any IOException. */
	@Deprecated
	public static final int CLOSE_STATUS_IOEXCEPTION =
		-3;
	
	/**
	 * Returns the number of bytes which are known to be available. This is
	 * not required to be supported but is available for usage if it would
	 * result in optimization.
	 *
	 * If this is not supported by a resource then zero or a negative value
	 * may be returned.
	 *
	 * @param __fd The file descriptor to check.
	 * @return The number of available bytes.
	 * @since 2018/10/07
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int available(int __fd);
	
	/**
	 * Closes the given resource.
	 *
	 * @param __fd The resource descriptor to close.
	 * @return A negative value indicating the reason for the failure.
	 * @since 2018/10/07
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int close(int __fd);
	
	/**
	 * Opens the specified resource in the given JAR.
	 *
	 * @param __jar The JAR the resource is in, this specifies the name of a
	 * suite.
	 * @param __res The name of the resource to load.
	 * @return The file descriptor or a negative value if it does not exist.
	 * If {@code -2} is returned that means there was an exception trying to
	 * load the resource.
	 * @since 2018/10/07
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int open(String __jar, String __res);
	
	/**
	 * Reads data from the given resource.
	 *
	 * @param __fd The file descriptor to read from.
	 * @param __b The output byte array.
	 * @param __o The offset.
	 * @param __l The length.
	 * @return The number of bytes read or a negative value if the end of
	 * stream was reached.
	 * @since 2018/10/07
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int read(int __fd, byte[] __b, int __o,
		int __l);
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/StaticMethod.java.

11
12
13
14
15
16
17

18
19
20
21
package cc.squirreljme.runtime.cldc.asm;

/**
 * This interface represents a static method which may be executed accordingly.
 *
 * @since 2018/11/20
 */

public interface StaticMethod
{
}








>




11
12
13
14
15
16
17
18
19
20
21
22
package cc.squirreljme.runtime.cldc.asm;

/**
 * This interface represents a static method which may be executed accordingly.
 *
 * @since 2018/11/20
 */
@Deprecated
public interface StaticMethod
{
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/SuiteAccess.java.

14
15
16
17
18
19
20

21
22
23
24
25
26

27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72

73
74
75
76
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * Access to suites and other suites which are available for usage.
 *
 * @since 2018/10/26
 */

public class SuiteAccess
{
	/**
	 * Compile/install using data which was passed directly to the given
	 * byte array.
	 */

	public static final int WHERE_DIRECT =
		1;
	
	/**
	 * Compile/install using the given JAR suite specified as a string, this
	 * may be the same as a classpath value.
	 */

	public static final int WHERE_SUITE =
		2;
	
	/**
	 * Returns the suites which are available for usage.
	 *
	 * @return The suites which are available for usage.
	 * @since 2018/10/26
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native String[] availableSuites();
	
	/**
	 * Returns the current classpath that is being used.
	 *
	 * @return The current classpath.
	 * @since 2018/12/06
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native String[] currentClassPath();
	
	/**
	 * Specifies that the given JAR should be installed into the suite
	 * manager, it may be compiled first.
	 *
	 * @param __wh Where is this JAR located?
	 * @param __data Data which depends on the where parameter.
	 * @return The install status.
	 * @since 2019/04/17
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV)
	public static final native int installJar(int __wh, byte[] __data);
	
	/**
	 * Returns the last compile error which was set.
	 *
	 * @return The last compile error.
	 * @since 2019/04/17
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV)
	public static final native int lastCompileError();
}








>






>







>









>









>












>









>




14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * Access to suites and other suites which are available for usage.
 *
 * @since 2018/10/26
 */
@Deprecated
public class SuiteAccess
{
	/**
	 * Compile/install using data which was passed directly to the given
	 * byte array.
	 */
	@Deprecated
	public static final int WHERE_DIRECT =
		1;
	
	/**
	 * Compile/install using the given JAR suite specified as a string, this
	 * may be the same as a classpath value.
	 */
	@Deprecated
	public static final int WHERE_SUITE =
		2;
	
	/**
	 * Returns the suites which are available for usage.
	 *
	 * @return The suites which are available for usage.
	 * @since 2018/10/26
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native String[] availableSuites();
	
	/**
	 * Returns the current classpath that is being used.
	 *
	 * @return The current classpath.
	 * @since 2018/12/06
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native String[] currentClassPath();
	
	/**
	 * Specifies that the given JAR should be installed into the suite
	 * manager, it may be compiled first.
	 *
	 * @param __wh Where is this JAR located?
	 * @param __data Data which depends on the where parameter.
	 * @return The install status.
	 * @since 2019/04/17
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV)
	public static final native int installJar(int __wh, byte[] __data);
	
	/**
	 * Returns the last compile error which was set.
	 *
	 * @return The last compile error.
	 * @since 2019/04/17
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV)
	public static final native int lastCompileError();
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/SystemAccess.java.

14
15
16
17
18
19
20

21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * Access to system related details.
 *
 * @since 2018/10/13
 */

public final class SystemAccess
{
	/**
	 * Not used.
	 *
	 * @since 2018/10/13
	 */

	private SystemAccess()
	{
	}
	
	/**
	 * Returns the specified environment variable, it is unspecified and
	 * system dependent if variables are case sensitive or not. Locale may
	 * be considered by the host system additionally. If environment variables
	 * do not exist in the environment then only {@code null} will be
	 * returned.
	 *
	 * @param __e The environment variable to get.
	 * @return The value of that variable or {@code null} if it is not set.
	 * @since 2018/10/14
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native String getEnv(String __e);
}








>







>















>




14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * Access to system related details.
 *
 * @since 2018/10/13
 */
@Deprecated
public final class SystemAccess
{
	/**
	 * Not used.
	 *
	 * @since 2018/10/13
	 */
	@Deprecated
	private SystemAccess()
	{
	}
	
	/**
	 * Returns the specified environment variable, it is unspecified and
	 * system dependent if variables are case sensitive or not. Locale may
	 * be considered by the host system additionally. If environment variables
	 * do not exist in the environment then only {@code null} will be
	 * returned.
	 *
	 * @param __e The environment variable to get.
	 * @return The value of that variable or {@code null} if it is not set.
	 * @since 2018/10/14
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native String getEnv(String __e);
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/SystemProperties.java.

15
16
17
18
19
20
21

22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * Access to system properties.
 *
 * @since 2018/09/20
 */

public final class SystemProperties
{
	/**
	 * Not used.
	 *
	 * @since 2018/09/20
	 */

	private SystemProperties()
	{
	}
	
	/**
	 * Returns the approximated path where the VM's executable exists. This
	 * will be the actual JVM's JAR or EXE file.
	 *
	 * @return The approximated executable path or {@code null} if it is not
	 * known.
	 * @since 2018/12/08
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static native String executablePath();
	
	/**
	 * Returns the depth of the guests within the virtual machine.
	 *
	 * @return The number of guests.
	 * @since 2018/11/04
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int guestDepth();
	
	/**
	 * The class to use for a given implementation of something.
	 *
	 * @param __n The class name to lookup.
	 * @return The class that should get its instance created or {@code null}
	 * if there is no implementation.
	 * @since 2018/12/13
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native String implementationClass(String __n);
	
	/**
	 * Returns the e-mail to contact for the virtual machine.
	 *
	 * @return The contact e-mail for the virtual machine.
	 * @since 2017/10/02
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static native String javaVMEmail();
	
	/**
	 * Returns the name of the Java virtual machine.
	 *
	 * @return The name of the virtual machine.
	 * @since 2017/10/02
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static native String javaVMName();
	
	/**
	 * Returns the URL to the virtual machine's vendor's URL.
	 *
	 * @return The URL of the JVM's virtual machine.
	 * @since 2017/10/02
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static native String javaVMURL();
	
	/**
	 * Returns the vendor of the Java virtual machine.
	 *
	 * @return The vendor of the Java virtual machine.
	 * @since 2017/10/02
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static native String javaVMVendor();
	
	/**
	 * Returns the full version of the Java virtual machine.
	 *
	 * @return The full Java virtual machine version.
	 * @since 2017/08/13
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static native String javaVMVersion();
	
	/**
	 * Returns the type of operating SquirrelJME is running on.
	 *
	 * @return The type of operating system SquirrelJME is running on.
	 * @since 2018/10/14
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int operatingSystemType();
	
	/**
	 * Returns a system property for the given value.
	 *
	 * @param __k The key to get.
	 * @return The value of the property, will be {@code null} if it is not
	 * valid.
	 * @since 2018/09/20
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static native String systemProperty(String __k);
	
	/**
	 * Returns the version of the class libraries.
	 *
	 * @return The class library version.
	 * @since 2017/10/02
	 */
	public static String javaRuntimeVersion()
	{
		return SquirrelJME.RUNTIME_VERSION;
	}
}








>







>





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







<
<
|
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







<
<
|
<
<
<
<
<
<
<
<

|
<
<
<
<
<
<
<
<
<
<
<


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35




















36
37
38
39
40
41
42


43






44









45



























46
47
48
49
50
51
52


53








54
55











56
57
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * Access to system properties.
 *
 * @since 2018/09/20
 */
@Deprecated
public final class SystemProperties
{
	/**
	 * Not used.
	 *
	 * @since 2018/09/20
	 */
	@Deprecated
	private SystemProperties()
	{
	}
	
	/**




















	 * The class to use for a given implementation of something.
	 *
	 * @param __n The class name to lookup.
	 * @return The class that should get its instance created or {@code null}
	 * if there is no implementation.
	 * @since 2018/12/13
	 */


	@Deprecated






	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)









	public static native String implementationClass(String __n);



























	
	/**
	 * Returns the type of operating SquirrelJME is running on.
	 *
	 * @return The type of operating system SquirrelJME is running on.
	 * @since 2018/10/14
	 */


	@Deprecated








	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static native int operatingSystemType();











}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/TaskAccess.java.

14
15
16
17
18
19
20

21
22
23

24
25
26
27

28
29
30
31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126
127
128
129
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * This class provides access to tasks which are running.
 *
 * @since 2018/11/04
 */

public final class TaskAccess
{
	/** The entry point is not valid. */

	public static final int ERROR_INVALID_ENTRY =
		-2;
	
	/** Library in the classpath is missing. */

	public static final int ERROR_MISSING_LIBRARY =
		-3;
	
	/** Exit code indicating bad task things. */

	public static final int EXIT_CODE_FATAL_EXCEPTION =
		127;
	
	/**
	 * Not used.
	 *
	 * @since 2018/11/04
	 */
	private TaskAccess()
	{
	}
	
	/**
	 * Returns the ID of the current thread.
	 *
	 * @return The current thread ID.
	 * @since 2018/11/20
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int currentThread();
	
	/**
	 * Sets the priority of the thread.
	 *
	 * @param __tid The thread ID.
	 * @param __p The priority.
	 * @since 2018/12/07
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native void setThreadPriority(int __tid, int __p);
	
	/**
	 * Signals a hardware interrupt on the given thread.
	 *
	 * @param __tid The thread to signal.
	 * @since 2018/11/21
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native void signalInterrupt(int __tid);
	
	/**
	 * Starts the specified task.
	 *
	 * @param __cp The classpath used.
	 * @param __main The main entry point.
	 * @param __args Arguments to start the task with.
	 * @return The task identifier or a negative number if the task could
	 * not start.
	 * @since 2018/11/04
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int startTask(String[] __cp, String __main,
		String[] __args);
	
	/**
	 * Starts the specified task.
	 *
	 * @param __cp The classpath used.
	 * @param __main The main entry point.
	 * @param __args Arguments to start the task with.
	 * @param __sprops System properties in key/value pairs to pass to the
	 * target environment.
	 * @param __stdout Callback to receive standard output data, may be
	 * {@code null} to ignore.
	 * @param __stderr Callback to receive standard error data, may be
	 * {@code null} to ignore.
	 * @return The task identifier or a negative number if the task could
	 * not start.
	 * @since 2019/02/02
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV)
	public static final native int startTask(String[] __cp, String __main,
		String[] __args, String[] __sprops, ConsoleCallback __stdout,
		ConsoleCallback __stderr);
	
	/**
	 * Starts the given thread.
	 *
	 * @param __t The thread which is to run, the execution point of the
	 * thread is the {@code Thread.__start()} method.
	 * @param __n The name hint of this thread.
	 * @return The thread ID.
	 * @since 2018/11/17
	 */
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int startThread(Thread __t, String __n);
	
	/**
	 * Returns the status of the target task.
	 *
	 * @param __tid The task to get the status of.
	 * @return The status for the given task.
	 * @since 2018/11/04
	 */

	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int taskStatus(int __tid);
}








>



>




>




>












<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










>




















>





<
<
<
<
<
<
<
<
<
<
<
<







>




14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47




























48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84












85
86
87
88
89
90
91
92
93
94
95
96
import cc.squirreljme.runtime.cldc.lang.ApiLevel;

/**
 * This class provides access to tasks which are running.
 *
 * @since 2018/11/04
 */
@Deprecated
public final class TaskAccess
{
	/** The entry point is not valid. */
	@Deprecated
	public static final int ERROR_INVALID_ENTRY =
		-2;
	
	/** Library in the classpath is missing. */
	@Deprecated
	public static final int ERROR_MISSING_LIBRARY =
		-3;
	
	/** Exit code indicating bad task things. */
	@Deprecated
	public static final int EXIT_CODE_FATAL_EXCEPTION =
		127;
	
	/**
	 * Not used.
	 *
	 * @since 2018/11/04
	 */
	private TaskAccess()
	{
	}
	




























	/**
	 * Starts the specified task.
	 *
	 * @param __cp The classpath used.
	 * @param __main The main entry point.
	 * @param __args Arguments to start the task with.
	 * @return The task identifier or a negative number if the task could
	 * not start.
	 * @since 2018/11/04
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int startTask(String[] __cp, String __main,
		String[] __args);
	
	/**
	 * Starts the specified task.
	 *
	 * @param __cp The classpath used.
	 * @param __main The main entry point.
	 * @param __args Arguments to start the task with.
	 * @param __sprops System properties in key/value pairs to pass to the
	 * target environment.
	 * @param __stdout Callback to receive standard output data, may be
	 * {@code null} to ignore.
	 * @param __stderr Callback to receive standard error data, may be
	 * {@code null} to ignore.
	 * @return The task identifier or a negative number if the task could
	 * not start.
	 * @since 2019/02/02
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV)
	public static final native int startTask(String[] __cp, String __main,
		String[] __args, String[] __sprops, ConsoleCallback __stdout,
		ConsoleCallback __stderr);
	












	/**
	 * Returns the status of the target task.
	 *
	 * @param __tid The task to get the status of.
	 * @return The status for the given task.
	 * @since 2018/11/04
	 */
	@Deprecated
	@Api(ApiLevel.LEVEL_SQUIRRELJME_0_2_0_20181225)
	public static final native int taskStatus(int __tid);
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/asm/package-info.java.

11
12
13
14
15
16
17

18
19
/**
 * This package contains static methods which in which invocations of methods
 * in the package are replaced by the compiler using native means.
 *
 * @since 2017/12/27
 */


package cc.squirreljme.runtime.cldc.asm;








>


11
12
13
14
15
16
17
18
19
20
/**
 * This package contains static methods which in which invocations of methods
 * in the package are replaced by the compiler using native means.
 *
 * @since 2017/12/27
 */

@Deprecated
package cc.squirreljme.runtime.cldc.asm;

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/debug/CallTraceElement.java.

10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

package cc.squirreljme.runtime.cldc.debug;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.CallStackItem;
import cc.squirreljme.jvm.SystemCallError;
import cc.squirreljme.jvm.SystemCallIndex;

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Objects;

/**
 * This represents a single entry within the call stack. This is used for
 * debugging purposes to determine where code has thrown an exception.
 *
 * @since 2018/02/21
 */
public final class CallTraceElement
{
	/** The class name. */
	protected final String classname;
	
	/** The method name. */
	protected final String methodname;
	
	/** The method descriptor. */
	protected final String methoddescriptor;
	
	/** The execution pointer of the address. */
	protected final long address;
	
	/** The source code file. */
	protected final String file;
	
	/** The line in the file. */
	protected final int line;
	
	/** The Java byte code instruction. */
	protected final int jbcinst;
	
	/** The Java byte code address. */
	protected final int jbcaddr;
	
	/** The task ID. */
	protected final int taskid;
	
	/** String representation. */
	private Reference<String> _string;
	
	/** At line form. */
	private Reference<String> _stringatl;
	







>













|


|


|











|


|


|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

package cc.squirreljme.runtime.cldc.debug;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.CallStackItem;
import cc.squirreljme.jvm.SystemCallError;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.jvm.mle.brackets.TracePointBracket;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Objects;

/**
 * This represents a single entry within the call stack. This is used for
 * debugging purposes to determine where code has thrown an exception.
 *
 * @since 2018/02/21
 */
public final class CallTraceElement
{
	/** The class name. */
	protected final String className;
	
	/** The method name. */
	protected final String methodName;
	
	/** The method descriptor. */
	protected final String methodType;
	
	/** The execution pointer of the address. */
	protected final long address;
	
	/** The source code file. */
	protected final String file;
	
	/** The line in the file. */
	protected final int line;
	
	/** The Java byte code instruction. */
	protected final int byteCodeOp;
	
	/** The Java byte code address. */
	protected final int byteCodeAddr;
	
	/** The task ID. */
	protected final int taskId;
	
	/** String representation. */
	private Reference<String> _string;
	
	/** At line form. */
	private Reference<String> _stringatl;
	
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
	 * @since 2018/02/21
	 */
	public CallTraceElement()
	{
		this(null, null, null, -1);
	}
	
	/**
	 * Initializes a call trace element.
	 *
	 * @param __cl The class name.
	 * @param __mn The method name.
	 * @since 2018/02/21
	 */
	public CallTraceElement(String __cl, String __mn)
	{
		this(__cl, __mn, null, -1);
	}
	
	/**
	 * Initializes a call trace element.
	 *
	 * @param __cl The class name.
	 * @param __mn The method name.
	 * @param __md The method descriptor.
	 * @since 2018/02/21
	 */
	public CallTraceElement(String __cl, String __mn, String __md)
	{
		this(__cl, __mn, __md, -1);
	}
	
	/**
	 * Initializes a call trace element.
	 *
	 * @param __cl The class name.
	 * @param __mn The method name.
	 * @param __md The method descriptor.
	 * @param __addr The address the method executes at.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







72
73
74
75
76
77
78

























79
80
81
82
83
84
85
	 * @since 2018/02/21
	 */
	public CallTraceElement()
	{
		this(null, null, null, -1);
	}
	

























	/**
	 * Initializes a call trace element.
	 *
	 * @param __cl The class name.
	 * @param __mn The method name.
	 * @param __md The method descriptor.
	 * @param __addr The address the method executes at.
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
	 * @param __jpc The Java PC address.
	 * @param __tid The task ID.
	 * @since 2019/10/05
	 */
	public CallTraceElement(String __cl, String __mn, String __md, long __addr,
		String __file, int __line, int __jbc, int __jpc, int __tid)
	{
		this.classname = __cl;
		this.methodname = __mn;
		this.methoddescriptor = __md;
		this.address = __addr;
		this.file = __file;
		this.line = __line;
		this.jbcinst = __jbc;
		this.jbcaddr = __jpc;
		this.taskid = __tid;
	}
	
	/**
	 * Returns the address of the element.
	 *
	 * @return The element address.
	 * @since 2018/03/15







|
|
|



|
|
|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
	 * @param __jpc The Java PC address.
	 * @param __tid The task ID.
	 * @since 2019/10/05
	 */
	public CallTraceElement(String __cl, String __mn, String __md, long __addr,
		String __file, int __line, int __jbc, int __jpc, int __tid)
	{
		this.className = __cl;
		this.methodName = __mn;
		this.methodType = __md;
		this.address = __addr;
		this.file = __file;
		this.line = __line;
		this.byteCodeOp = __jbc;
		this.byteCodeAddr = __jpc;
		this.taskId = __tid;
	}
	
	/**
	 * Returns the address of the element.
	 *
	 * @return The element address.
	 * @since 2018/03/15
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
	 * Returns the address of the instruction at the Java byte code position.
	 *
	 * @return The address of the instruction in Java byte code.
	 * @since 2019/04/26
	 */
	public final int byteCodeAddress()
	{
		return this.jbcaddr;
	}
	
	/**
	 * Returns the byte code instruction that was used for this.
	 *
	 * @return The used byte code instruction or {@code 0xFF} if it is not
	 * valid or specified.
	 * @since 2019/04/26
	 */
	public final int byteCodeInstruction()
	{
		return this.jbcinst & 0xFF;
	}
	
	/**
	 * Returns the name of the associated class.
	 *
	 * @return The associated class.
	 * @since 2018/03/15
	 */
	public final String className()
	{
		return this.classname;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/02/21
	 */
	@Override
	public final boolean equals(Object __o)
	{
		if (__o == this)
			return true;
		
		if (this.hashCode() != __o.hashCode())
			return false;
		
		if (!(__o instanceof CallTraceElement))
			return false;
		
		CallTraceElement o = (CallTraceElement)__o;
		return Objects.equals(this.classname, o.classname) &&
			Objects.equals(this.methodname, o.methodname) &&
			Objects.equals(this.methoddescriptor, o.methoddescriptor) &&
			Objects.equals(this.file, o.file) &&
			this.address == o.address &&
			this.line == o.line &&
			this.jbcinst == o.jbcinst &&
			this.jbcaddr == o.jbcaddr &&
			this.taskid == o.taskid;
	}
	
	/**
	 * Returns the source file.
	 *
	 * @return The source file.
	 * @since 2018/04/02







|











|










|



















|
|
|



|
|
|







169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	 * Returns the address of the instruction at the Java byte code position.
	 *
	 * @return The address of the instruction in Java byte code.
	 * @since 2019/04/26
	 */
	public final int byteCodeAddress()
	{
		return this.byteCodeAddr;
	}
	
	/**
	 * Returns the byte code instruction that was used for this.
	 *
	 * @return The used byte code instruction or {@code 0xFF} if it is not
	 * valid or specified.
	 * @since 2019/04/26
	 */
	public final int byteCodeInstruction()
	{
		return this.byteCodeOp & 0xFF;
	}
	
	/**
	 * Returns the name of the associated class.
	 *
	 * @return The associated class.
	 * @since 2018/03/15
	 */
	public final String className()
	{
		return this.className;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/02/21
	 */
	@Override
	public final boolean equals(Object __o)
	{
		if (__o == this)
			return true;
		
		if (this.hashCode() != __o.hashCode())
			return false;
		
		if (!(__o instanceof CallTraceElement))
			return false;
		
		CallTraceElement o = (CallTraceElement)__o;
		return Objects.equals(this.className, o.className) &&
			Objects.equals(this.methodName, o.methodName) &&
			Objects.equals(this.methodType, o.methodType) &&
			Objects.equals(this.file, o.file) &&
			this.address == o.address &&
			this.line == o.line &&
			this.byteCodeOp == o.byteCodeOp &&
			this.byteCodeAddr == o.byteCodeAddr &&
			this.taskId == o.taskId;
	}
	
	/**
	 * Returns the source file.
	 *
	 * @return The source file.
	 * @since 2018/04/02
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
	@Override
	public final int hashCode()
	{
		int rv = this._hash;
		if (rv == 0)
		{
			long address = this.address;
			this._hash = (rv = Objects.hashCode(this.classname) ^
				Objects.hashCode(this.methodname) ^
				Objects.hashCode(this.methoddescriptor) ^
				Objects.hashCode(this.file) ^
				(int)((address >>> 32) | address) ^
				~this.line +
				~this.jbcinst +
				~this.jbcaddr +
				~this.taskid);
		}
		return rv;
	}
	
	/**
	 * Returns the source file line.
	 *







|
|
|



|
|
|







245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
	@Override
	public final int hashCode()
	{
		int rv = this._hash;
		if (rv == 0)
		{
			long address = this.address;
			this._hash = (rv = Objects.hashCode(this.className) ^
				Objects.hashCode(this.methodName) ^
				Objects.hashCode(this.methodType) ^
				Objects.hashCode(this.file) ^
				(int)((address >>> 32) | address) ^
				~this.line +
				~this.byteCodeOp +
				~this.byteCodeAddr +
				~this.taskId);
		}
		return rv;
	}
	
	/**
	 * Returns the source file line.
	 *
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
	 * Returns the descriptor of the method.
	 *
	 * @return The method descriptor.
	 * @since 2018/03/15
	 */
	public final String methodDescriptor()
	{
		return this.methoddescriptor;
	}
	
	/**
	 * Returns the name of the method.
	 *
	 * @return The method name.
	 * @since 2018/03/15
	 */
	public final String methodName()
	{
		return this.methodname;
	}
	
	/**
	 * Formats the call trace element but having it only represent the method
	 * point without the class information.
	 *
	 * @return The at line string.
	 * @since 2019/05/11
	 */
	public final String toAtLineString()
	{
		Reference<String> ref = this._stringatl;
		String rv;
		
		if (ref == null || null == (rv = ref.get()))
		{
			// Get all fields to determine how to print it pretty
			String methodname = this.methodname,
				methoddescriptor = this.methoddescriptor;
			long address = this.address;
			int line = this.line;
			int jbcinst = this.jbcinst & 0xFF;
			int jbcaddr = this.jbcaddr;
			int taskid = this.taskid;
			
			// Format it nicely
			StringBuilder sb = new StringBuilder();
			
			// Method name
			sb.append('.');
			sb.append((methodname == null ? "<unknown>" : methodname));







|










|

















|
|


|
|
|







277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
	 * Returns the descriptor of the method.
	 *
	 * @return The method descriptor.
	 * @since 2018/03/15
	 */
	public final String methodDescriptor()
	{
		return this.methodType;
	}
	
	/**
	 * Returns the name of the method.
	 *
	 * @return The method name.
	 * @since 2018/03/15
	 */
	public final String methodName()
	{
		return this.methodName;
	}
	
	/**
	 * Formats the call trace element but having it only represent the method
	 * point without the class information.
	 *
	 * @return The at line string.
	 * @since 2019/05/11
	 */
	public final String toAtLineString()
	{
		Reference<String> ref = this._stringatl;
		String rv;
		
		if (ref == null || null == (rv = ref.get()))
		{
			// Get all fields to determine how to print it pretty
			String methodname = this.methodName,
				methoddescriptor = this.methodType;
			long address = this.address;
			int line = this.line;
			int jInst = this.byteCodeOp & 0xFF;
			int jAddr = this.byteCodeAddr;
			int taskid = this.taskId;
			
			// Format it nicely
			StringBuilder sb = new StringBuilder();
			
			// Method name
			sb.append('.');
			sb.append((methodname == null ? "<unknown>" : methodname));
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
				
				// Otherwise use an index
				else
					sb.append(address);
			}
			
			// File, Line, and/or Java instruction/address
			boolean hasline = (line >= 0),
				hasjbcinst = (jbcinst > 0xFF && jbcinst < 0xFF),
				hasjbcaddr = (jbcaddr >= 0);
			if (hasline || hasjbcinst || hasjbcaddr)
			{
				sb.append(" (");
				
				// Line
				boolean sp = false;
				if ((sp |= hasline))
				{
					sb.append(':');
					sb.append(line);
				}
				
				// Java instruction info
				if (hasjbcinst || hasjbcaddr)
				{
					// Using space?
					if (sp)
						sb.append(' ');
					
					// Used to indicate Java specific stuff
					sb.append('J');
					
					// Write instruction
					if (hasjbcinst)
						sb.append(jbcinst);
					
					// Write address of Java operation
					if (hasjbcaddr)
					{
						sb.append('@');
						sb.append(jbcaddr);
					}
				}
				
				sb.append(')');
			}
			
			this._stringatl = new WeakReference<>((rv = sb.toString()));







|
|
|
|





|






|





<
<
<

|
|


|


|







355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
				
				// Otherwise use an index
				else
					sb.append(address);
			}
			
			// File, Line, and/or Java instruction/address
			boolean hasLine = (line >= 0),
				hasJInst = (jInst >= 0 && jInst < 0xFF),
				hasJAddr = (jAddr >= 0);
			if (hasLine || hasJInst || hasJAddr)
			{
				sb.append(" (");
				
				// Line
				boolean sp = false;
				if ((sp |= hasLine))
				{
					sb.append(':');
					sb.append(line);
				}
				
				// Java instruction info
				if (hasJInst || hasJAddr)
				{
					// Using space?
					if (sp)
						sb.append(' ');
					



					// Write instruction
					if (hasJInst)
						sb.append(JavaOpCodeUtils.toString(jInst));
					
					// Write address of Java operation
					if (hasJAddr)
					{
						sb.append('@');
						sb.append(jAddr);
					}
				}
				
				sb.append(')');
			}
			
			this._stringatl = new WeakReference<>((rv = sb.toString()));
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
	{
		Reference<String> ref = this._stringclh;
		String rv;
		
		if (ref == null || null == (rv = ref.get()))
		{
			// Get all fields to determine how to print it pretty
			String classname = this.classname,
				file = this.file;
			
			// Format it nicely
			StringBuilder sb = new StringBuilder();
			
			// Class name
			sb.append((classname == null ? "<unknown>" : classname));

			
			// Is this in a file?
			boolean hasfile = (file != null);
			if (hasfile)
			{
				sb.append(" (");
				
				// File
				boolean sp = false;
				if ((sp |= hasfile))
					sb.append(file);
				
				sb.append(')');
			}
			
			this._stringclh = new WeakReference<>((rv = sb.toString()));
		}
		
		return rv;







|






|
>


|
<


<
<
<
<
|
<







412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430

431
432




433

434
435
436
437
438
439
440
	{
		Reference<String> ref = this._stringclh;
		String rv;
		
		if (ref == null || null == (rv = ref.get()))
		{
			// Get all fields to determine how to print it pretty
			String classname = this.className,
				file = this.file;
			
			// Format it nicely
			StringBuilder sb = new StringBuilder();
			
			// Class name
			sb.append((classname == null ? "<unknown>" :
				classname.replace('/', '.')));
			
			// Is this in a file?
			if (file != null)

			{
				sb.append(" (");




				sb.append(file);

				sb.append(')');
			}
			
			this._stringclh = new WeakReference<>((rv = sb.toString()));
		}
		
		return rv;
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
	{
		Reference<String> ref = this._string;
		String rv;
		
		if (ref == null || null == (rv = ref.get()))
		{
			// Get all fields to determine how to print it pretty
			String classname = this.classname,
				methodname = this.methodname,
				methoddescriptor = this.methoddescriptor,
				file = this.file;
			long address = this.address;
			int line = this.line;
			int jbcinst = this.jbcinst & 0xFF;
			int jbcaddr = this.jbcaddr;
			int taskid = this.taskid;
			
			// Format it nicely
			StringBuilder sb = new StringBuilder();
			
			sb.append((classname == null ? "<unknown>" : classname));
			sb.append('.');
			sb.append((methodname == null ? "<unknown>" : methodname));







|
|
|



|
|
|







449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
	{
		Reference<String> ref = this._string;
		String rv;
		
		if (ref == null || null == (rv = ref.get()))
		{
			// Get all fields to determine how to print it pretty
			String classname = this.className,
				methodname = this.methodName,
				methoddescriptor = this.methodType,
				file = this.file;
			long address = this.address;
			int line = this.line;
			int jbcinst = this.byteCodeOp & 0xFF;
			int jbcaddr = this.byteCodeAddr;
			int taskid = this.taskId;
			
			// Format it nicely
			StringBuilder sb = new StringBuilder();
			
			sb.append((classname == null ? "<unknown>" : classname));
			sb.append('.');
			sb.append((methodname == null ? "<unknown>" : methodname));
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
				// Java instruction info
				if (hasjbcinst || hasjbcaddr)
				{
					// Using space?
					if (sp)
						sb.append(' ');
					
					// Used to indicate Java specific stuff
					sb.append('J');
					
					// Write instruction
					if (hasjbcinst)
						sb.append(jbcinst);
					
					// Write address of Java operation
					if (hasjbcaddr)
					{
						sb.append('@');
						sb.append(jbcaddr);
					}







<
<
<


|







525
526
527
528
529
530
531



532
533
534
535
536
537
538
539
540
541
				// Java instruction info
				if (hasjbcinst || hasjbcaddr)
				{
					// Using space?
					if (sp)
						sb.append(' ');
					



					// Write instruction
					if (hasjbcinst)
						sb.append(JavaOpCodeUtils.toString(jbcinst));
					
					// Write address of Java operation
					if (hasjbcaddr)
					{
						sb.append('@');
						sb.append(jbcaddr);
					}
587
588
589
590
591
592
593

594
595
596
597
598
599
600
	
	/**
	 * Obtains the current raw call trace which has not been resolved.
	 *
	 * @return The raw call trace.
	 * @since 2019/06/16
	 */

	public static final int[] traceRaw()
	{
		// Get the call height, ignore if not supported!
		int callheight = Assembly.sysCallPV(SystemCallIndex.CALL_STACK_HEIGHT);
		if (callheight <= 0 || Assembly.sysCallPV(SystemCallIndex.ERROR_GET,
			SystemCallIndex.CALL_STACK_HEIGHT) != SystemCallError.NO_ERROR)
			return new int[0];







>







552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
	
	/**
	 * Obtains the current raw call trace which has not been resolved.
	 *
	 * @return The raw call trace.
	 * @since 2019/06/16
	 */
	@Deprecated
	public static final int[] traceRaw()
	{
		// Get the call height, ignore if not supported!
		int callheight = Assembly.sysCallPV(SystemCallIndex.CALL_STACK_HEIGHT);
		if (callheight <= 0 || Assembly.sysCallPV(SystemCallIndex.ERROR_GET,
			SystemCallIndex.CALL_STACK_HEIGHT) != SystemCallError.NO_ERROR)
			return new int[0];
630
631
632
633
634
635
636

637
638
639
640
641
642
643
	 * Resolves the specified call trace into call trace elements.
	 *
	 * @param __trace The trace to resolve.
	 * @return The resolved trace.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/06/16
	 */

	public static final CallTraceElement[] traceResolve(int[] __trace)
		throws NullPointerException
	{
		if (__trace == null)
			throw new NullPointerException("NARG");
		
		// Get the call height







>







596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
	 * Resolves the specified call trace into call trace elements.
	 *
	 * @param __trace The trace to resolve.
	 * @return The resolved trace.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/06/16
	 */
	@Deprecated
	public static final CallTraceElement[] traceResolve(int[] __trace)
		throws NullPointerException
	{
		if (__trace == null)
			throw new NullPointerException("NARG");
		
		// Get the call height

Added modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/debug/CallTraceUtils.java.









































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.debug;

import cc.squirreljme.jvm.mle.DebugShelf;
import cc.squirreljme.jvm.mle.brackets.TracePointBracket;
import cc.squirreljme.runtime.cldc.lang.LineEndingUtils;
import java.io.IOException;

/**
 * Utilities to use for printing call traces and other related methods.
 *
 * SquirrelJME uses compactified traces which are smaller and easier to read
 * accordingly.
 *
 * @since 2020/06/11
 */
public final class CallTraceUtils
{
	/**
	 * Not used.
	 *
	 * @since 2020/06/11
	 */
	private CallTraceUtils()
	{
	}
	
	/**
	 * Prints the given stack trace.
	 *
	 * @param __out The stream to write to.
	 * @param __toss The throwable to print.
	 * @param __indentLevel The indentation level to use.
	 * @return If trace printing failed with an {@link IOException}.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static boolean printStackTrace(Appendable __out, Throwable __toss,
		int __indentLevel)
		throws NullPointerException
	{
		if (__out == null)
			throw new NullPointerException("NARG");
		
		return CallTraceUtils.printStackTrace(__out, __toss.toString(),
			DebugShelf.getThrowableTrace(__toss), __toss.getCause(),
			__toss.getSuppressed(), __indentLevel);
	}
	
	/**
	 * Prints the given stack trace to the output, resolving all of the entries
	 * before printing.
	 *
	 * @param __out The stream to write to.
	 * @param __message Exception message.
	 * @param __trace The trace to be printed.
	 * @param __cause The cause of this exception.
	 * @param __suppressed Suppressed exceptions.
	 * @param __indentLevel The indentation level to use.
	 * @return If trace printing failed with an {@link IOException}.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static boolean printStackTrace(Appendable __out, String __message,
		TracePointBracket[] __trace, Throwable __cause,
		Throwable[] __suppressed, int __indentLevel)
		throws NullPointerException
	{
		if (__out == null)
			throw new NullPointerException("NARG");
		
		return CallTraceUtils.printStackTrace(__out, __message,
			CallTraceUtils.resolveAll(__trace), __cause, __suppressed,
			__indentLevel);
	}
	
	/**
	 * Prints the given stack trace to the output.
	 *
	 * @param __out The stream to write to.
	 * @param __message The exception message.
	 * @param __trace The trace to be printed.
	 * @param __cause The cause of this exception.
	 * @param __suppressed The suppressed exceptions.
	 * @param __indentLevel The indentation level to use.
	 * @return If trace printing failed with an {@link IOException}.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static boolean printStackTrace(Appendable __out, String __message,
		CallTraceElement[] __trace, Throwable __cause,
		Throwable[] __suppressed, int __indentLevel)
		throws NullPointerException
	{
		if (__out == null)
			throw new NullPointerException("NARG");
		
		// We do not want any IOExceptions to cause stack trace printing to
		// fail, since this could potentially lead to a very nasty infinite
		// exception loop
		try
		{
			// If there is no actual trace then just print that this is the
			// case and stop printing right away
			if (__trace == null)
			{
				__out.append("<No stack trace>");
				return false;
			}
			
			// Print the initial message of the exception
			CallTraceUtils.__appendIndent(__out, __indentLevel);
			__out.append("EXCEPTION ");
			
			// And that message could be blank!
			if (__message != null)
				__out.append(__message);
			LineEndingUtils.append(__out);
			
			// Set sub-indentation level
			int subLevel = __indentLevel + 1;
			
			// Print each element in the trace, the start of the trace is
			// always the top-most entry
			String lastClass = "<Unknown>";
			for (CallTraceElement current : __trace)
			{
				// Get the current class to detect if it has changed
				String nowClass = current.className();
				if (nowClass == null)
					nowClass = "<Unknown>";
				
				// If the class changed, specify the class which the trace
				// point resides in now
				if (!nowClass.equals(lastClass))
				{
					CallTraceUtils.__appendIndent(__out, subLevel);
					
					__out.append(" IN ");
					__out.append(current.toClassHeaderString());
					
					LineEndingUtils.append(__out);
					
					// If we stay in the same class, then we will not print
					// this header again
					lastClass = nowClass;
				}
				
				CallTraceUtils.__appendIndent(__out, subLevel);
				
				__out.append("- ");
				__out.append(current.toAtLineString());
				
				LineEndingUtils.append(__out);
			}
			
			// Print the exception cause, if any
			if (__cause != null)
			{
				// Starting sequence
				CallTraceUtils.__appendIndent(__out, subLevel);
				__out.append("CAUSED BY:");
				LineEndingUtils.append(__out);
				
				// Recursively enter the printing for this
				CallTraceUtils.printStackTrace(__out, __cause,
					subLevel + 1);
			}
			
			// Then print any suppressed exceptions
			if (__suppressed != null)
				for (Throwable __throwable : __suppressed)
				{
					// Starting sequence
					CallTraceUtils.__appendIndent(__out, subLevel);
					__out.append("SUPPRESSED:");
					LineEndingUtils.append(__out);
					
					// Recursively enter the printing for this
					CallTraceUtils.printStackTrace(__out, __throwable,
						subLevel + 1);
				}
		}
		
		// Ignore these completely, should hopefully not happen if the
		// Appendable we are writing to is a PrintStream or StringBuilder.
		catch (IOException ignored)
		{
			return true;
		}
		
		// All other cases means no exception was thrown
		return false;
	}
	
	/**
	 * Resolves a single trace element.
	 *
	 * @param __point The single trace point to resolve.
	 * @return The resolved trace point.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static CallTraceElement resolve(TracePointBracket __point)
		throws NullPointerException
	{
		if (__point == null)
			throw new NullPointerException("NARG");
		
		return new CallTraceElement(
			DebugShelf.pointClass(__point),
			DebugShelf.pointMethodName(__point),
			DebugShelf.pointMethodType(__point),
			DebugShelf.pointAddress(__point),
			DebugShelf.pointFile(__point),
			DebugShelf.pointLine(__point),
			DebugShelf.pointJavaOperation(__point),
			DebugShelf.pointJavaAddress(__point));
	}
	
	/**
	 * Resolves all entries in the stack trace.
	 *
	 * @param __trace The trace to resolve.
	 * @return The entire resolved trace.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static CallTraceElement[] resolveAll(TracePointBracket[] __trace)
		throws NullPointerException
	{
		if (__trace == null)
			throw new NullPointerException("NARG");
		
		int n = __trace.length;
		CallTraceElement[] rv = new CallTraceElement[n];
		
		// Resolve each one individually
		for (int i = 0; i < n; i++)
			rv[i] = CallTraceUtils.resolve(__trace[i]);
		
		return rv;
	}
	
	/**
	 * Appends an indentation sequence to the output.
	 *
	 * @param __out The output source.
	 * @param __indentLevel The indentation level to use.
	 * @throws IOException If outputting caused an exception.
	 * @since 2020/06/11
	 */
	private static void __appendIndent(Appendable __out, int __indentLevel)
		throws IOException
	{
		// Doing nothing
		if (__indentLevel == 0)
			return;
		
		// Base space indent that is always there
		__out.append(' ');
		__out.append(' ');
		
		// Print bars for indentation level
		for (int i = 0; i < __indentLevel; i++)
			__out.append('|');
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/debug/Debugging.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


16
17
18
19
20





21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40




41
42
43
44
45
46
47
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.debug;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.jvm.config.ConfigRomKey;
import cc.squirreljme.jvm.config.LineEndingType;


import todo.OOPS;
import todo.TODO;

/**
 * This contains static method forwarders.





 *
 * @since 2020/03/21
 */
public final class Debugging
{
	/** Only bytes up to this value are permitted in the output. */
	public static final int _BYTE_LIMIT =
		0x7E;
	
	/** The descriptor used for standard error. */
	private static int _pipe =
		Integer.MIN_VALUE;
	
	/** Line ending type. */
	private static int _line =
		Integer.MIN_VALUE;
	
	/** Used to prevent loops. */
	@SuppressWarnings("StaticVariableMayNotBeInitialized")
	private static volatile boolean _noLoop;




	
	/**
	 * Not used.
	 *
	 * @since 2020/03/21
	 */
	private Debugging()











|
|
|
|
>
>
|
|


|
>
>
>
>
>






|


|
|
<
|
<
<
<




>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.debug;

import cc.squirreljme.jvm.mle.DebugShelf;
import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.TerminalShelf;
import cc.squirreljme.jvm.mle.constants.StandardPipeType;
import cc.squirreljme.runtime.cldc.io.ConsoleOutputStream;
import cc.squirreljme.runtime.cldc.lang.LineEndingUtils;
import java.io.PrintStream;
import todo.OOPS;

/**
 * This class contains all of the static methods which are for writing debug
 * output and failing accordingly on incomplete code. All the methods here for
 * the most part do not touch the standard {@link System#err} and
 * {@link System#out} (which use {@link PrintStream}), as in the event those
 * have a bug or otherwise issues can occur. The methods here should be
 * reliable enough on their own to convey a message accordingly.
 *
 * @since 2020/03/21
 */
public final class Debugging
{
	/** Only bytes up to this value are permitted in the output. */
	private static final int _BYTE_LIMIT =
		0x7E;
	
	/** Exit status for TODOs. */
	private static final int _TODO_EXIT_STATUS =

		63;



	
	/** Used to prevent loops. */
	@SuppressWarnings("StaticVariableMayNotBeInitialized")
	private static volatile boolean _noLoop;
	
	/** This will be set when TODOs are tripped, to prevent infinite loops. */
	@SuppressWarnings("StaticVariableMayNotBeInitialized")
	private static volatile boolean _tripped;
	
	/**
	 * Not used.
	 *
	 * @since 2020/03/21
	 */
	private Debugging()
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

104
105



106


























































107
108
109
110
111
112
113
	 * Emits a To-Do error.
	 *
	 * @return The generated error.
	 * @since 2020/03/21
	 */
	public static Error todo()
	{
		return new TODO();
	}
	
	/**
	 * Emits a To-Do error.
	 *
	 * @param __args Arguments to the error.
	 * @return The generated error.
	 * @since 2020/03/21
	 */

	public static Error todo(Object... __args)
	{



		return new TODO();


























































	}
	
	/**
	 * Emits a To-Do note.
	 *
	 * @param __fmt Format string.
	 * @since 2020/05/13







|









>


>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
	 * Emits a To-Do error.
	 *
	 * @return The generated error.
	 * @since 2020/03/21
	 */
	public static Error todo()
	{
		return Debugging.todo((Object[])null);
	}
	
	/**
	 * Emits a To-Do error.
	 *
	 * @param __args Arguments to the error.
	 * @return The generated error.
	 * @since 2020/03/21
	 */
	@SuppressWarnings("StaticVariableUsedBeforeInitialization")
	public static Error todo(Object... __args)
	{
		// Only trip this once! In the event this trips twice, just shortcut
		// with an exception otherwise
		if (Debugging._tripped)
			return new Error("Recursive TODO");
		Debugging._tripped = true;
		
		// This try is here so that in event this fails or throws another
		// exception, we always terminal no matter what
		try
		{
			// Print a very visible banner to not hide this information
			Debugging.todoNote(
				"*****************************************");
			Debugging.todoNote("INCOMPLETE CODE HAS BEEN REACHED: ");
			
			// Print the stack trace first like this so it does not possibly
			// get trashed
			CallTraceUtils.printStackTrace(
				new ConsoleOutputStream(StandardPipeType.STDERR),
				"INCOMPLETE CODE", DebugShelf.traceStack(),
				null, null, 0);
			
			// Print all arguments passed afterwards, just in case
			if (__args != null)
			{
				Debugging.todoNote(
					"-----------------------------------------");
				
				int n = __args.length;
				for (int i = 0; i < n; i++)
					try
					{
						Debugging.todoNote("%d: %s", i, __args[i]);
					}
					catch (Throwable ignored)
					{
						// Just drop everything here, so we can try to print
						// as much as we can
					}
			}
			
			Debugging.todoNote(
				"*****************************************");
		}
		
		// Always try to exit at the end of the call, in the event another
		// exception is thrown
		finally
		{
			// Just exit directly so there is no way to continue, if we can
			try
			{
				System.exit(Debugging._TODO_EXIT_STATUS);
			}
			catch (SecurityException ignored)
			{
				// However just ignore this case if we cannot truly exit here
			}
		}
		
		// Throw normal error here
		throw new Error("TODO");
	}
	
	/**
	 * Emits a To-Do note.
	 *
	 * @param __fmt Format string.
	 * @since 2020/05/13
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
	 */
	public static void todoNote(String __fmt, Object... __args)
	{
		Debugging.__format('T', 'D', __fmt, __args);
	}
	
	/**
	 * Returns a TODO for an object.
	 *
	 * @param <T> The type.
	 * @param __args The calling arguments.
	 * @return Never returns.
	 * @since 2020/04/09
	 */
	public static <T> T todoObject(Object... __args)







|







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
	 */
	public static void todoNote(String __fmt, Object... __args)
	{
		Debugging.__format('T', 'D', __fmt, __args);
	}
	
	/**
	 * Returns a To-Do for an object.
	 *
	 * @param <T> The type.
	 * @param __args The calling arguments.
	 * @return Never returns.
	 * @since 2020/04/09
	 */
	public static <T> T todoObject(Object... __args)
189
190
191
192
193
194
195
196

197
198
199
200

201
202
203
204
205
206
207
				// Printing a specifier
				if (specifier)
				{
					// Ignore flags
					if (c == '-' || c == '#' || c == '+' ||
						c == ' ' || c == ',' || c == '(' ||
						(firstChar && c == '0'))
						;

					
					// Ignore precision
					else if (c == '.')
						;

					
					// Could be width or argument index position
					else if ((c >= '1' && c <= '9') ||
						(!firstChar && c == '0'))
					{
						if (hasArgIndex)
						{







<
>



<
>







258
259
260
261
262
263
264

265
266
267
268

269
270
271
272
273
274
275
276
				// Printing a specifier
				if (specifier)
				{
					// Ignore flags
					if (c == '-' || c == '#' || c == '+' ||
						c == ' ' || c == ',' || c == '(' ||
						(firstChar && c == '0'))

						continue;
					
					// Ignore precision
					else if (c == '.')

						continue;
					
					// Could be width or argument index position
					else if ((c >= '1' && c <= '9') ||
						(!firstChar && c == '0'))
					{
						if (hasArgIndex)
						{
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

373
374
375
376
377
378
379
380
381
	 * @param __c The character to print.
	 * @param __d Second character to print.
	 * @since 2020/05/07
	 */
	@SuppressWarnings("FeatureEnvy")
	private static void __print(char __c, char __d)
	{
		// If we do not know the pipe for standard error, get it
		int pipe = Debugging._pipe;
		if (pipe == Integer.MIN_VALUE)
			Debugging._pipe = (pipe = Assembly.sysCallPV(
				SystemCallIndex.PD_OF_STDERR));
				
		// Print first character, snip to ASCII
		Assembly.sysCallPV(SystemCallIndex.PD_WRITE_BYTE, pipe,
			(__c > Debugging._BYTE_LIMIT ? '?' : __c));
		
		// Print other characters in bulk, snip to ASCII
		if (__d != 0)
			Assembly.sysCallPV(SystemCallIndex.PD_WRITE_BYTE, pipe,

				(__d > Debugging._BYTE_LIMIT ? '?' : __d));
	}
	
	/**
	 * Prints end of line.
	 *
	 * @since 2020/05/07
	 */
	private static void __printLine()
	{
		// Get the line type used
		int line = Debugging._line;
		if (line == Integer.MIN_VALUE)
			Debugging._line = (line = Assembly.sysCallV(
				SystemCallIndex.CONFIG_GET_VALUE, ConfigRomKey.LINE_ENDING));
		
		// Print it depending on what is desired
		switch (line)
		{
			case LineEndingType.CR:
				Debugging.__print('\r', '\0');
				break;
				
			case LineEndingType.LF:
				Debugging.__print('\n', '\0');

				break;
				
			case LineEndingType.CRLF:
			default:
				Debugging.__print('\r', '\n');
				break;
		}
	}
}







<
<
<
<
<
|
<
<


<
|
<
>










<
|
<
<
<
|
<
<

|
<
<
|
<
<
>

|
<
<
|
<



397
398
399
400
401
402
403





404


405
406

407

408
409
410
411
412
413
414
415
416
417
418

419



420


421
422


423


424
425
426


427

428
429
430
	 * @param __c The character to print.
	 * @param __d Second character to print.
	 * @since 2020/05/07
	 */
	@SuppressWarnings("FeatureEnvy")
	private static void __print(char __c, char __d)
	{





		TerminalShelf.write(StandardPipeType.STDERR,


			(__c > Debugging._BYTE_LIMIT ? '?' : __c));
		

		if (__d > 0)

			TerminalShelf.write(StandardPipeType.STDERR,
				(__d > Debugging._BYTE_LIMIT ? '?' : __d));
	}
	
	/**
	 * Prints end of line.
	 *
	 * @since 2020/05/07
	 */
	private static void __printLine()
	{

		int lineType = RuntimeShelf.lineEnding();



		for (int i = 0;; i++)


		{
			char c = LineEndingUtils.toChar(lineType, i);


			


			if (c == 0)
				break;
			


			Debugging.__print(c, '\0');

		}
	}
}

Added modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/debug/JavaOpCodeUtils.java.





















































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.debug;

/**
 * Utilities for Java op-codes.
 *
 * @since 2020/06/13
 */
public final class JavaOpCodeUtils
{
	/**
	 * Not used.
	 *
	 * @since 2020/06/13
	 */
	private JavaOpCodeUtils()
	{
	}
	
	/**
	 * Converts the op-code to a string.
	 *
	 * @param __code The opcode.
	 * @return The string representation of the code.
	 * @since 2020/06/13
	 */
	@SuppressWarnings("MagicNumber")
	public static String toString(int __code)
	{
		// Wide codes
		switch (__code & 0xFFFF)
		{
			case 50197:	return "WIDE_ILOAD";
			case 50198:	return "WIDE_LLOAD";
			case 50199:	return "WIDE_FLOAD";
			case 50200:	return "WIDE_DLOAD";
			case 50201:	return "WIDE_ALOAD";
			case 50230:	return "WIDE_ISTORE";
			case 50231:	return "WIDE_LSTORE";
			case 50232:	return "WIDE_FSTORE";
			case 50233:	return "WIDE_DSTORE";
			case 50234:	return "WIDE_ASTORE";
			case 50308:	return "WIDE_IINC";
		}
		
		// Narrow codes
		switch (__code & 0xFF)
		{
			case 0:		return "NOP";
			case 1:		return "ACONST_NULL";
			case 2:		return "ICONST_M1";
			case 3:		return "ICONST_0";
			case 4:		return "ICONST_1";
			case 5:		return "ICONST_2";
			case 6:		return "ICONST_3";
			case 7:		return "ICONST_4";
			case 8:		return "ICONST_5";
			case 9:		return "LCONST_0";
			case 10:	return "LCONST_1";
			case 11:	return "FCONST_0";
			case 12:	return "FCONST_1";
			case 13:	return "FCONST_2";
			case 14:	return "DCONST_0";
			case 15:	return "DCONST_1";
			case 16:	return "BIPUSH";
			case 17:	return "SIPUSH";
			case 18:	return "LDC";
			case 19:	return "LDC_W";
			case 20:	return "LDC2_W";
			case 21:	return "ILOAD";
			case 22:	return "LLOAD";
			case 23:	return "FLOAD";
			case 24:	return "DLOAD";
			case 25:	return "ALOAD";
			case 26:	return "ILOAD_0";
			case 27:	return "ILOAD_1";
			case 28:	return "ILOAD_2";
			case 29:	return "ILOAD_3";
			case 30:	return "LLOAD_0";
			case 31:	return "LLOAD_1";
			case 32:	return "LLOAD_2";
			case 33:	return "LLOAD_3";
			case 34:	return "FLOAD_0";
			case 35:	return "FLOAD_1";
			case 36:	return "FLOAD_2";
			case 37:	return "FLOAD_3";
			case 38:	return "DLOAD_0";
			case 39:	return "DLOAD_1";
			case 40:	return "DLOAD_2";
			case 41:	return "DLOAD_3";
			case 42:	return "ALOAD_0";
			case 43:	return "ALOAD_1";
			case 44:	return "ALOAD_2";
			case 45:	return "ALOAD_3";
			case 46:	return "IALOAD";
			case 47:	return "LALOAD";
			case 48:	return "FALOAD";
			case 49:	return "DALOAD";
			case 50:	return "AALOAD";
			case 51:	return "BALOAD";
			case 52:	return "CALOAD";
			case 53:	return "SALOAD";
			case 54:	return "ISTORE";
			case 55:	return "LSTORE";
			case 56:	return "FSTORE";
			case 57:	return "DSTORE";
			case 58:	return "ASTORE";
			case 59:	return "ISTORE_0";
			case 60:	return "ISTORE_1";
			case 61:	return "ISTORE_2";
			case 62:	return "ISTORE_3";
			case 63:	return "LSTORE_0";
			case 64:	return "LSTORE_1";
			case 65:	return "LSTORE_2";
			case 66:	return "LSTORE_3";
			case 67:	return "FSTORE_0";
			case 68:	return "FSTORE_1";
			case 69:	return "FSTORE_2";
			case 70:	return "FSTORE_3";
			case 71:	return "DSTORE_0";
			case 72:	return "DSTORE_1";
			case 73:	return "DSTORE_2";
			case 74:	return "DSTORE_3";
			case 75:	return "ASTORE_0";
			case 76:	return "ASTORE_1";
			case 77:	return "ASTORE_2";
			case 78:	return "ASTORE_3";
			case 79:	return "IASTORE";
			case 80:	return "LASTORE";
			case 81:	return "FASTORE";
			case 82:	return "DASTORE";
			case 83:	return "AASTORE";
			case 84:	return "BASTORE";
			case 85:	return "CASTORE";
			case 86:	return "SASTORE";
			case 87:	return "POP";
			case 88:	return "POP2";
			case 89:	return "DUP";
			case 90:	return "DUP_X1";
			case 91:	return "DUP_X2";
			case 92:	return "DUP2";
			case 93:	return "DUP2_X1";
			case 94:	return "DUP2_X2";
			case 95:	return "SWAP";
			case 96:	return "IADD";
			case 97:	return "LADD";
			case 98:	return "FADD";
			case 99:	return "DADD";
			case 100:	return "ISUB";
			case 101:	return "LSUB";
			case 102:	return "FSUB";
			case 103:	return "DSUB";
			case 104:	return "IMUL";
			case 105:	return "LMUL";
			case 106:	return "FMUL";
			case 107:	return "DMUL";
			case 108:	return "IDIV";
			case 109:	return "LDIV";
			case 110:	return "FDIV";
			case 111:	return "DDIV";
			case 112:	return "IREM";
			case 113:	return "LREM";
			case 114:	return "FREM";
			case 115:	return "DREM";
			case 116:	return "INEG";
			case 117:	return "LNEG";
			case 118:	return "FNEG";
			case 119:	return "DNEG";
			case 120:	return "ISHL";
			case 121:	return "LSHL";
			case 122:	return "ISHR";
			case 123:	return "LSHR";
			case 124:	return "IUSHR";
			case 125:	return "LUSHR";
			case 126:	return "IAND";
			case 127:	return "LAND";
			case 128:	return "IOR";
			case 129:	return "LOR";
			case 130:	return "IXOR";
			case 131:	return "LXOR";
			case 132:	return "IINC";
			case 133:	return "I2L";
			case 134:	return "I2F";
			case 135:	return "I2D";
			case 136:	return "L2I";
			case 137:	return "L2F";
			case 138:	return "L2D";
			case 139:	return "F2I";
			case 140:	return "F2L";
			case 141:	return "F2D";
			case 142:	return "D2I";
			case 143:	return "D2L";
			case 144:	return "D2F";
			case 145:	return "I2B";
			case 146:	return "I2C";
			case 147:	return "I2S";
			case 148:	return "LCMP";
			case 149:	return "FCMPL";
			case 150:	return "FCMPG";
			case 151:	return "DCMPL";
			case 152:	return "DCMPG";
			case 153:	return "IFEQ";
			case 154:	return "IFNE";
			case 155:	return "IFLT";
			case 156:	return "IFGE";
			case 157:	return "IFGT";
			case 158:	return "IFLE";
			case 159:	return "IF_ICMPEQ";
			case 160:	return "IF_ICMPNE";
			case 161:	return "IF_ICMPLT";
			case 162:	return "IF_ICMPGE";
			case 163:	return "IF_ICMPGT";
			case 164:	return "IF_ICMPLE";
			case 165:	return "IF_ACMPEQ";
			case 166:	return "IF_ACMPNE";
			case 167:	return "GOTO";
			case 168:	return "JSR";
			case 169:	return "RET";
			case 170:	return "TABLESWITCH";
			case 171:	return "LOOKUPSWITCH";
			case 172:	return "IRETURN";
			case 173:	return "LRETURN";
			case 174:	return "FRETURN";
			case 175:	return "DRETURN";
			case 176:	return "ARETURN";
			case 177:	return "RETURN";
			case 178:	return "GETSTATIC";
			case 179:	return "PUTSTATIC";
			case 180:	return "GETFIELD";
			case 181:	return "PUTFIELD";
			case 182:	return "INVOKEVIRTUAL";
			case 183:	return "INVOKESPECIAL";
			case 184:	return "INVOKESTATIC";
			case 185:	return "INVOKEINTERFACE";
			case 186:	return "INVOKEDYNAMIC";
			case 187:	return "NEW";
			case 188:	return "NEWARRAY";
			case 189:	return "ANEWARRAY";
			case 190:	return "ARRAYLENGTH";
			case 191:	return "ATHROW";
			case 192:	return "CHECKCAST";
			case 193:	return "INSTANCEOF";
			case 194:	return "MONITORENTER";
			case 195:	return "MONITOREXIT";
			case 196:	return "WIDE";
			case 197:	return "MULTIANEWARRAY";
			case 198:	return "IFNULL";
			case 199:	return "IFNONNULL";
			case 200:	return "GOTO_W";
			case 201:	return "JSR_W";
			case 202:	return "BREAKPOINT";
			case 254:	return "IMPDEP1";
			case 255:	return "IMPDEP2";
		}
		
		return "UNKNOWN";
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/i18n/DefaultLocale.java.

1
2
3
4
5
6
7
8
9
10
11
12



13
14
15
16
17
18
19
20
21
22

23
24

25
26
27
28
29
30
31
32
33
34
35






















36
37
38
39
40
41
42
43
44
45
46
47


48













49
50
51
52
53
54

55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.i18n;




/**
 * This class provides access to the default locale.
 *
 * @since 2018/09/20
 */
public final class DefaultLocale
{
	/** The locale to use for conversion in cases where one is not used. */
	public static final Locale NO_LOCALE =
		new LocaleEnUs();

	
	/** The default locale. */

	private static final Locale _DEFAULT_LOCALE =
		DefaultLocale.__defaultLocale();
	
	/**
	 * Not used.
	 *
	 * @since 2018/09/20
	 */
	private DefaultLocale()
	{
	}






















	
	/**
	 * Returns the default locale, if one was not initialized yet then "en-US"
	 * will be used temporarily until one is.
	 *
	 * @return The default locale, this value should not be cached.
	 * @since 2018/09/20
	 */
	public static final Locale defaultLocale()
	{
		Locale rv = DefaultLocale._DEFAULT_LOCALE;
		if (rv == null)


			return DefaultLocale.NO_LOCALE;













		return rv;
	}
	
	/**
	 * Determines the default locale.
	 *

	 * @return The default locale.

	 * @since 2018/09/20
	 */
	private static final Locale __defaultLocale()
	{
		// Use local from system property
		String prop = null;
		try
		{
			prop = System.getProperty("microedition.locale");
		}
		catch (SecurityException e)
		{
		}
		
		// If there is none, default to US
		if (prop == null)
			return new LocaleEnUs();
		
		// Determine the locale to use
		Locale use;
		switch (prop.toLowerCase())
		{

				// Fallback to en-US
			case "en-us":
			default:
				return new LocaleEnUs();
		}
	}
}













>
>
>








|
|
>


>
|
|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|

|

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>




|

>
|
>
|

<
<
|
|
<
<
<
<
|
|
<
|
<
<
<
|
<
|
<
|
>
|
<

|



<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101


102
103




104
105

106



107

108

109
110
111

112
113
114
115
116

// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.i18n;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.BuiltInLocaleType;

/**
 * This class provides access to the default locale.
 *
 * @since 2018/09/20
 */
public final class DefaultLocale
{
	/** The locale to use for conversion in cases where one is not used. */
	@SuppressWarnings("RedundantFieldInitialization")
	private static Locale _noLocale =
		null;
	
	/** The default locale. */
	@SuppressWarnings("RedundantFieldInitialization")
	private static Locale _defaultLocale =
		null;
	
	/**
	 * Not used.
	 *
	 * @since 2018/09/20
	 */
	private DefaultLocale()
	{
	}
	
	/**
	 * Returns the built-in locale instance.
	 *
	 * @param __id The {@link BuiltInLocaleType}.
	 * @return The built-in locale.
	 * @since 2020/06/11
	 */
	@SuppressWarnings("SwitchStatementWithTooFewBranches")
	public static Locale builtInLocale(int __id)
	{
		switch (__id)
		{
			case BuiltInLocaleType.UNSPECIFIED:
			case BuiltInLocaleType.ENGLISH_US:
				return new LocaleEnUs();
			
				// {@squirreljme.error ZZ3v Unknown built-in locale ID. (ID)}
			default:
				throw new IllegalArgumentException("ZZ3v " + __id);
		}
	}
	
	/**
	 * Returns the default locale, if one was not initialized yet then "en-US"
	 * will be used temporarily until one is.
	 *
	 * @return The default locale, this value should not be cached.
	 * @since 2018/09/20
	 */
	public static Locale defaultLocale()
	{
		Locale rv = DefaultLocale._defaultLocale;
		if (rv == null)
			DefaultLocale._defaultLocale = (rv = DefaultLocale.builtInLocale(
				RuntimeShelf.locale()));
		return rv;
	}
	
	/**
	 * Returns the default no-locale which is used for default operations.
	 *
	 * @return The no-locale.
	 * @since 2020/06/11
	 */
	public static Locale noLocale()
	{
		Locale rv = DefaultLocale._noLocale;
		if (rv == null)
			DefaultLocale._noLocale = (rv = new LocaleEnUs());
		return rv;
	}
	
	/**
	 * Returns the string representation of the given locale.
	 *
	 * @param __builtIn The {@link BuiltInLocaleType}.
	 * @return The string representation of this locale.
	 * @throws IllegalArgumentException If the built-in encoding is unknown.
	 * @since 2020/06/11
	 */


	@SuppressWarnings("SwitchStatementWithTooFewBranches")
	public static String toString(int __builtIn)




		throws IllegalArgumentException
	{

		switch (__builtIn)



		{

			case BuiltInLocaleType.ENGLISH_US:	return "en-US";

			
				// {@squirreljme.error ZZ4a Unknown built-in encoding.
				// (The built-in encoding ID)}.

			default:
				throw new IllegalArgumentException("ZZ4a " + __builtIn);
		}
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/io/CodecFactory.java.

1
2
3
4
5
6
7
8
9
10
11
12



13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.io;




import java.io.UnsupportedEncodingException;

/**
 * This contains the code used to obtain the default encoding as well as
 * obtaining the encoder or decoder as needed.
 *
 * @since 2018/09/16












>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.io;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.BuiltInEncodingType;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.io.UnsupportedEncodingException;

/**
 * This contains the code used to obtain the default encoding as well as
 * obtaining the encoder or decoder as needed.
 *
 * @since 2018/09/16
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118


119







120
121
122
123
124
125
126
127
128
129


130
131

132






133
134
135

136

137
138
139

140
141
142
143
144
145
146

147
148


149


150


151





152
153
154
155
156
157
158
159
160
161
162
163
164
165













166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218




219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
	 * @since 2018/09/16
	 */
	private CodecFactory()
	{
	}
	
	/**
	 * Returns a decoder for the given encoding.
	 *
	 * @param __enc The encoding to decode for.
	 * @return The decoder for the given encoding.
	 * @throws NullPointerException On null arguments.
	 * @throws UnsupportedEncodingException If the encoding is not supported.
	 * @since 2018/10/13
	 */
	public static final Decoder decoder(String __enc)
		throws NullPointerException, UnsupportedEncodingException
	{
		if (__enc == null)
			throw new NullPointerException("NARG");
		
		// Normalization makes it easier to match
		switch ((__enc = CodecFactory.__normalizeEncodingName(__enc)))
		{
				// ASCII
			case "ascii":
				return new ASCIIDecoder();
				


				// IBM037
			case "ibm037":
				throw new todo.TODO();

				// ISO-8859-1
			case "iso-8859-1":
				return new ISO88591Decoder();
				
				// ISO-8859-15
			case "iso-8859-15":
				return new ISO885915Decoder();
				
				// UTF-8
			case "utf-8":
				return new UTF8Decoder();
			
				// {@squirreljme.error ZZ01 Unknown encoding. (The input
				// encoding)}

			default:
				throw new UnsupportedEncodingException(
					String.format("ZZ01 %s", __enc));
		}
	}
	
	/**
	 * Returns a decoder for the given encoding.
	 *
	 * @param __enc The encoding to decode for.
	 * @return The decoder for the given encoding.
	 * @throws NullPointerException On null arguments.
	 * @throws RuntimeException If the encoding is not supported.
	 * @since 2018/10/13
	 */
	public static final Decoder decoderUnchecked(String __enc)
		throws NullPointerException, RuntimeException
	{
		if (__enc == null)
			throw new NullPointerException("NARG");
		
		// Could fail
		try
		{
			return CodecFactory.decoder(__enc);
		}
		
		// {@squirreljme.error ZZ02 Unknown or unsupported encoding.
		// (The encoding)}
		catch (UnsupportedEncodingException e)
		{
			throw new RuntimeException(String.format("ZZ02 %s", __enc), e);
		}
	}
	
	/**
	 * Returns the default decoder.
	 *
	 * @return The default decoder.
	 * @since 2018/10/13
	 */
	public static final Decoder defaultDecoder()
	{


		return CodecFactory.decoderUnchecked(CodecFactory.defaultEncoding());







	}
	
	/**
	 * Returns the default system encoder.
	 *
	 * @return The default encoder.
	 * @since 2018/09/16
	 */
	public static final Encoder defaultEncoder()
	{


		return CodecFactory.encoderUnchecked(CodecFactory.defaultEncoding());
	}

	






	/**
	 * Returns the default encoding.
	 *

	 * @return The default encoding.

	 * @since 2018/09/16
	 */
	public static final String defaultEncoding()

	{
		// If no encoding has been set, fallback on one so it is always valid
		try
		{
			String rv = System.getProperty("microedition.encoding");
			if (rv == null)
				return CodecFactory.FALLBACK_ENCODING;

			return rv;
		}


		catch (SecurityException e)


		{


			return CodecFactory.FALLBACK_ENCODING;





		}
	}
	
	/**
	 * Returns the specified encoder.
	 *
	 * @param __enc The encoding to encode to.
	 * @return The encoder for the given encoding.
	 * @throws NullPointerException On null arguments.
	 * @throws UnsupportedEncodingException If the encoding is not supported.
	 * @since 2018/09/17
	 */
	public static final Encoder encoder(String __enc)
		throws NullPointerException, UnsupportedEncodingException













	{
		if (__enc == null)
			throw new NullPointerException("NARG");
		
		// Normalization makes it easier to match
		switch ((__enc = CodecFactory.__normalizeEncodingName(__enc)))
		{
				// ASCII
			case "ascii":
				return new ASCIIEncoder();
				
				// IBM037
			case "ibm037":
				return new IBM037Encoder();

				// ISO-8859-1
			case "iso-8859-1":
				return new ISO88591Encoder();
				
				// ISO-8859-15
			case "iso-8859-15":
				return new ISO885915Encoder();
				
				// UTF-8
			case "utf-8":
				return new UTF8Encoder();
			
				// {@squirreljme.error ZZ03 Unknown encoding. (The output
				// encoding)}
			default:
				throw new UnsupportedEncodingException(
					String.format("ZZ03 %s", __enc));
		}
	}
	
	/**
	 * Returns the specified encoder.
	 *
	 * @param __enc The encoding to encode to.
	 * @return The encoder for the given encoding.
	 * @throws NullPointerException On null arguments.
	 * @throws RuntimeException If the encoding is not valid.
	 * @since 2018/09/17
	 */
	public static final Encoder encoderUnchecked(String __enc)
		throws NullPointerException, RuntimeException
	{
		if (__enc == null)
			throw new NullPointerException("NARG");
		
		// Could fail
		try
		{




			return CodecFactory.encoder(__enc);
		}
		
		// {@squirreljme.error ZZ04 Unknown or unsupported encoding.
		// (The encoding)}

		catch (UnsupportedEncodingException e)
		{
			throw new RuntimeException(String.format("ZZ04 %s", __enc), e);
		}
	}
	
	/**
	 * Normalizes the name of the encoding since there are so many aliases that
	 * way this code can operate very simply.
	 *
	 * @param __n The encoding to normalize.
	 * @return The normalized encoding, if it is not known then the input is
	 * returned.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/19
	 */
	private static final String __normalizeEncodingName(String __n)
		throws NullPointerException
	{
		if (__n == null)
			throw new NullPointerException("NARG");
		
		// Store original since it will be lowercase
		String orign = __n;
		
		// Lowercase and map values
		switch ((__n = __n.toLowerCase()))
		{
				// ASCII
			case "646":
			case "ansi_x3.4-1968":
			case "ansi_x3.4-1986":
			case "ascii":
			case "ascii7":







|

|

<
|
|

|
|

<
<
|
<
<

|
<

|
>
>
<
<
<
|
<
|

|
<
|

|
<
|

|
|
|
>

|
<









|


|
|

<
<
<
<
<
<
|
<
<
<
<
<
<
<
<








|

>
>
|
>
>
>
>
>
>
>








|

>
>
|
|
>
|
>
>
>
>
>
>

|

>
|
>
|

|
>

<
|

|
|
|
>
|
|
>
>
|
>
>
|
>
>
|
>
>
>
>
>












|

>
>
>
>
>
>
>
>
>
>
>
>
>







<
|
<
<
<
|
<
<
<
|
<
<
<
|
<
<
<
|
<

|



|




|

|
|
<
|
|

|
|

<
<
|
<
<

>
>
>
>
|
|
<
|
|
>
|
<
<













|





<
<
<

|







33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49


50


51
52

53
54
55
56



57

58
59
60

61
62
63

64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86






87








88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

197



198



199



200



201

202
203
204
205
206
207
208
209
210
211
212
213
214
215

216
217
218
219
220
221


222


223
224
225
226
227
228
229

230
231
232
233


234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252



253
254
255
256
257
258
259
260
261
	 * @since 2018/09/16
	 */
	private CodecFactory()
	{
	}
	
	/**
	 * Returns the decoder for the given encoding.
	 *
	 * @param __builtIn The {@link BuiltInEncodingType}.
	 * @return The decoder for the given encoding.

	 * @throws UnsupportedEncodingException If the encoding is invalid.
	 * @since 2020/06/11
	 */
	public static Decoder decoder(int __builtIn)
		throws UnsupportedEncodingException
	{


		switch (__builtIn)


		{
			case BuiltInEncodingType.ASCII:

				return new ASCIIDecoder();
			
			case BuiltInEncodingType.IBM037:
				throw Debugging.todo();



			

			case BuiltInEncodingType.ISO_8859_1:
				return new ISO88591Decoder();
			

			case BuiltInEncodingType.ISO_8859_15:
				return new ISO885915Decoder();
			

			case BuiltInEncodingType.UTF8:
				return new UTF8Decoder();
				
				// {@squirreljme.error ZZ47 Unsupported decoder.
				// (The built-in encoding ID)}
			case BuiltInEncodingType.UNSPECIFIED:
			default:
				throw new UnsupportedEncodingException("ZZ47 " + __builtIn);

		}
	}
	
	/**
	 * Returns a decoder for the given encoding.
	 *
	 * @param __enc The encoding to decode for.
	 * @return The decoder for the given encoding.
	 * @throws NullPointerException On null arguments.
	 * @throws UnsupportedEncodingException If the encoding is not supported.
	 * @since 2018/10/13
	 */
	public static Decoder decoder(String __enc)
		throws NullPointerException, UnsupportedEncodingException
	{






		return CodecFactory.decoder(CodecFactory.toBuiltIn(__enc));








	}
	
	/**
	 * Returns the default decoder.
	 *
	 * @return The default decoder.
	 * @since 2018/10/13
	 */
	public static Decoder defaultDecoder()
	{
		try
		{
			return CodecFactory.decoder(RuntimeShelf.encoding());
		}
		catch (UnsupportedEncodingException e)
		{
			// {@squirreljme.error ZZ02 Built-in encoding is not configured
			// properly.}
			throw new Error("ZZ02", e);
		}
	}
	
	/**
	 * Returns the default system encoder.
	 *
	 * @return The default encoder.
	 * @since 2018/09/16
	 */
	public static Encoder defaultEncoder()
	{
		try
		{
			return CodecFactory.encoder(RuntimeShelf.encoding());
		}
		catch (UnsupportedEncodingException e)
		{
			// {@squirreljme.error ZZ04 Built-in encoding is not configured
			// properly.}
			throw new Error("ZZ04", e);
		}
	}
	
	/**
	 * Returns the encoder for the given built-in encoding.
	 *
	 * @param __builtIn The {@link BuiltInEncodingType}.
	 * @return The encoder.
	 * @throws UnsupportedEncodingException If the encoder is not valid.
	 * @since 2020/06/11
	 */
	public static Encoder encoder(int __builtIn)
		throws UnsupportedEncodingException
	{

		switch (__builtIn)
		{
			case BuiltInEncodingType.ASCII:
				return new ASCIIEncoder();
			
			case BuiltInEncodingType.IBM037:
				return new IBM037Encoder();
			
			case BuiltInEncodingType.ISO_8859_1:
				return new ISO88591Encoder();
			
			case BuiltInEncodingType.ISO_8859_15:
				return new ISO885915Encoder();
			
			case BuiltInEncodingType.UTF8:
				return new UTF8Encoder();
				
				// {@squirreljme.error ZZ48 Unsupported encoder.
				// (The built-in encoding ID)}
			case BuiltInEncodingType.UNSPECIFIED:
			default:
				throw new UnsupportedEncodingException("ZZ48 " + __builtIn);
		}
	}
	
	/**
	 * Returns the specified encoder.
	 *
	 * @param __enc The encoding to encode to.
	 * @return The encoder for the given encoding.
	 * @throws NullPointerException On null arguments.
	 * @throws UnsupportedEncodingException If the encoding is not supported.
	 * @since 2018/09/17
	 */
	public static Encoder encoder(String __enc)
		throws NullPointerException, UnsupportedEncodingException
	{
		return CodecFactory.encoder(CodecFactory.toBuiltIn(__enc));
	}
	
	/**
	 * Returns the built-in encoding ID.
	 *
	 * @param __enc The name of the encoding.
	 * @return The built-in encoding.
	 * @since 2020/06/11
	 */
	public static int toBuiltIn(String __enc)
		throws UnsupportedEncodingException
	{
		if (__enc == null)
			throw new NullPointerException("NARG");
		
		// Normalization makes it easier to match
		switch ((__enc = CodecFactory.__normalizeEncodingName(__enc)))
		{

			case "ascii":		return BuiltInEncodingType.ASCII;



			case "ibm037":		return BuiltInEncodingType.IBM037;



			case "iso-8859-1":	return BuiltInEncodingType.ISO_8859_1;



			case "iso-8859-15":	return BuiltInEncodingType.ISO_8859_15;



			case "utf-8":		return BuiltInEncodingType.UTF8;

			
				// {@squirreljme.error ZZ01 Unknown encoding. (The input
				// encoding)}
			default:
				throw new UnsupportedEncodingException(
					String.format("ZZ01 %s", __enc));
		}
	}
	
	/**
	 * Returns the string representation of the given built-in encoding.
	 *
	 * @param __builtIn The {@link BuiltInEncodingType}.
	 * @return The string for this built-in encoding.

	 * @throws IllegalArgumentException If the encoding is not valid.
	 * @since 2020/06/11
	 */
	public static String toString(int __builtIn)
		throws IllegalArgumentException
	{


		switch (__builtIn)


		{
			case BuiltInEncodingType.ASCII:			return "ascii";
			case BuiltInEncodingType.IBM037:		return "ibm037";
			case BuiltInEncodingType.ISO_8859_1:	return "iso-8859-1";
			case BuiltInEncodingType.ISO_8859_15:	return "iso-8859-15";
			case BuiltInEncodingType.UTF8:			return "utf-8";
			

				// {@squirreljme.error ZZ49 Invalid built-in encoding.
				// (The built-in ID}}
			default:
				throw new IllegalArgumentException("ZZ49 " + __builtIn);


		}
	}
	
	/**
	 * Normalizes the name of the encoding since there are so many aliases that
	 * way this code can operate very simply.
	 *
	 * @param __n The encoding to normalize.
	 * @return The normalized encoding, if it is not known then the input is
	 * returned.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/19
	 */
	private static String __normalizeEncodingName(String __n)
		throws NullPointerException
	{
		if (__n == null)
			throw new NullPointerException("NARG");
		



		// Lowercase and map values
		switch (__n.toLowerCase())
		{
				// ASCII
			case "646":
			case "ansi_x3.4-1968":
			case "ansi_x3.4-1986":
			case "ascii":
			case "ascii7":
306
307
308
309
310
311
312
313
314
315
316
317
			case "unicode-1-1-utf-8":
			case "utf8":
			case "utf-8":
				return "utf-8";
			
				// Unknown use original
			default:
				return orign;
		}
	}
}








|




310
311
312
313
314
315
316
317
318
319
320
321
			case "unicode-1-1-utf-8":
			case "utf8":
			case "utf-8":
				return "utf-8";
			
				// Unknown use original
			default:
				return __n;
		}
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/io/ConsoleOutputStream.java.

1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19


20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37

















































38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.io;



import cc.squirreljme.runtime.cldc.asm.ConsoleOutput;
import java.io.IOException;
import java.io.OutputStream;

/**
 * This provides an output stream which writes to a console file descriptor.
 *


 * @since 2018/12/08
 */
public final class ConsoleOutputStream
	extends OutputStream

{
	/** the file descriptor to write to. */
	protected final int fd;
	
	/**
	 * Initializes the output stream.
	 *
	 * @param __fd The descriptor to write to.
	 * @since 2018/12/08
	 */
	public ConsoleOutputStream(int __fd)
	{
		this.fd = __fd;
	}

















































	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/08
	 */
	@Override
	public void flush()
		throws IOException
	{
		// {@squirreljme.error ZZ05 Could not flush the console.}
		if (ConsoleOutput.flush(this.fd) < 0)
			throw new IOException("ZZ05");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2016/06/16
	 */
	@Override
	public void write(int __b)
		throws IOException
	{
		// {@squirreljme.error ZZ06 Error writing to console.}
		if (ConsoleOutput.write(this.fd, __b) != 0)
			throw new IOException("ZZ06");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/05
	 */
	@Override
	public void write(byte[] __b)
		throws IOException, NullPointerException
	{
		if (__b == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ07 Error writing to console.}
		if (ConsoleOutput.write(this.fd, __b, 0, __b.length) < 0)
			throw new IOException("ZZ07");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/05
	 */
	@Override
	public void write(byte[] __b, int __o, int __l)
		throws IndexOutOfBoundsException, IOException, NullPointerException
	{
		if (__b == null)
			throw new NullPointerException("NARG");
		if (__o < 0 || __l < 0 || (__o + __l) > __b.length)
			throw new IndexOutOfBoundsException("IOOB");
		
		// {@squirreljme.error ZZ08 Error writing to console.}
		if (ConsoleOutput.write(this.fd, __b, __o, __l) < 0)
			throw new IOException("ZZ08");
	}
}













>
>
|






>
>




>














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|












|















|

















|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.io;

import cc.squirreljme.jvm.mle.TerminalShelf;
import cc.squirreljme.jvm.mle.constants.StandardPipeType;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.io.IOException;
import java.io.OutputStream;

/**
 * This provides an output stream which writes to a console file descriptor.
 *
 * @see StandardPipeType
 * @see TerminalShelf
 * @since 2018/12/08
 */
public final class ConsoleOutputStream
	extends OutputStream
	implements Appendable
{
	/** the file descriptor to write to. */
	protected final int fd;
	
	/**
	 * Initializes the output stream.
	 *
	 * @param __fd The descriptor to write to.
	 * @since 2018/12/08
	 */
	public ConsoleOutputStream(int __fd)
	{
		this.fd = __fd;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/15
	 */
	@Override
	public Appendable append(CharSequence __seq)
		throws IOException
	{
		if (__seq == null)
			return this.append("null", 0, 4);
		return this.append(__seq, 0, __seq.length());
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/15
	 */
	@Override
	public Appendable append(CharSequence __seq, int __s, int __e)
		throws IOException
	{
		CharSequence trueSeq = (__seq == null ? "null" : __seq);
		
		for (int i = __s; i < __e; i++)
			this.append(trueSeq.charAt(i));
		
		return this;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/15
	 */
	@Override
	public Appendable append(char __c)
		throws IOException
	{
		// Encode bytes to whatever the system encoding is
		Encoder encoder = CodecFactory.defaultEncoder();
		int maxSeq = encoder.maximumSequenceLength();
		byte[] enc = new byte[maxSeq];
		int n = encoder.encode(__c, enc, 0, maxSeq);
		
		for (int i = 0; i < n; i++)
			this.write(enc[i]);
		
		return this;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/08
	 */
	@Override
	public void flush()
		throws IOException
	{
		// {@squirreljme.error ZZ05 Could not flush the console.}
		if (TerminalShelf.flush(this.fd) < 0)
			throw new IOException("ZZ05");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2016/06/16
	 */
	@Override
	public void write(int __b)
		throws IOException
	{
		// {@squirreljme.error ZZ06 Error writing to console.}
		if (TerminalShelf.write(this.fd, __b) < 0)
			throw new IOException("ZZ06");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/05
	 */
	@Override
	public void write(byte[] __b)
		throws IOException, NullPointerException
	{
		if (__b == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ07 Error writing to console.}
		if (TerminalShelf.write(this.fd, __b, 0, __b.length) < 0)
			throw new IOException("ZZ07");
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/05
	 */
	@Override
	public void write(byte[] __b, int __o, int __l)
		throws IndexOutOfBoundsException, IOException, NullPointerException
	{
		if (__b == null)
			throw new NullPointerException("NARG");
		if (__o < 0 || __l < 0 || (__o + __l) > __b.length)
			throw new IndexOutOfBoundsException("IOOB");
		
		// {@squirreljme.error ZZ08 Error writing to console.}
		if (TerminalShelf.write(this.fd, __b, __o, __l) < 0)
			throw new IOException("ZZ08");
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/io/ResourceInputStream.java.

13
14
15
16
17
18
19

20
21

22
23
24
25
26
27
28
import cc.squirreljme.runtime.cldc.asm.ResourceAccess;
import java.io.IOException;
import java.io.InputStream;

/**
 * This input stream handles reading of resources.
 *

 * @since 2018/10/07
 */

public final class ResourceInputStream
	extends InputStream
{
	/** The file descriptor. */
	protected final int fd;
	
	/** Has this been closed? */







>


>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import cc.squirreljme.runtime.cldc.asm.ResourceAccess;
import java.io.IOException;
import java.io.InputStream;

/**
 * This input stream handles reading of resources.
 *
 * @deprecated Being removed as it is no longer needed.
 * @since 2018/10/07
 */
@Deprecated
public final class ResourceInputStream
	extends InputStream
{
	/** The file descriptor. */
	protected final int fd;
	
	/** Has this been closed? */

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/lang/ArrayUtils.java.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.lang;


import cc.squirreljme.runtime.cldc.asm.ObjectAccess;

/**
 * This method contains the code which is able to initialize multi-dimensional
 * arrays and perform other array related tasks.
 *
 * @since 2018/11/03
 */












>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.lang;

import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.TypeShelf;

/**
 * This method contains the code which is able to initialize multi-dimensional
 * arrays and perform other array related tasks.
 *
 * @since 2018/11/03
 */
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
	 * @param __v The value to store.
	 * @throws ArrayIndexOutOfBoundsException If the index is out of bounds.
	 * @throws ClassCastException If the wrong class is used.
	 * @throws IllegalArgumentException If the argument is invalid.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/13
	 */
	public static final void arraySet(Object __a, int __dx, Object __v)
		throws ArrayIndexOutOfBoundsException, ClassCastException,
			IllegalArgumentException, NullPointerException
	{
		ArrayUtils.arraySet(ArrayUtils.arrayType(__a), __a, __dx, __v);
	}
	
	/**
	 * Sets the value in the array.
	 *
	 * @param __type The type of array used.
	 * @param __a The array.
	 * @param __dx The index to set.
	 * @param __v The value to store.
	 * @throws ArrayIndexOutOfBoundsException If the index is out of bounds.
	 * @throws ClassCastException If the wrong class is used.
	 * @throws IllegalArgumentException If the argument is invalid.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/13
	 */
	public static final void arraySet(int __type, Object __a, int __dx,
		Object __v)
		throws ArrayIndexOutOfBoundsException, ClassCastException,
			IllegalArgumentException, NullPointerException
	{
		if (__a == null)
			throw new NullPointerException("NARG");
		
		// Depends on the type
		switch (__type)
		{
			case ArrayUtils.ARRAY_BOOLEAN:
				((boolean[])__a)[__dx] = ((Boolean)__v).booleanValue();
				break;
				
			case ArrayUtils.ARRAY_BYTE:
				((byte[])__a)[__dx] = ((Byte)__v).byteValue();
				break;
				
			case ArrayUtils.ARRAY_SHORT:
				((short[])__a)[__dx] = ((Short)__v).shortValue();
				break;
				
			case ArrayUtils.ARRAY_CHARACTER:
				((char[])__a)[__dx] = ((Character)__v).charValue();
				break;
				
			case ArrayUtils.ARRAY_INTEGER:
				((int[])__a)[__dx] = ((Integer)__v).intValue();
				break;
				
			case ArrayUtils.ARRAY_LONG:
				((long[])__a)[__dx] = ((Long)__v).longValue();
				break;
				
			case ArrayUtils.ARRAY_FLOAT:
				((float[])__a)[__dx] = ((Float)__v).floatValue();
				break;
				
			case ArrayUtils.ARRAY_DOUBLE:
				((double[])__a)[__dx] = ((Double)__v).doubleValue();
				break;
				
			case ArrayUtils.ARRAY_OBJECT:
				((Object[])__a)[__dx] = __v;
				break;
			
				// {@squirreljme.error ZZ0c Invalid array type.}







|



















|











|



|



|



|



|



|



|



|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
	 * @param __v The value to store.
	 * @throws ArrayIndexOutOfBoundsException If the index is out of bounds.
	 * @throws ClassCastException If the wrong class is used.
	 * @throws IllegalArgumentException If the argument is invalid.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/13
	 */
	public static void arraySet(Object __a, int __dx, Object __v)
		throws ArrayIndexOutOfBoundsException, ClassCastException,
			IllegalArgumentException, NullPointerException
	{
		ArrayUtils.arraySet(ArrayUtils.arrayType(__a), __a, __dx, __v);
	}
	
	/**
	 * Sets the value in the array.
	 *
	 * @param __type The type of array used.
	 * @param __a The array.
	 * @param __dx The index to set.
	 * @param __v The value to store.
	 * @throws ArrayIndexOutOfBoundsException If the index is out of bounds.
	 * @throws ClassCastException If the wrong class is used.
	 * @throws IllegalArgumentException If the argument is invalid.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/13
	 */
	public static void arraySet(int __type, Object __a, int __dx,
		Object __v)
		throws ArrayIndexOutOfBoundsException, ClassCastException,
			IllegalArgumentException, NullPointerException
	{
		if (__a == null)
			throw new NullPointerException("NARG");
		
		// Depends on the type
		switch (__type)
		{
			case ArrayUtils.ARRAY_BOOLEAN:
				((boolean[])__a)[__dx] = (Boolean)__v;
				break;
				
			case ArrayUtils.ARRAY_BYTE:
				((byte[])__a)[__dx] = (Byte)__v;
				break;
				
			case ArrayUtils.ARRAY_SHORT:
				((short[])__a)[__dx] = (Short)__v;
				break;
				
			case ArrayUtils.ARRAY_CHARACTER:
				((char[])__a)[__dx] = (Character)__v;
				break;
				
			case ArrayUtils.ARRAY_INTEGER:
				((int[])__a)[__dx] = (Integer)__v;
				break;
				
			case ArrayUtils.ARRAY_LONG:
				((long[])__a)[__dx] = (Long)__v;
				break;
				
			case ArrayUtils.ARRAY_FLOAT:
				((float[])__a)[__dx] = (Float)__v;
				break;
				
			case ArrayUtils.ARRAY_DOUBLE:
				((double[])__a)[__dx] = (Double)__v;
				break;
				
			case ArrayUtils.ARRAY_OBJECT:
				((Object[])__a)[__dx] = __v;
				break;
			
				// {@squirreljme.error ZZ0c Invalid array type.}
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	 *
	 * @param __a The array type.
	 * @return The type of array this is.
	 * @throws IllegalArgumentException If not an array.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/13
	 */
	public static final int arrayType(Object __a)
		throws IllegalArgumentException, NullPointerException
	{
		if (__a == null)
			throw new NullPointerException("NARG");
		
		if (__a instanceof Object[])
			return ArrayUtils.ARRAY_OBJECT;







|







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	 *
	 * @param __a The array type.
	 * @return The type of array this is.
	 * @throws IllegalArgumentException If not an array.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/13
	 */
	public static int arrayType(Object __a)
		throws IllegalArgumentException, NullPointerException
	{
		if (__a == null)
			throw new NullPointerException("NARG");
		
		if (__a instanceof Object[])
			return ArrayUtils.ARRAY_OBJECT;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
	 * @param __a Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a});
	}
	







|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
	 * @param __a Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a});
	}
	
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
	 * @param __b Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b});
	}
	







|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	 * @param __b Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b});
	}
	
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
	 * @param __c Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c});
	}
	







|







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
	 * @param __c Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c});
	}
	
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
	 * @param __d Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d});
	}
	







|







267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
	 * @param __d Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d});
	}
	
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
	 * @param __e Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e});
	}
	







|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
	 * @param __e Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e});
	}
	
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
	 * @param __f Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f});
	}
	







|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
	 * @param __f Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f});
	}
	
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
	 * @param __g Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f, int __g)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f, __g});
	}
	







|







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
	 * @param __g Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f, int __g)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f, __g});
	}
	
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
	 * @param __h Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f, int __g,
		int __h)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f, __g, __h});
	}







|







373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
	 * @param __h Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f, int __g,
		int __h)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f, __g, __h});
	}
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
	 * @param __i Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f, int __g,
		int __h, int __i)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f, __g, __h, __i});
	}







|







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
	 * @param __i Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f, int __g,
		int __h, int __i)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f, __g, __h, __i});
	}
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
	 * @param __j Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f, int __g,
		int __h, int __i, int __j)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f, __g, __h, __i, __j});
	}







|







434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
	 * @param __j Length of dimension.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/04
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int __a, int __b, int __c, int __d, int __e, int __f, int __g,
		int __h, int __i, int __j)
		throws NegativeArraySizeException, NullPointerException
	{
		return ArrayUtils.multiANewArray(__type, __skip,
			new int[]{__a, __b, __c, __d, __e, __f, __g, __h, __i, __j});
	}
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
	 * @param __dims The dimensions and the number of them to use.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/03
	 */
	public static final Object multiANewArray(Class<?> __type, int __skip,
		int[] __dims)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__type == null || __dims == null)
			throw new NullPointerException("NARG");
		
		// Count the number of dimensions represented in the type
		String typename = __type.getName();
		int typedims = 0;
		while (typename.charAt(typedims) == '[')
			typedims++;
		
		// {@squirreljme.error ZZ0e Negative number of dimensions available
		// or input type is not correct for the array type.}
		int dims = __dims.length - __skip;
		if (__skip < 0 || dims <= 0 || typedims < dims)
			throw new IllegalArgumentException("ZZ0e");
		
		// Allocate array of this type
		int numelem = __dims[__skip];
		Object rv = ObjectAccess.arrayNew(__type, numelem);

		
		// Need to determine the type for setting
		int type = ArrayUtils.arrayType(rv);
		
		// The array has more dimensions which must be set
		if (dims > 1)
		{







|








|
|
|




|



|
|
>







456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
	 * @param __dims The dimensions and the number of them to use.
	 * @return The allocated multi-dimensional array.
	 * @throws NegativeArraySizeException If an allocated array would be
	 * of a negative size.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/03
	 */
	public static Object multiANewArray(Class<?> __type, int __skip,
		int[] __dims)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__type == null || __dims == null)
			throw new NullPointerException("NARG");
		
		// Count the number of dimensions represented in the type
		String typename = __type.getName();
		int typeDims = 0;
		while (typename.charAt(typeDims) == '[')
			typeDims++;
		
		// {@squirreljme.error ZZ0e Negative number of dimensions available
		// or input type is not correct for the array type.}
		int dims = __dims.length - __skip;
		if (__skip < 0 || dims <= 0 || typeDims < dims)
			throw new IllegalArgumentException("ZZ0e");
		
		// Allocate array of this type
		int numElem = __dims[__skip];
		Object rv = ObjectShelf.arrayNew(
			TypeShelf.classToType(__type), numElem);
		
		// Need to determine the type for setting
		int type = ArrayUtils.arrayType(rv);
		
		// The array has more dimensions which must be set
		if (dims > 1)
		{
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
			// multi-dimensional array.}
			catch (ClassNotFoundException e)
			{
				throw new Error("ZZ0f", e);
			}
			
			// Skipping ahead by one
			int nxskip = __skip + 1;
			
			// Allocate
			for (int i = 0; i < numelem; i++)
				ArrayUtils.arraySet(type, rv, i,
					ArrayUtils.multiANewArray(subtype, nxskip, __dims));
		}
		
		return (Object)rv;
	}
}








|


|

|


|



503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
			// multi-dimensional array.}
			catch (ClassNotFoundException e)
			{
				throw new Error("ZZ0f", e);
			}
			
			// Skipping ahead by one
			int nextSkip = __skip + 1;
			
			// Allocate
			for (int i = 0; i < numElem; i++)
				ArrayUtils.arraySet(type, rv, i,
					ArrayUtils.multiANewArray(subtype, nextSkip, __dims));
		}
		
		return rv;
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/lang/ClassData.java.

21
22
23
24
25
26
27

28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118

119
120
121
 *
 * @since 2018/12/04
 */
@Deprecated
public abstract class ClassData
{
	/** The version of the class data. */

	public final byte version;
	
	/**
	 * Initializes the base class data.
	 *
	 * @param __v The version.
	 * @since 2018/12/04
	 */

	public ClassData(int __v)
	{
		this.version = (byte)__v;
	}
	
	/**
	 * Returns the binary name.
	 *
	 * @return The binary name.
	 * @since 2018/12/04
	 */

	public abstract String binaryName();
	
	/**
	 * Returns the component of the array.
	 *
	 * @return The array component.
	 * @since 2018/12/04
	 */

	public abstract Class<?> component();
	
	/**
	 * Returns the flags for the default constructor.
	 *
	 * @return The default constructor flags.
	 * @since 2018/12/04
	 */

	public abstract int defaultConstructorFlags();
	
	/**
	 * Returns the method which is used for the default constructor.
	 *
	 * @return The static method for the default constructor.
	 * @since 2018/12/04
	 */

	public abstract StaticMethod defaultConstructorMethod();
	
	/**
	 * Returns the number of dimensions for the array.
	 *
	 * @return The dimension count.
	 * @since 2018/12/04
	 */

	public abstract int dimensions();
	
	/**
	 * Method which returns the enumeration values, if an enum.
	 *
	 * @return The enumeration values getter.
	 * @since 2018/12/08
	 */

	public abstract StaticMethod enumValues();
	
	/**
	 * Returns the class flags.
	 *
	 * @return The class flags.
	 * @since 2018/12/04
	 */

	public abstract int flags();
	
	/**
	 * Returns the JAR this class is in.
	 *
	 * @return The JAR this class is in.
	 * @since 2018/12/04
	 */

	public abstract String inJar();
	
	/**
	 * Returns the the interfaces this class implements.
	 *
	 * @return The interface classes.
	 * @since 2018/12/04
	 */

	public abstract Class<?>[] interfaceClasses();
	
	/**
	 * Returns the super class.
	 *
	 * @return The super class.
	 * @since 2018/12/04
	 */

	public abstract Class<?> superClass();
}








>








>











>








>








>








>








>








>








>








>








>








>



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 *
 * @since 2018/12/04
 */
@Deprecated
public abstract class ClassData
{
	/** The version of the class data. */
	@Deprecated
	public final byte version;
	
	/**
	 * Initializes the base class data.
	 *
	 * @param __v The version.
	 * @since 2018/12/04
	 */
	@Deprecated
	public ClassData(int __v)
	{
		this.version = (byte)__v;
	}
	
	/**
	 * Returns the binary name.
	 *
	 * @return The binary name.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract String binaryName();
	
	/**
	 * Returns the component of the array.
	 *
	 * @return The array component.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract Class<?> component();
	
	/**
	 * Returns the flags for the default constructor.
	 *
	 * @return The default constructor flags.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract int defaultConstructorFlags();
	
	/**
	 * Returns the method which is used for the default constructor.
	 *
	 * @return The static method for the default constructor.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract StaticMethod defaultConstructorMethod();
	
	/**
	 * Returns the number of dimensions for the array.
	 *
	 * @return The dimension count.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract int dimensions();
	
	/**
	 * Method which returns the enumeration values, if an enum.
	 *
	 * @return The enumeration values getter.
	 * @since 2018/12/08
	 */
	@Deprecated
	public abstract StaticMethod enumValues();
	
	/**
	 * Returns the class flags.
	 *
	 * @return The class flags.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract int flags();
	
	/**
	 * Returns the JAR this class is in.
	 *
	 * @return The JAR this class is in.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract String inJar();
	
	/**
	 * Returns the the interfaces this class implements.
	 *
	 * @return The interface classes.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract Class<?>[] interfaceClasses();
	
	/**
	 * Returns the super class.
	 *
	 * @return The super class.
	 * @since 2018/12/04
	 */
	@Deprecated
	public abstract Class<?> superClass();
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/lang/ClassDataV1.java.

66
67
68
69
70
71
72

73
74
75
76
77
78
79
	 * @param __flags Class flags.
	 * @param __dcf Default constructor flag.
	 * @param __dcm Default constructor method.
	 * @param __efm The method used to fill enumerations.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/04
	 */

	public ClassDataV1(int __csi, String __bn, Class<?> __sc, Class<?>[] __ic,
		Class<?> __ct, String __ij, int __flags, int __dcf, StaticMethod __dcm,
		StaticMethod __efm)
		throws NullPointerException
	{
		super(1);
		







>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
	 * @param __flags Class flags.
	 * @param __dcf Default constructor flag.
	 * @param __dcm Default constructor method.
	 * @param __efm The method used to fill enumerations.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/04
	 */
	@Deprecated
	public ClassDataV1(int __csi, String __bn, Class<?> __sc, Class<?>[] __ic,
		Class<?> __ct, String __ij, int __flags, int __dcf, StaticMethod __dcm,
		StaticMethod __efm)
		throws NullPointerException
	{
		super(1);
		

Deleted modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/lang/GuestDepth.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.lang;

/**
 * This class returns the current guest depth.
 *
 * @since 2018/11/04
 */
public final class GuestDepth
{
	/** The calculated guest depth. */
	private static int _DEPTH =
		-1;
	
	/**
	 * Not used.
	 *
	 * @since 2018/11/04
	 */
	private GuestDepth()
	{
	}
	
	/**
	 * The guest depth for the virtual machine.
	 *
	 * @return The guest depth for the virtual machine.
	 * @since 2018/11/04
	 */
	public static final int guestDepth()
	{
		// Pre-cached depth?
		int rv = GuestDepth._DEPTH;
		if (rv >= 0)
			return rv;
		
		// System property will indicate the number of guests in the VM
		try
		{
			String prop = System.getProperty("cc.squirreljme.guests");
			if (prop == null)
				rv = 0;
			else
				rv = Integer.parseInt(prop);
		}
		
		// Cannot get property so it cannot be known
		catch (SecurityException|NumberFormatException e)
		{
			rv = 0;
		} 
		
		// Cache it for later
		GuestDepth._DEPTH = rv;
		return rv;
	}
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































Added modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/lang/LineEndingUtils.java.













































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.lang;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.LineEndingType;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

/**
 * Utilities for line endings.
 *
 * @see LineEndingType
 * @since 2020/06/11
 */
public final class LineEndingUtils
{
	/**
	 * Not used.
	 *
	 * @since 2020/06/11
	 */
	private LineEndingUtils()
	{
	}
	
	/**
	 * Appends the default line ending to the given output.
	 *
	 * @param __out Where to write to.
	 * @throws IOException On write errors.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static void append(Appendable __out)
		throws IOException, NullPointerException
	{
		LineEndingUtils.append(__out, RuntimeShelf.lineEnding());
	}
	
	/**
	 * Appends the line ending to the given output.
	 *
	 * @param __out Where to write to.
	 * @param __type The {@link LineEndingType}.
	 * @throws IOException On write errors.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static void append(Appendable __out, int __type)
		throws IOException, NullPointerException
	{
		for (int i = 0;; i++)
		{
			char c = LineEndingUtils.toChar(__type, i);
			if (c == 0)
				return;
			
			__out.append(c);
		}
	}
	
	/**
	 * Appends the default end of line, but wraps the exception so that it is
	 * not thrown and instead returns a boolean if one was generated.
	 *
	 * @param __out The appendable to write to.
	 * @return If an {@link IOException} was thrown.
	 * @since 2020/06/11
	 */
	public static boolean appendWrap(Appendable __out)
		throws NullPointerException
	{
		return LineEndingUtils.appendWrap(__out, RuntimeShelf.lineEnding());
	}
	
	/**
	 * Appends the end of line, but wraps the exception so that it is not
	 * thrown and instead returns a boolean if one was generated.
	 *
	 * @param __out The appendable to write to.
	 * @param __type The {@link LineEndingType}.
	 * @return If an {@link IOException} was thrown.
	 * @since 2020/06/11
	 */
	public static boolean appendWrap(Appendable __out, int __type)
		throws NullPointerException
	{
		try
		{
			LineEndingUtils.append(__out, __type);
			return false;
		}
		catch (IOException ignored)
		{
			return true;
		}
	}
	
	/**
	 * Returns the character sequence used for the line ending.
	 *
	 * @param __type The {@link LineEndingType}.
	 * @param __index The character index to return.
	 * @return The resultant character or {@code 0} if none are left.
	 * @throws IllegalArgumentException If the line ending type is not valid.
	 * @since 2020/06/11
	 */
	public static char toChar(int __type, int __index)
		throws IllegalArgumentException
	{
		// No sequence is ever within this range
		if (__index < 0 || __index > 1)
			return 0;
		
		switch (__type)
		{
			case LineEndingType.CR:
				return (__index == 0 ? '\r' : 0);
			
			case LineEndingType.LF:
				return (__index == 0 ? '\n' : 0);
				
			case LineEndingType.CRLF:
				return (__index == 0 ? '\r' : '\n');
			
			// {@squirreljme.error ZZ03 Unknown line ending type. (Type)}
			default:
				throw new IllegalArgumentException("ZZ03 " + __type);
		}
	}
	
	/**
	 * Returns the string for the given line ending sequence.
	 *
	 * @param __type The {@link LineEndingType}.
	 * @return The string representing the end of line sequence.
	 * @throws IllegalArgumentException If the line ending type is not valid.
	 * @since 2020/06/11
	 */
	public static String toString(int __type)
		throws IllegalArgumentException
	{
		switch (__type)
		{
			case LineEndingType.CR:		return "\r";
			case LineEndingType.LF:		return "\n";
			case LineEndingType.CRLF:	return "\r\n";
			
			// {@squirreljme.error ZZ29 Unknown line ending type. (Type)}
			default:
				throw new IllegalArgumentException("ZZ29 " + __type);
		}
	}
	
	/**
	 * Converts the string to the given type.
	 *
	 * @param __string The string to convert.
	 * @return The type from the string.
	 * @throws IllegalArgumentException If the string is not valid.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/13
	 */
	public static int toType(String __string)
		throws IllegalArgumentException, NullPointerException
	{
		if (__string == null)
			throw new NullPointerException("NARG");
		
		switch (__string)
		{
			case "\r":		return LineEndingType.CR;
			case "\n":		return LineEndingType.LF;
			case "\r\n":	return LineEndingType.CRLF;
			
				// {@squirreljme.error ZZ3w Unknown line ending string.}
			default:
				throw new IllegalArgumentException("ZZ3w " + __string);
		}
	}
	
	/**
	 * Writes the default line ending to the given output.
	 *
	 * @param __out Where to write to.
	 * @throws IOException On write errors.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static void write(OutputStream __out)
		throws IOException, NullPointerException
	{
		LineEndingUtils.write(__out, RuntimeShelf.lineEnding());
	}
	
	/**
	 * Writes the line ending to the given output.
	 *
	 * @param __out Where to write to.
	 * @param __type The {@link LineEndingType}.
	 * @throws IOException On write errors.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static void write(OutputStream __out, int __type)
		throws IOException, NullPointerException
	{
		for (int i = 0;; i++)
		{
			char c = LineEndingUtils.toChar(__type, i);
			if (c == 0)
				return;
			
			__out.write(c);
		}
	}
	
	/**
	 * Writes the default line ending to the given output.
	 *
	 * @param __out Where to write to.
	 * @throws IOException On write errors.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static void write(Writer __out)
		throws IOException, NullPointerException
	{
		LineEndingUtils.write(__out, RuntimeShelf.lineEnding());
	}
	
	/**
	 * Writes the line ending to the given output.
	 *
	 * @param __out Where to write to.
	 * @param __type The {@link LineEndingType}.
	 * @throws IOException On write errors.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/11
	 */
	public static void write(Writer __out, int __type)
		throws IOException, NullPointerException
	{
		for (int i = 0;; i++)
		{
			char c = LineEndingUtils.toChar(__type, i);
			if (c == 0)
				return;
			
			__out.write(c);
		}
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/lang/UncaughtExceptionHandler.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22




23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42


43
44
45
46
47
48
49

50
51
52


53








// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.lang;

import java.io.PrintStream;

/**
 * This method is called when there has been an uncaught exception being
 * handled.
 *
 * @since 2018/10/29
 */
public final class UncaughtExceptionHandler
{




	/**
	 * Not used.
	 *
	 * @since 2018/10/29
	 */
	private UncaughtExceptionHandler()
	{
	}
	
	/**
	 * Performs some default handling for exceptions that were not caught
	 * anywhere.
	 *
	 * @param __t The throwable to handle.
	 * @since 2018/10/29
	 */
	public static final void handle(Throwable __t)
	{
		// Make a nice and big banner on it
		PrintStream out = System.err;


		out.println("****************************************************");
		out.print("UNCAUGHT EXCEPTION IN THREAD: ");
		out.println(Thread.currentThread());
		
		if (__t != null)
			__t.printStackTrace(out);
		

		out.println("****************************************************");
	}
}























|









>
>
>
>
















|

|
|
>
>
|
|
<
|
<
|
|
>
|
|
|
>
>
|
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.lang;

import cc.squirreljme.runtime.cldc.debug.Debugging;

/**
 * This method is called when there has been an uncaught exception being
 * handled.
 *
 * @since 2018/10/29
 */
public final class UncaughtExceptionHandler
{
	/** Exit status for when this is hit. */
	private static final int _EXIT_STATUS =
		62;
	
	/**
	 * Not used.
	 *
	 * @since 2018/10/29
	 */
	private UncaughtExceptionHandler()
	{
	}
	
	/**
	 * Performs some default handling for exceptions that were not caught
	 * anywhere.
	 *
	 * @param __t The throwable to handle.
	 * @since 2018/10/29
	 */
	public static void handle(Throwable __t)
	{
		// Make sure this does not cause the thread to die again
		try
		{
			Debugging.debugNote(
				"*****************************************");
			Debugging.debugNote("UNCAUGHT EXCEPTION IN THREAD: ");

			

			__t.printStackTrace();
			
			Debugging.debugNote(
				"*****************************************");
		}
		
		// Stop this from failing
		catch (Throwable e)
		{
			// Emit a message to indicate the reason
			Debugging.debugNote("UNCAUGHT DOUBLE-EXCEPTION?");
			Debugging.debugNote("Class: %s", e.getClass().getName());
			Debugging.debugNote("Message: %s", e.getMessage());
		}
	}
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/ref/PrimitiveReference.java.

11
12
13
14
15
16
17

18
19
20
21
package cc.squirreljme.runtime.cldc.ref;

/**
 * Represents an internal primitive reference.
 *
 * @since 2018/09/23
 */

public interface PrimitiveReference
{
}








>




11
12
13
14
15
16
17
18
19
20
21
22
package cc.squirreljme.runtime.cldc.ref;

/**
 * Represents an internal primitive reference.
 *
 * @since 2018/09/23
 */
@Deprecated
public interface PrimitiveReference
{
}

Changes to modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/ref/PrimitiveWeakReference.java.

12
13
14
15
16
17
18

19
20
21
22
23

/**
 * This represents a primitive weak reference which should be garbage
 * collected when it does not point to anything.
 *
 * @since 2018/09/23
 */

public interface PrimitiveWeakReference
	extends PrimitiveReference
{
}








>





12
13
14
15
16
17
18
19
20
21
22
23
24

/**
 * This represents a primitive weak reference which should be garbage
 * collected when it does not point to anything.
 *
 * @since 2018/09/23
 */
@Deprecated
public interface PrimitiveWeakReference
	extends PrimitiveReference
{
}

Changes to modules/cldc-compact/src/main/java/java/io/ByteArrayInputStream.java.

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
				read = count - pos;
			
			// Do not exceed this
			if (len < read)
				read = len;
			
			// Copy bytes
			for (int i = 0; i < len; i++)
				__b[i] = buf[pos++];
			
			// Store new position
			this.pos = pos;
			
			if (read == 0)
				return (pos >= count ? -1 : 0);
			return read;







|
|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
				read = count - pos;
			
			// Do not exceed this
			if (len < read)
				read = len;
			
			// Copy bytes
			System.arraycopy(buf, pos, __b, 0, read);
			pos += read;
			
			// Store new position
			this.pos = pos;
			
			if (read == 0)
				return (pos >= count ? -1 : 0);
			return read;
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
				read = count - pos;
			
			// Do not exceed this
			if (__l < read)
				read = __l;
			
			// Copy bytes
			for (int i = 0; i < read; i++)
				__b[__o++] = buf[pos++];
			
			// Store new position
			this.pos = pos;
			
			if (read == 0)
				return (pos >= count ? -1 : 0);
			return read;







|
|







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
				read = count - pos;
			
			// Do not exceed this
			if (__l < read)
				read = __l;
			
			// Copy bytes
			System.arraycopy(buf, pos, __b, __o, read);
			pos += read;
			
			// Store new position
			this.pos = pos;
			
			if (read == 0)
				return (pos >= count ? -1 : 0);
			return read;

Changes to modules/cldc-compact/src/main/java/java/io/InputStream.java.

40
41
42
43
44
45
46

47
48
49
50
51
52
53
	 * Returns the number of bytes which can be read from the stream without
	 * blocking.
	 *
	 * @return The number of bytes which can be read.
	 * @throws IOException On read errors.
	 * @since 2019/01/20
	 */

	@ProgrammerTip("The base implementation always returns 0.")
	public int available()
		throws IOException
	{
		return 0;
	}
	







>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	 * Returns the number of bytes which can be read from the stream without
	 * blocking.
	 *
	 * @return The number of bytes which can be read.
	 * @throws IOException On read errors.
	 * @since 2019/01/20
	 */
	@SuppressWarnings("RedundantThrows")
	@ProgrammerTip("The base implementation always returns 0.")
	public int available()
		throws IOException
	{
		return 0;
	}
	

Changes to modules/cldc-compact/src/main/java/java/io/PrintStream.java.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15

16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.io;


import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.io.CodecFactory;
import cc.squirreljme.runtime.cldc.io.Encoder;

import java.util.Formatter;

/**
 * This class is used to print translated and formatted text.
 *
 * No {@link IOException} is ever thrown by any of these methods, they are
 * handled and provided as an error flag which can be obtained. If












>



>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.io;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.io.CodecFactory;
import cc.squirreljme.runtime.cldc.io.Encoder;
import cc.squirreljme.runtime.cldc.lang.LineEndingUtils;
import java.util.Formatter;

/**
 * This class is used to print translated and formatted text.
 *
 * No {@link IOException} is ever thrown by any of these methods, they are
 * handled and provided as an error flag which can be obtained. If
44
45
46
47
48
49
50








51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
	 * most cases this class will either not be used or will be outputting just
	 * text to the console. So since most consoles and most text will likely
	 * be 80 columns or less, this buffer size is enough to fit such a terminal
	 * but also give some extra room in the event of overflow.
	 */
	private static final int _BUFFER_SIZE =
		96;








	
	/** Threshold before a forced flush. */
	private static final int _THRESHOLD =
		90;
	
	/** The newline sequence. */
	private static final String _NEWLINE;
	
	/** The stream to write bytes to. */
	private final OutputStream _out;
	
	/** Is auto-flushing to be used? */
	private final boolean _autoflush;
	
	/** The encoder used to encode chars to bytes. */
	private final Encoder _encoder;
	
	/** Mini-byte buffer for encoded characters. */
	private final byte[] _minienc =
		new byte[8];
	
	/** The internal buffer. */
	private final byte[] _buf =
		new byte[PrintStream._BUFFER_SIZE];
	
	/** The position the buffer is at. */
	private int _bat;
	
	/** Error state? */
	private boolean _inerror;
	
	/**
	 * Cache the line separator which is derived from the system properties.
	 *
	 * @since 2018/09/18
	 */
	static
	{
		String nl;
		try
		{
			nl = System.getProperty("line.separator");
		}
		catch (SecurityException e)
		{
			nl = "\n";
		}
		
		_NEWLINE = nl;
	}
	
	/**
	 * Writes to the given stream using the default encoding and with no
	 * auto flushing.
	 *
	 * @param __out The stream to write to.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/17







>
>
>
>
>
>
>
>



<
|
<
<












|











<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

64


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88




















89
90
91
92
93
94
95
	 * most cases this class will either not be used or will be outputting just
	 * text to the console. So since most consoles and most text will likely
	 * be 80 columns or less, this buffer size is enough to fit such a terminal
	 * but also give some extra room in the event of overflow.
	 */
	private static final int _BUFFER_SIZE =
		96;
	
	/** If the buffer gets too big we have to drop bytes. */
	private static final int _EMERGENCY_HALT =
		95;
	
	/** The maximum number of byte that might be encoded at once. */
	private static final int _MAX_ENCODE_BYTES =
		8;
	
	/** Threshold before a forced flush. */
	private static final int _THRESHOLD =

		88;


	
	/** The stream to write bytes to. */
	private final OutputStream _out;
	
	/** Is auto-flushing to be used? */
	private final boolean _autoflush;
	
	/** The encoder used to encode chars to bytes. */
	private final Encoder _encoder;
	
	/** Mini-byte buffer for encoded characters. */
	private final byte[] _minienc =
		new byte[PrintStream._MAX_ENCODE_BYTES];
	
	/** The internal buffer. */
	private final byte[] _buf =
		new byte[PrintStream._BUFFER_SIZE];
	
	/** The position the buffer is at. */
	private int _bat;
	
	/** Error state? */
	private boolean _inerror;
	




















	/**
	 * Writes to the given stream using the default encoding and with no
	 * auto flushing.
	 *
	 * @param __out The stream to write to.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/17
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
			return;
		
		// Write individual bytes and detect any exceptions
		OutputStream out = this._out;
		boolean oopsie = false;
		byte[] buf = this._buf;
		int bop = 0;
		for (bop = 0; bop < bat; bop++)
			try
			{
				out.write(buf[bop]);
			}
			catch (InterruptedIOException e)
			{
				// Just stop handling here and interrupt the thread







|







654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
			return;
		
		// Write individual bytes and detect any exceptions
		OutputStream out = this._out;
		boolean oopsie = false;
		byte[] buf = this._buf;
		int bop = 0;
		for (; bop < bat; bop++)
			try
			{
				out.write(buf[bop]);
			}
			catch (InterruptedIOException e)
			{
				// Just stop handling here and interrupt the thread
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
	/**
	 * Prints the specified string.
	 *
	 * @param __s The string to print, if {@code null} then {@code "null"} is
	 * printed.
	 * @since 2018/09/20
	 */
	private final void __print(String __s)
	{
		synchronized (this)
		{
			// Print null explicitely
			if (__s == null)
				__s = "null";
			
			for (int i = 0, n = __s.length(); i < n; i++)
				this.__writeChar(__s.charAt(i));
		}
	}







|



|







696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
	/**
	 * Prints the specified string.
	 *
	 * @param __s The string to print, if {@code null} then {@code "null"} is
	 * printed.
	 * @since 2018/09/20
	 */
	private void __print(String __s)
	{
		synchronized (this)
		{
			// Print null explicitly
			if (__s == null)
				__s = "null";
			
			for (int i = 0, n = __s.length(); i < n; i++)
				this.__writeChar(__s.charAt(i));
		}
	}
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779


780
781

782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822



823
824
825
826
827
828
829
830
831
832
833
834
835



836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
		
		return this;
	}
	
	/**
	 * Prints the end of line sequence that is used for the current platform.
	 *
	 * @return The end of line sequence.
	 * @since 2018/09/21
	 */
	private final void __println()
	{
		synchronized (this)
		{
			// If the newline character has not yet been set, use a fallback
			String nl = PrintStream._NEWLINE;
			if (nl == null)
				nl = "\n";
			
			// Write the ending


			for (int i = 0, n = nl.length(); i < n; i++)
				this.__writeChar(nl.charAt(i));

			
			// Flush the stream after every line printed, in the event the
			// system does not use a UNIX newline
			if (this._autoflush)
				this.flush();
		}
	}
	
	/**
	 * Writes multiple bytes to the output.
	 *
	 * @param __b The bytes to write.
	 * @param __o The offset.
	 * @param __l The length.
	 * @throws IndexOutOfBoundsException If the offset and/or length are
	 * negative or exceed the array bounds.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/06/21
	 */
	private final void __writeBytes(byte[] __b, int __o, int __l)
		throws IndexOutOfBoundsException, NullPointerException
	{
		if (__b == null)
			throw new NullPointerException("NARG");
		if (__o < 0 || __l < 0 || (__o + __l) > __b.length)
			throw new IndexOutOfBoundsException("IOOB");
		
		// Our current buffer state
		byte[] buf = this._buf;
		int bat = this._bat;
		
		// Auto-flush on any newlines?
		boolean autoflush = this._autoflush;
		
		// Copy bytes into the buffer
		boolean flush = false;
		for (int i = 0; i < __l; i++)
		{
			byte b = __b[i];
			
			// Fill into buffer



			buf[bat++] = b;
			
			// Auto-flushing on newline?
			if (autoflush && b == '\n')
				flush = true;
			
			// Force a flush?
			if (bat >= PrintStream._THRESHOLD)
			{
				// Store at location, flush then reload it
				this._bat = bat;
				this.__flush();
				bat = this._bat;



			}
		}
		
		// Store changes
		this._bat = bat;
		
		// Perform a flush?
		if (flush || bat >= PrintStream._THRESHOLD)
			this.__flush();
	}
	
	/**
	 * Writes a single character to the output, encoding it as required.
	 *
	 * @param __c The character to write.
	 * @since 2018/09/19
	 */
	private final void __writeChar(char __c)
	{
		// Encode bytes into the array
		byte[] minienc = this._minienc;
		int wc = this._encoder.encode(__c, minienc, 0, minienc.length);
		
		// {@squirreljme.error ZZ0q Did not expect the buffer to be out of
		// room.}
		if (wc < 0)
			throw new Error("ZZ0q");
		
		// Write them into the buffer
		this.__writeBytes(minienc, 0, wc);
	}
}








<


|



|
|
<
|
|
|
>
>
|
|
>



















|


















|

|
>
>
>
|












>
>
>

















|


|
|


|
|



|



747
748
749
750
751
752
753

754
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
		
		return this;
	}
	
	/**
	 * Prints the end of line sequence that is used for the current platform.
	 *

	 * @since 2018/09/21
	 */
	private void __println()
	{
		synchronized (this)
		{
			// Write end of line sequence
			int lineType = RuntimeShelf.lineEnding();

			for (int i = 0;; i++)
			{
				char c = LineEndingUtils.toChar(lineType, i);
				if (c == 0)
					break;
				
				this.__writeChar(c);
			}
			
			// Flush the stream after every line printed, in the event the
			// system does not use a UNIX newline
			if (this._autoflush)
				this.flush();
		}
	}
	
	/**
	 * Writes multiple bytes to the output.
	 *
	 * @param __b The bytes to write.
	 * @param __o The offset.
	 * @param __l The length.
	 * @throws IndexOutOfBoundsException If the offset and/or length are
	 * negative or exceed the array bounds.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/06/21
	 */
	private void __writeBytes(byte[] __b, int __o, int __l)
		throws IndexOutOfBoundsException, NullPointerException
	{
		if (__b == null)
			throw new NullPointerException("NARG");
		if (__o < 0 || __l < 0 || (__o + __l) > __b.length)
			throw new IndexOutOfBoundsException("IOOB");
		
		// Our current buffer state
		byte[] buf = this._buf;
		int bat = this._bat;
		
		// Auto-flush on any newlines?
		boolean autoflush = this._autoflush;
		
		// Copy bytes into the buffer
		boolean flush = false;
		for (int i = 0; i < __l; i++)
		{
			byte b = __b[__o + i];
			
			// Fill into buffer as long as we can actually fit bytes here,
			// if this case ever happens we just for the most part drop the
			// bytes since there is no room to store them anymore
			if (bat < PrintStream._EMERGENCY_HALT)
				buf[bat++] = b;
			
			// Auto-flushing on newline?
			if (autoflush && b == '\n')
				flush = true;
			
			// Force a flush?
			if (bat >= PrintStream._THRESHOLD)
			{
				// Store at location, flush then reload it
				this._bat = bat;
				this.__flush();
				bat = this._bat;
				
				// Clear the flush flag as we already flushed once
				flush = false;
			}
		}
		
		// Store changes
		this._bat = bat;
		
		// Perform a flush?
		if (flush || bat >= PrintStream._THRESHOLD)
			this.__flush();
	}
	
	/**
	 * Writes a single character to the output, encoding it as required.
	 *
	 * @param __c The character to write.
	 * @since 2018/09/19
	 */
	private void __writeChar(char __c)
	{
		// Encode bytes into the array
		byte[] encBytes = this._minienc;
		int wc = this._encoder.encode(__c, encBytes, 0, encBytes.length);
		
		// {@squirreljme.error ZZ0q Did not expect the buffer to be out of
		// room or be too small.}
		if (wc < 0 || wc > encBytes.length)
			throw new Error("ZZ0q");
		
		// Write them into the buffer
		this.__writeBytes(encBytes, 0, wc);
	}
}

Added modules/cldc-compact/src/main/java/java/io/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This package contains the standard Java input/output classes.
 *
 * @since 2020/06/16
 */

package java.io;

Changes to modules/cldc-compact/src/main/java/java/lang/Boolean.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.asm.ObjectAccess;

/**
 * This is a boxed boolean value.
 *
 * @since 2018/12/07
 */
public final class Boolean
	implements Comparable<Boolean>
{
	/** The false value. */
	public static final Boolean FALSE =
		new Boolean(false);
	
	/** The true value. */
	public static final Boolean TRUE =
		new Boolean(true);
	
	/** The class representing the primitive type. */
	public static final Class<Boolean> TYPE =
		ObjectAccess.<Boolean>classByNameType("boolean");
	
	/** The value of this boolean. */
	private final boolean _value;
	
	/**
	 * Initializes the boolean with the given value.
	 *












|



















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.TypeShelf;

/**
 * This is a boxed boolean value.
 *
 * @since 2018/12/07
 */
public final class Boolean
	implements Comparable<Boolean>
{
	/** The false value. */
	public static final Boolean FALSE =
		new Boolean(false);
	
	/** The true value. */
	public static final Boolean TRUE =
		new Boolean(true);
	
	/** The class representing the primitive type. */
	public static final Class<Boolean> TYPE =
		TypeShelf.<Boolean>typeToClass(TypeShelf.typeOfBoolean());
	
	/** The value of this boolean. */
	private final boolean _value;
	
	/**
	 * Initializes the boolean with the given value.
	 *

Changes to modules/cldc-compact/src/main/java/java/lang/Byte.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This represents a boxed byte value.
 *
 * @since 2018/12/07












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.TypeShelf;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This represents a boxed byte value.
 *
 * @since 2018/12/07
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	
	/** The number of bits in a byte. */
	public static final int SIZE =
		8;
	
	/** The class representing the primitive type. */
	public static final Class<Byte> TYPE =
		ObjectAccess.<Byte>classByNameType("byte");
	
	/** The value of the byte. */
	private final byte _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	
	/** The number of bits in a byte. */
	public static final int SIZE =
		8;
	
	/** The class representing the primitive type. */
	public static final Class<Byte> TYPE =
		TypeShelf.<Byte>typeToClass(TypeShelf.typeOfByte());
	
	/** The value of the byte. */
	private final byte _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	

Changes to modules/cldc-compact/src/main/java/java/lang/Character.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import cc.squirreljme.runtime.cldc.i18n.DefaultLocale;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This is a boxed representation of {@link char}.
 *












|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.i18n.DefaultLocale;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This is a boxed representation of {@link char}.
 *
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
	
	/** The number of bits used to represent a character. */
	public static final int SIZE =
		16;
	
	/** The class representing the primitive type. */
	public static final Class<Character> TYPE =
		ObjectAccess.<Character>classByNameType("char");
	
	/** The character value. */
	private final char _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	







|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
	
	/** The number of bits used to represent a character. */
	public static final int SIZE =
		16;
	
	/** The class representing the primitive type. */
	public static final Class<Character> TYPE =
		TypeShelf.<Character>typeToClass(TypeShelf.typeOfCharacter());
	
	/** The character value. */
	private final char _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	 * @return The converted character.
	 * @since 2018/10/13
	 */
	@ImplementationNote("CLDC only supports Latin-1 and this method has no " +
		"locale support.")
	public static char toLowerCase(char __c)
	{
		return DefaultLocale.NO_LOCALE.toLowerCase(__c);
	}
	
	/**
	 * Returns a string representation of the given character.
	 *
	 * @param __c The character to represent as a string.
	 * @return The string representation of that character.







|







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	 * @return The converted character.
	 * @since 2018/10/13
	 */
	@ImplementationNote("CLDC only supports Latin-1 and this method has no " +
		"locale support.")
	public static char toLowerCase(char __c)
	{
		return DefaultLocale.noLocale().toLowerCase(__c);
	}
	
	/**
	 * Returns a string representation of the given character.
	 *
	 * @param __c The character to represent as a string.
	 * @return The string representation of that character.
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
	 * @return The converted character.
	 * @since 2018/10/13
	 */
	@ImplementationNote("CLDC only supports Latin-1 and this method has no " +
		"locale support.")
	public static char toUpperCase(char __c)
	{
		return DefaultLocale.NO_LOCALE.toUpperCase(__c);
	}
	
	/**
	 * Boxes the specified value.
	 *
	 * @param __v The value to box.
	 * @return The resulting character value.







|







327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
	 * @return The converted character.
	 * @since 2018/10/13
	 */
	@ImplementationNote("CLDC only supports Latin-1 and this method has no " +
		"locale support.")
	public static char toUpperCase(char __c)
	{
		return DefaultLocale.noLocale().toUpperCase(__c);
	}
	
	/**
	 * Boxes the specified value.
	 *
	 * @param __v The value to box.
	 * @return The resulting character value.

Changes to modules/cldc-compact/src/main/java/java/lang/Class.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import cc.squirreljme.runtime.cldc.asm.StaticMethod;
import cc.squirreljme.runtime.cldc.asm.SuiteAccess;
import cc.squirreljme.runtime.cldc.io.ResourceInputStream;
import cc.squirreljme.runtime.cldc.lang.ClassData;
import cc.squirreljme.runtime.cldc.lang.ClassFlag;
import java.io.InputStream;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This class is the in-language representation of a Java class, the CLDC
 * allows for minimal reflection via {@link Class#forName(String)} and
 * {@link Class#newInstance()}.
 *
 * @since 2018/12/08
 */
public final class Class<T>
{
	/** This is the prefix that is used for assertion checks. */
	private static final String _ASSERTION_PREFIX =
		"cc.squirreljme.runtime.noassert.";
	
	/** The class data storage. */
	final ClassData _data;
	
	/** Has the assertion status been checked already? */
	private volatile boolean _checkedassert;
	
	/** Is this class being asserted? */
	private volatile boolean _useassert;
	
	/** The display name of the class. */
	private Reference<String> _name;
	
	/** String representation of class. */
	private Reference<String> _string;
	
	/**
	 * Initializes the class with the class data.
	 *
	 * @param __d The data to use.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/04
	 */
	private Class(ClassData __d)
		throws NullPointerException
	{
		if (__d == null)
			throw new NullPointerException("NARG");
		
		this._data = __d;
	}
	
	/**
	 * This checks whether the specified input class extends this class or
	 * implements an interface and then returns this class object which is
	 * "cast" to the specified type. Note that this does not change the
	 * returned value.












|
|
|
|
|
|

<
<














|
|


|


|

<
<
<
<
<
<

|

|

|

|


|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42






43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.JarPackageShelf;
import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.jvm.mle.brackets.JarPackageBracket;
import cc.squirreljme.jvm.mle.brackets.TypeBracket;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.io.InputStream;



/**
 * This class is the in-language representation of a Java class, the CLDC
 * allows for minimal reflection via {@link Class#forName(String)} and
 * {@link Class#newInstance()}.
 *
 * @since 2018/12/08
 */
public final class Class<T>
{
	/** This is the prefix that is used for assertion checks. */
	private static final String _ASSERTION_PREFIX =
		"cc.squirreljme.runtime.noassert.";
	
	/** The type shelf for this class. */
	private final TypeBracket _type;
	
	/** Has the assertion status been checked already? */
	private volatile boolean _checkedAssert;
	
	/** Is this class being asserted? */
	private volatile boolean _useAssert;
	






	/**
	 * Initializes the class reference holder.
	 *
	 * @param __type The type shelf to set this as.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/07
	 */
	private Class(TypeBracket __type)
		throws NullPointerException
	{
		if (__type == null)
			throw new NullPointerException("NARG");
		
		this._type = __type;
	}
	
	/**
	 * This checks whether the specified input class extends this class or
	 * implements an interface and then returns this class object which is
	 * "cast" to the specified type. Note that this does not change the
	 * returned value.
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
	@SuppressWarnings({"unchecked"})
	public <U> Class<? extends U> asSubclass(Class<U> __cl)
		throws ClassCastException, NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ0v The specifed class is not a sub-class
		// of this class. (The class being checked; The current class)}
		if (!this.isAssignableFrom(__cl))
			throw new ClassCastException(
				String.format("ZZ0v %s %s", __cl, this));
		
		return (Class<? extends U>)this;
	}
	
	/**
	 * Casts the object to this class, checking it.
	 *







|


|
<







75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
	@SuppressWarnings({"unchecked"})
	public <U> Class<? extends U> asSubclass(Class<U> __cl)
		throws ClassCastException, NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ0v The specified class is not a sub-class
		// of this class. (The class being checked; The current class)}
		if (!this.isAssignableFrom(__cl))
			throw new ClassCastException("ZZ0v " + __cl + " " + this);

		
		return (Class<? extends U>)this;
	}
	
	/**
	 * Casts the object to this class, checking it.
	 *
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
	 * @return In SquirrelJME this returns by default {@code true}, otherwise
	 * this may return {@code false} if they are disabled for a class.
	 * @since 2016/06/13
	 */
	public boolean desiredAssertionStatus()
	{
		// If assertions have been checked, they do not have to be rechecked
		if (this._checkedassert)
			return this._useassert;
		
		// Otherwise check it
		return this.__checkAssertionStatus();
	}
	
	/**
	 * Returns the name of this class.
	 *
	 * @return The name of this class.
	 * @since 2018/09/22
	 */
	public String getName()
	{
		Reference<String> ref = this._name;
		String rv;
		
		if (ref == null || null == (rv = ref.get()))
		{
			String bn = this._data.binaryName();
			
			// Slashes become dots
			this._name = new WeakReference<>((rv = bn.replace('/', '.')));
		}
		
		return rv;
	}
	
	/**
	 * Obtains a resource from the classpath which exists within a JAR file,
	 * inside of a directory, or in a prepacked resource. If a resource needs
	 * to be obtain from another class which exists in another JAR file then
	 * this method must be called from a class in that JAR.







|
|













<
<
<
<
<
<
<
<
<
<
<
|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147











148
149
150
151
152
153
154
155
	 * @return In SquirrelJME this returns by default {@code true}, otherwise
	 * this may return {@code false} if they are disabled for a class.
	 * @since 2016/06/13
	 */
	public boolean desiredAssertionStatus()
	{
		// If assertions have been checked, they do not have to be rechecked
		if (this._checkedAssert)
			return this._useAssert;
		
		// Otherwise check it
		return this.__checkAssertionStatus();
	}
	
	/**
	 * Returns the name of this class.
	 *
	 * @return The name of this class.
	 * @since 2018/09/22
	 */
	public String getName()
	{











		return TypeShelf.runtimeName(this._type);
	}
	
	/**
	 * Obtains a resource from the classpath which exists within a JAR file,
	 * inside of a directory, or in a prepacked resource. If a resource needs
	 * to be obtain from another class which exists in another JAR file then
	 * this method must be called from a class in that JAR.
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232




233
234
235
236
237
238
239
240

241

242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289


290



291



292
293

294
295
296
297
298
299
300
301
302
303
304


305
306
307
308
309



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
		// Check
		if (__name == null)
			throw new NullPointerException("NARG");
		
		// Do not lookup blank resources
		if (__name.isEmpty())
			return null;
		
		// This is not within any JAR, so nothing will ever be found
		String injar = this._data.inJar();
		if (injar == null)
			return null;
		
		// Absolute paths are not translated
		String want;
		if (__name.startsWith("/"))
			want = __name.substring(1);
		
		// Otherwise append to the binary name
		else
		{
			// Has a package
			String pkg = this._data.binaryName();
			int ld = pkg.lastIndexOf('/');
			if (ld >= 0)
				want = pkg.substring(0, ld + 1) + __name;
			

			// Is in default package
			else
				want = __name;
		}
		
		// Open the resource, perhaps




		InputStream rv = ResourceInputStream.open(injar, want);
		if (rv != null)
			return rv;
		
		// Otherwise, do a traditional back to front search for the resource
		// since it might be in another JAR
		String[] classpath = SuiteAccess.currentClassPath();
		for (int i = classpath.length - 1; i >= 0; i--)

			if (null != (rv = ResourceInputStream.open(classpath[i], want)))

				return rv;

		
		// Not found
		return null;
	}
	
	/**
	 * Returns the class which is the superclass of this class.
	 *
	 * @return The superclass or {@code null} if there is none.
	 * @since 2017/03/29
	 */
	@SuppressWarnings({"unchecked"})
	public Class<? super T> getSuperclass()
	{
		return (Class<? super T>)((Object)this._data.superClass());

	}
	
	/**
	 * Returns {@code true} if this class represents an array type.
	 *
	 * @return {@code true} if this class represents an array type.
	 * @since 2016/06/16
	 */
	public boolean isArray()
	{
		// Guess what! Every array starts with with brackets so this is quite
		// easily something which can be determined from the classname
		return this._data.binaryName().startsWith("[");
	}
	
	/**
	 * Checks if the given class can be assigned to this one, the check is
	 * in the same order as {code instanceOf Object} that is
	 * {@code a.getClass().isAssignableFrom(b.getClass()) == (a instanceof b)}.
	 *
	 * @param __cl The other class type.
	 * @return If the otehr class can be assigned to this one.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/27
	 */
	@SuppressWarnings("EqualsBetweenInconvertibleTypes")
	public boolean isAssignableFrom(Class<?> __cl)
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		


		// Go through target superclasses to find this class



		for (Class<?> r = __cl; r != null; r = r._data.superClass())



		{
			if (r == this)

				return true;
		
			// Go through interfaces for the class to find this class
			for (Class<?> i : r._data.interfaceClasses())
				if (i == this)
					return true;
		}
		
		// If this is an array and the other type is an array with the same
		// number of dimensions, then compare the base type so that say
		// Number[] is assignable from Integer[].


		int thisdims = this._data.dimensions(),
			otherdims = __cl._data.dimensions();
		if (thisdims > 0 && thisdims == otherdims)
			if (this.__rootType().isAssignableFrom(__cl.__rootType()))
				return true;



		
		// Not assignable
		return false;
	}
	
	/**
	 * Is this class an interface?
	 *
	 * @return If this is an interface.
	 * @since 2018/11/03
	 */
	public boolean isInterface()
	{
		return (this._data.flags() & ClassFlag.INTERFACE) != 0;
	}
	
	/**
	 * Checks if the given class is an instance of this class.
	 *
	 * @param __o The object to check.
	 * @return If the given object is an instance of this class.







|
|
<
<
<
|
|

|

<
<


|
<
<
<
<

>
|

|


<
>
>
>
>
|
|
|
|
|
<
|
|
>
|
>

>











<


|
>










<
<
|












<





|
>
>
|
>
>
>
|
>
>
>

|
>

|
|
|
|






>
>
|
|
|
|
|
>
>
>













|







180
181
182
183
184
185
186
187
188



189
190
191
192
193


194
195
196




197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
238
239
240
241
242
243
244


245
246
247
248
249
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
		// Check
		if (__name == null)
			throw new NullPointerException("NARG");
		
		// Do not lookup blank resources
		if (__name.isEmpty())
			return null;
			
		// If a resource starts with slash then it is treated as being an



		// absolute reference, otherwise it will depend on the package the
		// class is in
		String want;
		if (__name.charAt(0) == '/')
			want = __name.substring(1);


		else
		{
			String binName = TypeShelf.binaryPackageName(this._type);




			
			if (binName.isEmpty())
				want = __name;
			else
				want = binName + "/" + __name;
		}
		

		// If our class is within a JAR try to search our own JAR first
		JarPackageBracket inJar = TypeShelf.inJar(this._type);
		if (inJar != null)
		{
			InputStream rv = JarPackageShelf.openResource(inJar, want);
			if (rv != null)
				return rv;
		}
		

		// Otherwise search every JAR in the classpath for the given resource
		for (JarPackageBracket jar : JarPackageShelf.classPath())
		{
			InputStream rv = JarPackageShelf.openResource(jar, want);
			if (rv != null)
				return rv;
		}
		
		// Not found
		return null;
	}
	
	/**
	 * Returns the class which is the superclass of this class.
	 *
	 * @return The superclass or {@code null} if there is none.
	 * @since 2017/03/29
	 */

	public Class<? super T> getSuperclass()
	{
		TypeBracket rv = TypeShelf.superClass(this._type);
		return (rv == null ? null : TypeShelf.typeToClass(rv));
	}
	
	/**
	 * Returns {@code true} if this class represents an array type.
	 *
	 * @return {@code true} if this class represents an array type.
	 * @since 2016/06/16
	 */
	public boolean isArray()
	{


		return TypeShelf.isArray(this._type);
	}
	
	/**
	 * Checks if the given class can be assigned to this one, the check is
	 * in the same order as {code instanceOf Object} that is
	 * {@code a.getClass().isAssignableFrom(b.getClass()) == (a instanceof b)}.
	 *
	 * @param __cl The other class type.
	 * @return If the otehr class can be assigned to this one.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/27
	 */

	public boolean isAssignableFrom(Class<?> __cl)
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
			
		TypeBracket self = this._type;
		TypeBracket other = TypeShelf.classToType(__cl);
		
		// Quick determination if this is the same type
		if (self == other)
			return true;
		
		// Scan through the current and super classes of this class
		for (TypeBracket rover = self; rover != null;
			rover = TypeShelf.superClass(rover))
		{
			// Is this the same type?
			if (TypeShelf.equals(self, rover))
				return true;
			
			// Go through interfaces
			for (TypeBracket iFace : TypeShelf.interfaces(rover))
				if (TypeShelf.equals(self, iFace))
					return true;
		}
		
		// If this is an array and the other type is an array with the same
		// number of dimensions, then compare the base type so that say
		// Number[] is assignable from Integer[].
		if (TypeShelf.isArray(self) && TypeShelf.isArray(other))
		{
			int thisDims = TypeShelf.dimensions(self);
			int otherDims = TypeShelf.dimensions(other);
			
			if (thisDims > 0 && thisDims == otherDims)
				return TypeShelf.typeToClass(TypeShelf.componentRoot(self))
					.isAssignableFrom(TypeShelf.typeToClass(
						TypeShelf.componentRoot(other)));
		}
		
		// Not assignable
		return false;
	}
	
	/**
	 * Is this class an interface?
	 *
	 * @return If this is an interface.
	 * @since 2018/11/03
	 */
	public boolean isInterface()
	{
		return TypeShelf.isInterface(this._type);
	}
	
	/**
	 * Checks if the given class is an instance of this class.
	 *
	 * @param __o The object to check.
	 * @return If the given object is an instance of this class.
346
347
348
349
350
351
352
353
354
355
356
357
358




359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
	 * @throws InstantiationException If the default constructor cannot be
	 * accessed by the calling method.
	 * @throws IllegalAccessException If the class or constructor could not
	 * be accessed.
	 * @return The newly created instance.
	 * @since 2018/12/04
	 */
	@SuppressWarnings({"unchecked"})
	public T newInstance()
		throws InstantiationException, IllegalAccessException
	{
		todo.TODO.note("Implement newInstance() access checks.");
		




		return (T)((Object)this.__newInstance());
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/03
	 */
	@Override
	public String toString()
	{
		Reference<String> ref = this._string;
		String rv;
		
		if (ref == null || null == (rv = ref.get()))
		{
			// Based on the binary name
			String binaryname = this._data.binaryName();
			switch (binaryname)
			{
					// Primitive types have the same binary name
				case "boolean":
				case "byte":
				case "short":
				case "char":
				case "int":
				case "long":
				case "float":
				case "double":
					rv = binaryname;
					break;
				
					// Otherwise build a string
				default:
					rv = (this.isInterface() ? "interface " : "class ") +
						this.getName(); 
					break;
			}
			
			// Cache it
			this._string = new WeakReference<>(rv);
		}
		
		return rv;
	}
	
	/**
	 * This checks whether assertions should be **disabled** for this class (or
	 * for the entire package).
	 *
	 * @return The assertions status to use.
	 * @since 2016/10/09
	 */
	private final boolean __checkAssertionStatus()
	{
		// Default to true
		boolean rv = true;
		
		// Determine class name
		String cn = this.getName();
		String prop = Class._ASSERTION_PREFIX + cn;







|



|

>
>
>
>
|









<
<
|
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<









|







334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360


361



362


363








364

365


366









367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
	 * @throws InstantiationException If the default constructor cannot be
	 * accessed by the calling method.
	 * @throws IllegalAccessException If the class or constructor could not
	 * be accessed.
	 * @return The newly created instance.
	 * @since 2018/12/04
	 */
	@SuppressWarnings({"unchecked", "RedundantThrows"})
	public T newInstance()
		throws InstantiationException, IllegalAccessException
	{
		Debugging.todoNote("Implement newInstance() access checks.");
		
		Object rv = ObjectShelf.newInstance(this._type);
		if (rv == null)
			throw new OutOfMemoryError("OOME");
		
		return (T)rv;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/03
	 */
	@Override
	public String toString()
	{


		// Arrays and primitive types essentially just use the binary name



		TypeBracket type = this._type;


		if (TypeShelf.isArray(type) || TypeShelf.isPrimitive(type))








			return TypeShelf.binaryName(type);

		


		return (this.isInterface() ? "interface " : "class ") + this.getName();









	}
	
	/**
	 * This checks whether assertions should be **disabled** for this class (or
	 * for the entire package).
	 *
	 * @return The assertions status to use.
	 * @since 2016/10/09
	 */
	private boolean __checkAssertionStatus()
	{
		// Default to true
		boolean rv = true;
		
		// Determine class name
		String cn = this.getName();
		String prop = Class._ASSERTION_PREFIX + cn;
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

463
464
465


466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
			int ld = cn.lastIndexOf('.');
			if (ld > 0 && Boolean.getBoolean(prop.substring(0,
				prop.length() - (cn.length() - ld))))
				rv = false;
		}
		
		// Set as marked
		this._checkedassert = true;
		this._useassert = rv;
		return rv;
	}
	
	/**
	 * Returns the class data.
	 *
	 * SpringCoat depends on this method to exist.
	 *
	 * @return The class data.
	 * @since 2018/12/05
	 */
	final ClassData __classData()
	{
		return this._data;
	}
	
	/**
	 * Constructs a new instance of this class.
	 *
	 * @throws InstantiationException If the default constructor cannot be
	 * accessed by the calling method.
	 * @throws IllegalAccessException If the class or constructor could not
	 * be accessed.
	 * @since 2018/12/04
	 */

	final Object __newInstance()
		throws InstantiationException, IllegalAccessException
	{


		// Get class details
		ClassData data = this._data;
		String binaryname = data.binaryName();
		
		// {@squirreljme.error ZZ0x Cannot construct new instance of class
		// because it has no default constructor.}
		StaticMethod sm = data.defaultConstructorMethod();
		if (sm == null)
			throw new InstantiationException("ZZ0x " + binaryname);
		
		// Allocate class instance
		Object rv = ObjectAccess.allocateObject(binaryname);
		
		// {@squirreljme.error ZZ0y Could not allocate new instance.}
		if (rv == null)
			throw new OutOfMemoryError("ZZ0y");
		
		// Call default constructor
		ObjectAccess.invokeStatic(sm, rv);
		
		// All done!
		return rv;
	}
	
	/**
	 * Returns the root type, the base of the component.
	 *
	 * @return The root type of this type.
	 * @since 2018/09/27
	 */
	private final Class<?> __rootType()
	{
		Class<?> rv = this;
		for (Class<?> r = this; r != null; r = r._data.component())
			rv = r;
		return rv;
	}
	
	/**
	 * Locates the class with the given name and returns it, otherwise an
	 * exception is thrown.
	 *
	 * The expected form of the class is a name as is mostly used in the







|
|



<
<
<
<
<
<
<
<
<
<
<
<
<









>



>
>


|





|


|










<
<
<
<
<
<
<
|
<
<
<
<
<
<







394
395
396
397
398
399
400
401
402
403
404
405













406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442







443






444
445
446
447
448
449
450
			int ld = cn.lastIndexOf('.');
			if (ld > 0 && Boolean.getBoolean(prop.substring(0,
				prop.length() - (cn.length() - ld))))
				rv = false;
		}
		
		// Set as marked
		this._checkedAssert = true;
		this._useAssert = rv;
		return rv;
	}
	













	/**
	 * Constructs a new instance of this class.
	 *
	 * @throws InstantiationException If the default constructor cannot be
	 * accessed by the calling method.
	 * @throws IllegalAccessException If the class or constructor could not
	 * be accessed.
	 * @since 2018/12/04
	 */
	@SuppressWarnings("RedundantThrows")
	final Object __newInstance()
		throws InstantiationException, IllegalAccessException
	{
		throw Debugging.todo();
		/*
		// Get class details
		ClassData data = this._data;
		String binaryName = data.binaryName();
		
		// {@squirreljme.error ZZ0x Cannot construct new instance of class
		// because it has no default constructor.}
		StaticMethod sm = data.defaultConstructorMethod();
		if (sm == null)
			throw new InstantiationException("ZZ0x " + binaryName);
		
		// Allocate class instance
		Object rv = ObjectAccess.allocateObject(binaryName);
		
		// {@squirreljme.error ZZ0y Could not allocate new instance.}
		if (rv == null)
			throw new OutOfMemoryError("ZZ0y");
		
		// Call default constructor
		ObjectAccess.invokeStatic(sm, rv);
		
		// All done!
		return rv;







		*/






	}
	
	/**
	 * Locates the class with the given name and returns it, otherwise an
	 * exception is thrown.
	 *
	 * The expected form of the class is a name as is mostly used in the
523
524
525
526
527
528
529
530
531
532
533
534
535


536
537



538
539
540
541
	public static Class<?> forName(String __n)
		throws ClassNotFoundException
	{
		// No class specified
		if (__n == null)
			throw new NullPointerException();
		
		// The name will have to be converted to binary form since that is
		// what is internally used
		Class<?> rv = ObjectAccess.classByName(__n.replace('.', '/'));
		
		// {@squirreljme.error ZZ0z Could not find the specified class. (The
		// name of the class)}


		if (rv == null)
			throw new ClassNotFoundException(String.format("ZZ0z %s", __n));



		return rv;
	}
}








<
<
<
<


>
>
|
|
>
>
>
|



465
466
467
468
469
470
471




472
473
474
475
476
477
478
479
480
481
482
483
484
	public static Class<?> forName(String __n)
		throws ClassNotFoundException
	{
		// No class specified
		if (__n == null)
			throw new NullPointerException();
		




		// {@squirreljme.error ZZ0z Could not find the specified class. (The
		// name of the class)}
		TypeBracket found = TypeShelf.findType(
			__n.replace('.', '/'));
		if (found == null)
			throw new ClassNotFoundException("ZZ0z " + __n);
		
		// The name will have to be converted to binary form since that is
		// what is internally used
		return TypeShelf.typeToClass(found);
	}
}

Changes to modules/cldc-compact/src/main/java/java/lang/Double.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.runtime.cldc.asm.ObjectAccess;

public final class Double
	extends Number
	implements Comparable<Double>
{
	public static final int MAX_EXPONENT =
		1023;












|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.MathShelf;
import cc.squirreljme.jvm.mle.TypeShelf;

public final class Double
	extends Number
	implements Comparable<Double>
{
	public static final int MAX_EXPONENT =
		1023;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
	
	/** The number of bits double requires for storage. */
	public static final int SIZE =
		64;
	
	/** The class representing the primitive type. */
	public static final Class<Double> TYPE =
		ObjectAccess.<Double>classByNameType("double");
	
	/** The mask for NaN values. */
	private static final long _NAN_MASK =
		0b0111111111111000000000000000000000000000000000000000000000000000L;
	
	/** The value for this double. */
	private final double _value;







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
	
	/** The number of bits double requires for storage. */
	public static final int SIZE =
		64;
	
	/** The class representing the primitive type. */
	public static final Class<Double> TYPE =
		TypeShelf.<Double>typeToClass(TypeShelf.typeOfDouble());
	
	/** The mask for NaN values. */
	private static final long _NAN_MASK =
		0b0111111111111000000000000000000000000000000000000000000000000000L;
	
	/** The value for this double. */
	private final double _value;
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
	 *
	 * @param __v The input value.
	 * @return The raw bits for the value.
	 * @since 2018/11/03
	 */
	public static long doubleToRawLongBits(double __v)
	{
		return Assembly.doubleToRawLongBits(__v);
	}
	
	public static boolean isInfinite(double __a)
	{
		throw new todo.TODO();
	}
	







|







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
	 *
	 * @param __v The input value.
	 * @return The raw bits for the value.
	 * @since 2018/11/03
	 */
	public static long doubleToRawLongBits(double __v)
	{
		return MathShelf.rawDoubleToLong(__v);
	}
	
	public static boolean isInfinite(double __a)
	{
		throw new todo.TODO();
	}
	
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
	 *
	 * @param __b The bits to convert.
	 * @return The resulting double.
	 * @since 2018/11/03
	 */
	public static double longBitsToDouble(long __b)
	{
		return Assembly.longBitsToDouble(__b);
	}
	
	public static double parseDouble(String __a)
		throws NumberFormatException
	{
		if (false)
			throw new NumberFormatException();







|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
	 *
	 * @param __b The bits to convert.
	 * @return The resulting double.
	 * @since 2018/11/03
	 */
	public static double longBitsToDouble(long __b)
	{
		return MathShelf.rawLongToDouble(__b);
	}
	
	public static double parseDouble(String __a)
		throws NumberFormatException
	{
		if (false)
			throw new NumberFormatException();

Changes to modules/cldc-compact/src/main/java/java/lang/Enum.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import cc.squirreljme.runtime.cldc.asm.StaticMethod;
import cc.squirreljme.runtime.cldc.lang.ClassData;

/**
 * This is the base class for enum types.
 *
 * @param <E> The enum type.
 * @since 2018/09/24
 */












|
<
|







1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.TypeShelf;

import cc.squirreljme.jvm.mle.brackets.TypeBracket;

/**
 * This is the base class for enum types.
 *
 * @param <E> The enum type.
 * @since 2018/09/24
 */
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
	 * @param __cl The class to lookup.
	 * @param __s The string to search for.
	 * @return The enumeration value.
	 * @throws IllegalArgumentException If the value was not found.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/07
	 */

	public static <T extends Enum<T>> T valueOf(Class<T> __cl, String __s)
		throws IllegalArgumentException, NullPointerException
	{
		if (__cl == null || __s == null)
			throw new NullPointerException("NARG");
		
		// Get the data for this class because the enum information will be
		// in here somewhere
		ClassData data = ObjectAccess.classData(__cl);
		
		// {@squirreljme.error ZZ14 Cannot get the value of a non-enumeration
		// type or it has no implicit {@code values()} method.}
		StaticMethod getvalues = data.enumValues();
		if (getvalues == null)
			throw new ClassCastException("ZZ14");
		
		// Go through and check all the names

		for (Enum e : (Enum[])ObjectAccess.invokeStatic(getvalues))
			if (__s.equals(e.name()))
				return __cl.cast(e);
		
		// {@squirreljme.error ZZ15 Not an enumeration value. (The value)}
		throw new IllegalArgumentException(String.format("ZZ15 %s", __s));
	}
}








>






<
<
<
<
|
|
<
|
|

<
>
|
|
|






163
164
165
166
167
168
169
170
171
172
173
174
175
176




177
178

179
180
181

182
183
184
185
186
187
188
189
190
191
	 * @param __cl The class to lookup.
	 * @param __s The string to search for.
	 * @return The enumeration value.
	 * @throws IllegalArgumentException If the value was not found.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/07
	 */
	@SuppressWarnings({"rawtypes"})
	public static <T extends Enum<T>> T valueOf(Class<T> __cl, String __s)
		throws IllegalArgumentException, NullPointerException
	{
		if (__cl == null || __s == null)
			throw new NullPointerException("NARG");
		




		// {@squirreljme.error ZZ3x Type is not an enumeration. (The type)}
		TypeBracket type = TypeShelf.classToType(__cl);

		if (!TypeShelf.isEnum(type))
			throw new ClassCastException("ZZ3x " + __cl);
		

		// Enumerations will be found by their key name
		for (Enum value : TypeShelf.enumValues(type))
			if (__s.equals(value.name()))
				return __cl.cast(value);
		
		// {@squirreljme.error ZZ15 Not an enumeration value. (The value)}
		throw new IllegalArgumentException(String.format("ZZ15 %s", __s));
	}
}

Changes to modules/cldc-compact/src/main/java/java/lang/Float.java.

8
9
10
11
12
13
14


15
16
17
18
19
20
21
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.JVMFunction;


import cc.squirreljme.runtime.cldc.annotation.ProgrammerTip;

public final class Float
	extends Number
	implements Comparable<Float>
{
	public static final int MAX_EXPONENT =







>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.JVMFunction;
import cc.squirreljme.jvm.mle.MathShelf;
import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.runtime.cldc.annotation.ProgrammerTip;

public final class Float
	extends Number
	implements Comparable<Float>
{
	public static final int MAX_EXPONENT =
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
	
	/** The mask for NaN values. */
	private static final int _NAN_MASK =
		0b0111_1111_1000_0000_0000_0000_0000_0000;
	
	/** The class representing the primitive type. */
	public static final Class<Float> TYPE =
		JVMFunction.<Float>jvmLoadClass(Assembly.classInfoOfFloat());
	
	/** The stored value. */
	private final float _value;
	
	/**
	 * Stores the specified float.
	 *







|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	
	/** The mask for NaN values. */
	private static final int _NAN_MASK =
		0b0111_1111_1000_0000_0000_0000_0000_0000;
	
	/** The class representing the primitive type. */
	public static final Class<Float> TYPE =
		TypeShelf.<Float>typeToClass(TypeShelf.typeOfFloat());
	
	/** The stored value. */
	private final float _value;
	
	/**
	 * Stores the specified float.
	 *
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267
	 *
	 * @param __v The input value.
	 * @return The bits that make up the float.
	 * @since 2018/11/04
	 */
	public static int floatToRawIntBits(float __v)
	{
		return Assembly.floatToRawIntBits(__v);
	}
	
	/**
	 * Converts the specified integer bits into a floating point value.
	 *
	 * Note that this value might be modified depending on the platform if
	 * the platform based conversion cannot handle signaling NaNs or illegal
	 * floating point values.
	 *
	 * @param __b The input bits.
	 * @return The resulting float.
	 * @since 2018/11/04
	 */
	public static float intBitsToFloat(int __b)
	{
		return Assembly.intBitsToFloat(__b);
	}
	
	public static boolean isInfinite(float __a)
	{
		throw new todo.TODO();
	}
	
	/**
	 * Is the specified value a NaN?
	 *
	 * @param __v The value to check.
	 * @return If it is NaN or not.
	 * @since 2018/11/04
	 */
	public static boolean isNaN(float __v)
	{

		return (Float.floatToRawIntBits(__v) & Float._NAN_MASK) == Float._NAN_MASK;
	}
	
	public static float parseFloat(String __a)
		throws NumberFormatException
	{
		if (false)
			throw new NumberFormatException();







|















|
















>
|







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
	 *
	 * @param __v The input value.
	 * @return The bits that make up the float.
	 * @since 2018/11/04
	 */
	public static int floatToRawIntBits(float __v)
	{
		return MathShelf.rawFloatToInt(__v);
	}
	
	/**
	 * Converts the specified integer bits into a floating point value.
	 *
	 * Note that this value might be modified depending on the platform if
	 * the platform based conversion cannot handle signaling NaNs or illegal
	 * floating point values.
	 *
	 * @param __b The input bits.
	 * @return The resulting float.
	 * @since 2018/11/04
	 */
	public static float intBitsToFloat(int __b)
	{
		return MathShelf.rawIntToFloat(__b);
	}
	
	public static boolean isInfinite(float __a)
	{
		throw new todo.TODO();
	}
	
	/**
	 * Is the specified value a NaN?
	 *
	 * @param __v The value to check.
	 * @return If it is NaN or not.
	 * @since 2018/11/04
	 */
	public static boolean isNaN(float __v)
	{
		return Float._NAN_MASK ==
			(Float.floatToRawIntBits(__v) & Float._NAN_MASK);
	}
	
	public static float parseFloat(String __a)
		throws NumberFormatException
	{
		if (false)
			throw new NumberFormatException();
284
285
286
287
288
289
290

291
292
293
294
295
296
	/**
	 * Returns the boxed representation of the given float.
	 *
	 * @param __v The float value.
	 * @return The boxed float.
	 * @since 2018/11/04
	 */

	public static Float valueOf(float __v)
	{
		return new Float(__v);
	}
}








>






287
288
289
290
291
292
293
294
295
296
297
298
299
300
	/**
	 * Returns the boxed representation of the given float.
	 *
	 * @param __v The float value.
	 * @return The boxed float.
	 * @since 2018/11/04
	 */
	@SuppressWarnings("UnnecessaryBoxing")
	public static Float valueOf(float __v)
	{
		return new Float(__v);
	}
}

Changes to modules/cldc-compact/src/main/java/java/lang/Integer.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This represents a boxed {@code int} value.
 *
 * @since 2019/05/11












|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * This represents a boxed {@code int} value.
 *
 * @since 2019/05/11
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
	
	/** The number of bits this uses. */
	public static final int SIZE =
		32;
	
	/** The class type representing the primitive type. */
	public static final Class<Integer> TYPE =
		ObjectAccess.<Integer>classByNameType("int");
	
	/** The value of this integer. */
	private final int _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
	
	/** The number of bits this uses. */
	public static final int SIZE =
		32;
	
	/** The class type representing the primitive type. */
	public static final Class<Integer> TYPE =
		TypeShelf.<Integer>typeToClass(TypeShelf.typeOfInteger());
	
	/** The value of this integer. */
	private final int _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	
379
380
381
382
383
384
385

386
387
388
389
390
391
392
	/**
	 * Returns the number of zeros which trail on the right side.
	 *
	 * @param __v The value to check.
	 * @return The number of trailing zeros.
	 * @since 2018/11/11
	 */

	public static int numberOfTrailingZeros(int __v)
	{
		// c will be the number of zero bits on the right
		int c = 32;
		__v &= -__v;
		
		if ((__v) != 0)







>







379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
	/**
	 * Returns the number of zeros which trail on the right side.
	 *
	 * @param __v The value to check.
	 * @return The number of trailing zeros.
	 * @since 2018/11/11
	 */
	@SuppressWarnings("MagicNumber")
	public static int numberOfTrailingZeros(int __v)
	{
		// c will be the number of zero bits on the right
		int c = 32;
		__v &= -__v;
		
		if ((__v) != 0)
422
423
424
425
426
427
428



429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
	 */
	public static int parseInt(String __v, int __r)
		throws NumberFormatException
	{
		// {@squirreljme.error ZZ19 The radix is out of bounds. (The radix)}
		if (__r < Character.MIN_RADIX || __r > Character.MAX_RADIX)
			throw new NumberFormatException("ZZ19 " + __r);



		
		// {@squirreljme.error ZZ1a String is null or has zero length.}
		int n = __v.length();
		if (__v == null || n <= 0)
			throw new NumberFormatException("ZZ1a");
		
		// Detect sign
		boolean neg = false,
			signed = false;
		char c = __v.charAt(0);
		if ((neg = (c == '-')) || c == '+')
			signed = true;
		
		// If the number is negative, instead of negating the value at the end
		// just subtract digits instead.
		int digsign = (neg ? -1 : 1);
		
		// Read all digits
		int rv = 0;
		for (int i = (signed ? 1 : 0); i < n; i++)
		{
			// Read character
			c = __v.charAt(i);
			







>
>
>



|



|
|




<
<
<
<







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445




446
447
448
449
450
451
452
	 */
	public static int parseInt(String __v, int __r)
		throws NumberFormatException
	{
		// {@squirreljme.error ZZ19 The radix is out of bounds. (The radix)}
		if (__r < Character.MIN_RADIX || __r > Character.MAX_RADIX)
			throw new NumberFormatException("ZZ19 " + __r);
			
		if (__v == null)
			throw new NumberFormatException("ZZ1a");
		
		// {@squirreljme.error ZZ1a String is null or has zero length.}
		int n = __v.length();
		if (n <= 0)
			throw new NumberFormatException("ZZ1a");
		
		// Detect sign
		boolean neg;
		boolean signed = false;
		char c = __v.charAt(0);
		if ((neg = (c == '-')) || c == '+')
			signed = true;
		




		// Read all digits
		int rv = 0;
		for (int i = (signed ? 1 : 0); i < n; i++)
		{
			// Read character
			c = __v.charAt(i);
			
461
462
463
464
465
466
467



468
469
470
471
472
473
474
475
			// {@squirreljme.error ZZ1c Input integer out of range of 32-bit
			// integer. (The input string)}
			int prod = rv * __r;
			if (rv != 0 && (neg ? (prod > rv) : (prod < rv)))
				throw new NumberFormatException("ZZ1c " + __v);
			
			// Add up



			rv = prod + (dig * digsign);
		}
		
		return rv;
	}
	
	/**
	 * Returns the value of the specified string.







>
>
>
|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
			// {@squirreljme.error ZZ1c Input integer out of range of 32-bit
			// integer. (The input string)}
			int prod = rv * __r;
			if (rv != 0 && (neg ? (prod > rv) : (prod < rv)))
				throw new NumberFormatException("ZZ1c " + __v);
			
			// Add up
			if (neg)
				rv = prod - dig;
			else
				rv = prod + dig;
		}
		
		return rv;
	}
	
	/**
	 * Returns the value of the specified string.

Changes to modules/cldc-compact/src/main/java/java/lang/Long.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

public final class Long
	extends Number
	implements Comparable<Long>
{












|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

public final class Long
	extends Number
	implements Comparable<Long>
{
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	
	/** The size of the type in bits. */
	public static final int SIZE =
		64;
	
	/** The class representing the primitive long type. */
	public static final Class<Long> TYPE =
		ObjectAccess.<Long>classByNameType("long");
	
	/** The value of this long. */
	private final long _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	
	/** The size of the type in bits. */
	public static final int SIZE =
		64;
	
	/** The class representing the primitive long type. */
	public static final Class<Long> TYPE =
		TypeShelf.<Long>typeToClass(TypeShelf.typeOfLong());
	
	/** The value of this long. */
	private final long _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	
189
190
191
192
193
194
195










196
197
198









199
200
201






202



203


204






205
206



207
208
209






















210
211
212
213
214
215
216
	}
	
	public static int numberOfTrailingZeros(long __a)
	{
		throw new todo.TODO();
	}
	










	public static long parseLong(String __a, int __b)
		throws NumberFormatException
	{









		if (false)
			throw new NumberFormatException();
		throw new todo.TODO();






	}



	


	public static long parseLong(String __a)






		throws NumberFormatException
	{



		if (false)
			throw new NumberFormatException();
		throw new todo.TODO();






















	}
	
	public static long reverse(long __a)
	{
		throw new todo.TODO();
	}
	







>
>
>
>
>
>
>
>
>
>
|


>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
|
|
>
>
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
	}
	
	public static int numberOfTrailingZeros(long __a)
	{
		throw new todo.TODO();
	}
	
	/**
	 * Returns the value of the specified string using the given radix.
	 *
	 * @param __v The String to decode.
	 * @param __radix The radix to use.
	 * @return The resulting long.
	 * @throws NumberFormatException If the string is not valid or the radix
	 * is outside of the valid bounds.
	 * @since 2020/06/18
	 */
	public static long parseLong(String __v, int __radix)
		throws NumberFormatException
	{
		// {@squirreljme.error ZZ25 The radix is out of bounds. (The radix)}
		if (__radix < Character.MIN_RADIX || __radix > Character.MAX_RADIX)
			throw new NumberFormatException("ZZ25 " + __radix);
			
		if (__v == null)
			throw new NumberFormatException("ZZ26");
		
		// {@squirreljme.error ZZ26 String is null or has zero length.}
		int n = __v.length();
		if (n <= 0)
			throw new NumberFormatException("ZZ26");
		
		// Detect sign
		boolean neg;
		boolean signed = false;
		char c = __v.charAt(0);
		if ((neg = (c == '-')) || c == '+')
			signed = true;
		
		// Read all digits
		long rv = 0;
		for (int i = (signed ? 1 : 0); i < n; i++)
		{
			// Read character
			c = __v.charAt(i);
			
			// Convert to digit
			long dig = Character.digit(c, __radix);
			
			// {@squirreljme.error ZZ27 Character out of range of radix.
			// (The input string; The out of range character)}
			if (dig < 0)
				throw new NumberFormatException("ZZ27 " + __v + " " + c);
			
			// {@squirreljme.error ZZ28 Input integer out of range of 64-bit
			// long. (The input string)}
			long prod = rv * __radix;
			if (rv != 0 && (neg ? (prod > rv) : (prod < rv)))
				throw new NumberFormatException("ZZ28 " + __v);
			
			// Add up
			if (neg)
				rv = prod - dig;
			else
				rv = prod + dig;
		}
		
		return rv;
	}
	
	/**
	 * Returns the value of the specified string.
	 *
	 * @param __v The String to decode.
	 * @return The parsed long.
	 * @throws NumberFormatException If the string is not valid.
	 * @since 2020/06/18
	 */
	public static long parseLong(String __v)
		throws NumberFormatException
	{
		return Long.parseLong(__v, 10);
	}
	
	public static long reverse(long __a)
	{
		throw new todo.TODO();
	}
	

Changes to modules/cldc-compact/src/main/java/java/lang/Object.java.

1
2
3
4
5
6
7
8
9
10
11
12
13




14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47

48
49
50

51
52
53
54
55
56
57
58
59

60


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.Assembly;




import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.asm.ObjectAccess;

/**
 * This class is the root of all class trees in Java.
 *
 * @since 2016/02/08
 */
@ImplementationNote("The Java compiler does not allow any final fields to " +
	"exist in Object and if they are set via assignment no code will be " +
	"generated for them, so as such Object effectively has no fields.")
public class Object
{
	
	/**
	 * Clones the current copy creating a shallow copy of it if
	 * {@code Cloneable} is implemented, unless this method is overridden to
	 * perform class specific cloning.
	 *
	 * @throws CloneNotSupportedException If cloning is not supported by the
	 * current class, the default implementation always throws this if the
	 * {@link Cloneable} interface does not exist.
	 * @return The cloned object.
	 * @since 2016/02/08
	 */

	protected Object clone()
		throws CloneNotSupportedException
	{
		// If this is an array copy elements around
		Class<?> cl = this.getClass();
		if (cl.isArray())
		{
			// Need length of this array to recreate!
			int len = Assembly.arrayLength(this);

			
			// Allocate new array
			Object dest = ObjectAccess.arrayNew(cl, len);

			
			// Copy everything over
			System.arraycopy(this, 0, dest, 0, len);
			
			// This array was cloned
			return dest;
		}
		
		// {@squirreljme.error ZZ1d This object does not support being cloned.}

		throw new CloneNotSupportedException("ZZ1d");


	}
	
	/**
	 * Checks for equality between this object and another. Equality should be
	 * reflexive (equal to self), symmetric (a is equal to b as b is equal to
	 * a), transitive (a is equal to b, and b is equal to c, then a must be
	 * equal to c), and consistent (if no modifications to the object were made
	 * then it should return the same value returned as the previous call).
	 *
	 * If this method is overriden, then also override {@code hashCode()}.
	 *
	 * @param __o The object to check equality against.
	 * @return {@code true} if the two objects are equal.
	 * @since 2016/02/08
	 */
	public boolean equals(Object __o)
	{
		return this == __o;
	}
	
	/**
	 * Returns the class object which is associated with this object, this is
	 * the class of the current object.
	 *
	 * @return The current class object.
	 * @since 2016/02/08
	 */
	public final Class<?> getClass()
	{
		return ObjectAccess.classOf(this);
	}
	
	/**
	 * Calculates the hash code for this object.
	 *
	 * If two objects are equal than they must have the same hash code,
	 * otherwise undefined behavior will occur with their potential usage.












|
>
>
>
>

|











<







|



>



|
<
<
<
<
|
>
|

|
>









>
|
>
>









|



















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46




47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.ThreadShelf;
import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.jvm.mle.constants.MonitorResultType;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;
import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.debug.Debugging;

/**
 * This class is the root of all class trees in Java.
 *
 * @since 2016/02/08
 */
@ImplementationNote("The Java compiler does not allow any final fields to " +
	"exist in Object and if they are set via assignment no code will be " +
	"generated for them, so as such Object effectively has no fields.")
public class Object
{

	/**
	 * Clones the current copy creating a shallow copy of it if
	 * {@code Cloneable} is implemented, unless this method is overridden to
	 * perform class specific cloning.
	 *
	 * @throws CloneNotSupportedException If cloning is not supported by the
	 * current class, the default implementation always throws this if the
	 * {@link Cloneable} interface is not implemented by the current object.
	 * @return The cloned object.
	 * @since 2016/02/08
	 */
	@SuppressWarnings({"SuspiciousSystemArraycopy", "UseOfClone"})
	protected Object clone()
		throws CloneNotSupportedException
	{
		// If this is an array, its elements must be copied




		int len = ObjectShelf.arrayLength(this);
		if (len >= 0)
		{
			// Allocate new array
			Object dest = ObjectShelf.<Object>arrayNew(
				TypeShelf.objectType(this), len);
			
			// Copy everything over
			System.arraycopy(this, 0, dest, 0, len);
			
			// This array was cloned
			return dest;
		}
		
		// {@squirreljme.error ZZ1d This object does not support being cloned.}
		if (!(this instanceof Cloneable))
			throw new CloneNotSupportedException("ZZ1d");
		
		throw Debugging.todo();
	}
	
	/**
	 * Checks for equality between this object and another. Equality should be
	 * reflexive (equal to self), symmetric (a is equal to b as b is equal to
	 * a), transitive (a is equal to b, and b is equal to c, then a must be
	 * equal to c), and consistent (if no modifications to the object were made
	 * then it should return the same value returned as the previous call).
	 *
	 * If this method is overridden, then also override {@code hashCode()}.
	 *
	 * @param __o The object to check equality against.
	 * @return {@code true} if the two objects are equal.
	 * @since 2016/02/08
	 */
	public boolean equals(Object __o)
	{
		return this == __o;
	}
	
	/**
	 * Returns the class object which is associated with this object, this is
	 * the class of the current object.
	 *
	 * @return The current class object.
	 * @since 2016/02/08
	 */
	public final Class<?> getClass()
	{
		return TypeShelf.typeToClass(TypeShelf.objectType(this));
	}
	
	/**
	 * Calculates the hash code for this object.
	 *
	 * If two objects are equal than they must have the same hash code,
	 * otherwise undefined behavior will occur with their potential usage.
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154
155



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172



173
174
175
176
177
178
179
	 * @since 2016/02/08
	 */
	public final void notify()
		throws IllegalMonitorStateException
	{
		// {@squirreljme.error ZZ1e This thread does not own the monitor for
		// this thread.}
		if (ObjectAccess.monitorNotify(this, false) < 0)
			throw new IllegalMonitorStateException("ZZ1e");
	}
	
	/**
	 * Notifies all threads which are waiting on this monitor.
	 *
	 * @throws IllegalMonitorStateException If the current thread does not own
	 * the monitor for this object.
	 * @since 2016/02/09
	 */
	public final void notifyAll()
		throws IllegalMonitorStateException
	{
		// {@squirreljme.error ZZ1f This thread does not own the monitor for
		// this thread.}
		if (ObjectAccess.monitorNotify(this, true) < 0)
			throw new IllegalMonitorStateException("ZZ1f");
	}
	
	/**
	 * Returns the string representation of this object.
	 *
	 * The default implementation is {@code classname@hashcode}.
	 *
	 * @return The string representation of this object.
	 * @since 2016/02/09
	 */

	public String toString()
	{
		return this.getClass().getName() + "@" +
			Integer.toString(this.hashCode(), 16);
	}
	
	/**
	 * Causes the current thread to wait on this object's monitor until
	 * {@link #notify()} or {@link #notifyAll()} has been call.



	 *
	 * @throws IllegalMonitorStateException If the current thread does not own
	 * the monitor for this object.
	 * @throws InterruptedException If the current thread was interrupted
	 * during the wait.
	 * @since 2016/02/09
	 */
	public final void wait()
		throws InterruptedException, IllegalMonitorStateException
	{
		this.wait(0, 0);
	}
	
	/**
	 * Causes the current thread to wait on this object's monitor until
	 * {@link #notify()} or {@link #notifyAll()} has been call, however it will
	 * stop after the given time has elapsed.



	 *
	 * @param __ms The milliseconds to wait for, if this is {@code 0} then this
	 * will wait forever.
	 * @throws IllegalArgumentException If any input time is negative.
	 * @throws IllegalMonitorStateException If the current thread does not own
	 * the monitor for this object.
	 * @throws InterruptedException If the current thread was interrupted







|















|











>









>
>
>

















>
>
>







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
	 * @since 2016/02/08
	 */
	public final void notify()
		throws IllegalMonitorStateException
	{
		// {@squirreljme.error ZZ1e This thread does not own the monitor for
		// this thread.}
		if (ObjectShelf.notify(this, false) < 0)
			throw new IllegalMonitorStateException("ZZ1e");
	}
	
	/**
	 * Notifies all threads which are waiting on this monitor.
	 *
	 * @throws IllegalMonitorStateException If the current thread does not own
	 * the monitor for this object.
	 * @since 2016/02/09
	 */
	public final void notifyAll()
		throws IllegalMonitorStateException
	{
		// {@squirreljme.error ZZ1f This thread does not own the monitor for
		// this thread.}
		if (ObjectShelf.notify(this, false) < 0)
			throw new IllegalMonitorStateException("ZZ1f");
	}
	
	/**
	 * Returns the string representation of this object.
	 *
	 * The default implementation is {@code classname@hashcode}.
	 *
	 * @return The string representation of this object.
	 * @since 2016/02/09
	 */
	@SuppressWarnings("MagicNumber")
	public String toString()
	{
		return this.getClass().getName() + "@" +
			Integer.toString(this.hashCode(), 16);
	}
	
	/**
	 * Causes the current thread to wait on this object's monitor until
	 * {@link #notify()} or {@link #notifyAll()} has been call.
	 * 
	 * If the current thread is interrupted, then the interrupt status will
	 * be cleared for the current thread.
	 *
	 * @throws IllegalMonitorStateException If the current thread does not own
	 * the monitor for this object.
	 * @throws InterruptedException If the current thread was interrupted
	 * during the wait.
	 * @since 2016/02/09
	 */
	public final void wait()
		throws InterruptedException, IllegalMonitorStateException
	{
		this.wait(0, 0);
	}
	
	/**
	 * Causes the current thread to wait on this object's monitor until
	 * {@link #notify()} or {@link #notifyAll()} has been call, however it will
	 * stop after the given time has elapsed.
	 * 
	 * If the current thread is interrupted, then the interrupt status will
	 * be cleared for the current thread.
	 *
	 * @param __ms The milliseconds to wait for, if this is {@code 0} then this
	 * will wait forever.
	 * @throws IllegalArgumentException If any input time is negative.
	 * @throws IllegalMonitorStateException If the current thread does not own
	 * the monitor for this object.
	 * @throws InterruptedException If the current thread was interrupted
190
191
192
193
194
195
196



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

229

230
231

232
233
234
235
236
237
238
	/**
	 * Causes the current thread to wait on this object's monitor until
	 * {@link #notify()} or {@link #notifyAll()} has been call, however it will
	 * stop after the given time has elapsed.
	 *
	 * If both {@code __ms} and {@code __ns} are zero, then the wait will be
	 * forever.



	 *
	 * @param __ms The milliseconds to wait for, if this is {@code 0} then this
	 * will wait forever.
	 * @param __ns The number of nanoseconds to additionally wait for.
	 * @throws IllegalArgumentException If any input time is negative or
	 * {@code __ns} is not in the range [0, 999999].
	 * @throws IllegalMonitorStateException If the current thread does not own
	 * the monitor for this object.
	 * @throws InterruptedException If the current thread was interrupted
	 * during the wait.
	 * @since 2016/02/09
	 */
	public final void wait(long __ms, int __ns)
		throws IllegalArgumentException, IllegalMonitorStateException,
			InterruptedException
	{
		// Call wait, but return status can have multiple kind of things
		// going on
		switch (ObjectAccess.monitorWait(this, __ms, __ns))
		{
				// {@squirreljme.error ZZ1g Cannot wait on monitor because
				// this thread does not own the monitor.}
			case ObjectAccess.MONITOR_NOT_OWNED:
				throw new IllegalMonitorStateException("ZZ1g");
			
				// Not interrupted
			case ObjectAccess.MONITOR_NOT_INTERRUPTED:
				return;
			
				// {@squirreljme.error ZZ1h Wait operation has been
				// interrupted.}
			case ObjectAccess.MONITOR_INTERRUPTED:

				Thread.currentThread()._interrupted = false;

				throw new InterruptedException("ZZ1h");
				

				// Should not happen
			default:
				throw new todo.OOPS();
		}
	}
}








>
>
>


















|



|



|

|
<
|
|
>
|
>


>
|

|




202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
	/**
	 * Causes the current thread to wait on this object's monitor until
	 * {@link #notify()} or {@link #notifyAll()} has been call, however it will
	 * stop after the given time has elapsed.
	 *
	 * If both {@code __ms} and {@code __ns} are zero, then the wait will be
	 * forever.
	 * 
	 * If the current thread is interrupted, then the interrupt status will
	 * be cleared for the current thread.
	 *
	 * @param __ms The milliseconds to wait for, if this is {@code 0} then this
	 * will wait forever.
	 * @param __ns The number of nanoseconds to additionally wait for.
	 * @throws IllegalArgumentException If any input time is negative or
	 * {@code __ns} is not in the range [0, 999999].
	 * @throws IllegalMonitorStateException If the current thread does not own
	 * the monitor for this object.
	 * @throws InterruptedException If the current thread was interrupted
	 * during the wait.
	 * @since 2016/02/09
	 */
	public final void wait(long __ms, int __ns)
		throws IllegalArgumentException, IllegalMonitorStateException,
			InterruptedException
	{
		// Call wait, but return status can have multiple kind of things
		// going on
		switch (ObjectShelf.wait(this, __ms, __ns))
		{
				// {@squirreljme.error ZZ1g Cannot wait on monitor because
				// this thread does not own the monitor.}
			case MonitorResultType.NOT_OWNED:
				throw new IllegalMonitorStateException("ZZ1g");
			
				// Not interrupted
			case MonitorResultType.NOT_INTERRUPTED:
				return;
				

				// Our thread was interrupted
			case MonitorResultType.INTERRUPTED:
				// The interrupt status becomes cleared for our current thread
				ThreadShelf.javaThreadClearInterrupt(Thread.currentThread());
				
				throw new InterruptedException("ZZ1h");
				
				// {@squirreljme.error ZZ14 MLE Call returned an invalid
				// monitor result status.}
			default:
				throw new MLECallError("ZZ14");
		}
	}
}

Changes to modules/cldc-compact/src/main/java/java/lang/Runtime.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallError;
import cc.squirreljme.jvm.SystemCallIndex;


/**
 * This class contains information about the host memory environment along
 * with providing methods to perform garbage collection and exit the
 * virtual machine.
 *
 * @since 2018/10/14













|
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.VMStatisticType;

/**
 * This class contains information about the host memory environment along
 * with providing methods to perform garbage collection and exit the
 * virtual machine.
 *
 * @since 2018/10/14
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
	public void exit(int __v)
		throws SecurityException
	{
		// Check that we can exit
		System.getSecurityManager().checkExit(__v);
		
		// Then do the exit if no exception was thrown
		Assembly.sysCall(SystemCallIndex.EXIT, __v);
	}
	
	/**
	 * Returns the amount of memory that is free for the JVM to use.
	 *
	 * @return The amount of free memory.
	 * @since 2018/10/14
	 */
	public long freeMemory()
	{
		int rv = Assembly.sysCallV(SystemCallIndex.VMI_MEM_FREE);
		if (0 != SystemCallError.getError(SystemCallIndex.VMI_MEM_FREE))
			return Integer.MAX_VALUE;
		return rv;
	}
	
	/**
	 * Indicates that the application should have garbage collection be
	 * performed. It is unspecified when garbage collection occurs.
	 *
	 * @since 2017/02/08







|










<
<
<
|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66



67
68
69
70
71
72
73
74
	public void exit(int __v)
		throws SecurityException
	{
		// Check that we can exit
		System.getSecurityManager().checkExit(__v);
		
		// Then do the exit if no exception was thrown
		RuntimeShelf.exit(__v);
	}
	
	/**
	 * Returns the amount of memory that is free for the JVM to use.
	 *
	 * @return The amount of free memory.
	 * @since 2018/10/14
	 */
	public long freeMemory()
	{



		return RuntimeShelf.vmStatistic(VMStatisticType.MEM_FREE);
	}
	
	/**
	 * Indicates that the application should have garbage collection be
	 * performed. It is unspecified when garbage collection occurs.
	 *
	 * @since 2017/02/08
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
	 * be used.
	 *
	 * @return The maximum amount of memory available to the virtual machine.
	 * @since 2018/10/14
	 */
	public long maxMemory()
	{
		int rv = Assembly.sysCallV(SystemCallIndex.VMI_MEM_MAX);
		if (0 != SystemCallError.getError(SystemCallIndex.VMI_MEM_MAX))
			return Integer.MAX_VALUE;
		return rv;
	}
	
	/**
	 * Returns the total amount of memory that is being used by the virtual
	 * machine. This is a count of all the memory claimed by the virtual
	 * machine itself for its memory pools and such.
	 *
	 * @return The amount of memory being used by the virtual machine.
	 * @since 2018/10/14
	 */
	public long totalMemory()
	{
		int rv = Assembly.sysCallV(SystemCallIndex.VMI_MEM_USED);
		if (0 != SystemCallError.getError(SystemCallIndex.VMI_MEM_USED))
			return 0;
		return rv;
	}
	
	/**
	 * Returns the single instance of this class.
	 *
	 * Only a single runtime is valid and there will only be one.
	 *







<
<
<
|












<
<
|
<







84
85
86
87
88
89
90



91
92
93
94
95
96
97
98
99
100
101
102
103


104

105
106
107
108
109
110
111
	 * be used.
	 *
	 * @return The maximum amount of memory available to the virtual machine.
	 * @since 2018/10/14
	 */
	public long maxMemory()
	{



		return RuntimeShelf.vmStatistic(VMStatisticType.MEM_MAX);
	}
	
	/**
	 * Returns the total amount of memory that is being used by the virtual
	 * machine. This is a count of all the memory claimed by the virtual
	 * machine itself for its memory pools and such.
	 *
	 * @return The amount of memory being used by the virtual machine.
	 * @since 2018/10/14
	 */
	public long totalMemory()
	{


		return RuntimeShelf.vmStatistic(VMStatisticType.MEM_USED);

	}
	
	/**
	 * Returns the single instance of this class.
	 *
	 * Only a single runtime is valid and there will only be one.
	 *

Changes to modules/cldc-compact/src/main/java/java/lang/Short.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

public final class Short
	extends Number
	implements Comparable<Short>
{
	public static final short MAX_VALUE =
		32767;
	
	public static final short MIN_VALUE =
		-32768;
	
	public static final int SIZE =
		16;
	
	/** The class representing the primitive type. */
	public static final Class<Short> TYPE =
		ObjectAccess.<Short>classByNameType("short");
	
	/** The value of this integer. */
	private final short _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	












|


















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.TypeShelf;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

public final class Short
	extends Number
	implements Comparable<Short>
{
	public static final short MAX_VALUE =
		32767;
	
	public static final short MIN_VALUE =
		-32768;
	
	public static final int SIZE =
		16;
	
	/** The class representing the primitive type. */
	public static final Class<Short> TYPE =
		TypeShelf.<Short>typeToClass(TypeShelf.typeOfShort());
	
	/** The value of this integer. */
	private final short _value;
	
	/** The string representation of this value. */
	private Reference<String> _string;
	

Changes to modules/cldc-compact/src/main/java/java/lang/String.java.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 *
 * @since 2018/09/16
 */
@SuppressWarnings("StringOperationCanBeSimplified")
public final class String
	implements Comparable<String>, CharSequence
{
	/** The minumum trim character. */
	private static final char _MIN_TRIM_CHAR =
		' ';
	
	/** Is this string already lowercased? */
	private static final short _QUICK_ISLOWER =
		0b0000_0000__0000_0001;
	







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 *
 * @since 2018/09/16
 */
@SuppressWarnings("StringOperationCanBeSimplified")
public final class String
	implements Comparable<String>, CharSequence
{
	/** The minimum trim character. */
	private static final char _MIN_TRIM_CHAR =
		' ';
	
	/** Is this string already lowercased? */
	private static final short _QUICK_ISLOWER =
		0b0000_0000__0000_0001;
	
322
323
324
325
326
327
328



329

330

331
332



333
334
335
336
337
338
339
	 * {@inheritDoc}
	 * @since 2018/09/20
	 */
	@Override
	public char charAt(int __i)
		throws IndexOutOfBoundsException
	{



		char[] chars = this._chars;

		if (__i < 0 || __i >= chars.length)

			throw new IndexOutOfBoundsException("IOOB " + __i);
		return chars[__i];



	}
	
	/**
	 * Compares the character values of this string and compares it to the
	 * character values of the other string.
	 *
	 * Smaller strings always precede longer strings.







>
>
>
|
>
|
>
|
<
>
>
>







322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344
345
346
	 * {@inheritDoc}
	 * @since 2018/09/20
	 */
	@Override
	public char charAt(int __i)
		throws IndexOutOfBoundsException
	{
		// Rather than bounds checking, directly try to access the array
		try
		{
			return this._chars[__i];
		}
		
		// We must ensure that the correct exception is thrown here
		catch (ArrayIndexOutOfBoundsException e)

		{
			throw new StringIndexOutOfBoundsException(__i);
		}
	}
	
	/**
	 * Compares the character values of this string and compares it to the
	 * character values of the other string.
	 *
	 * Smaller strings always precede longer strings.

Changes to modules/cldc-compact/src/main/java/java/lang/StringBuilder.java.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;


/**
 * This is a string which has a mutable buffer.
 *
 * This class is not thread safe, for that use {@link StringBuffer} instead.
 *
 * The default capacity of this builder is 16 characters.













>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import java.util.Arrays;

/**
 * This is a string which has a mutable buffer.
 *
 * This class is not thread safe, for that use {@link StringBuffer} instead.
 *
 * The default capacity of this builder is 16 characters.
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
	 * Obtains the buffer, potentially resizing it to fit the given amount
	 * of characters.
	 *
	 * @param __l The number of characters to add.
	 * @return The buffer.
	 * @since 2018/09/23
	 */
	private final char[] __buffer(int __l)
	{
		// Get buffer properties
		char[] buffer = this._buffer;
		int limit = this._limit,
			at = this._at;
		
		// Need to resize the buffer to fit this?
		int nextat = at + __l;
		if (nextat > limit)
		{
			int newcapacity = nextat + StringBuilder._DEFAULT_CAPACITY;
			
			// Copy characters over
			char[] extra = new char[newcapacity];
			for (int i = 0; i < at; i++)
				extra[i] = buffer[i];
			
			this._buffer = (buffer = extra);
			this._limit = newcapacity;
		}
		
		return buffer;
	}
}








|







|
|

|


|
<
<


|






754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775


776
777
778
779
780
781
782
783
784
	 * Obtains the buffer, potentially resizing it to fit the given amount
	 * of characters.
	 *
	 * @param __l The number of characters to add.
	 * @return The buffer.
	 * @since 2018/09/23
	 */
	private char[] __buffer(int __l)
	{
		// Get buffer properties
		char[] buffer = this._buffer;
		int limit = this._limit,
			at = this._at;
		
		// Need to resize the buffer to fit this?
		int nextAt = at + __l;
		if (nextAt > limit)
		{
			int newCapacity = nextAt + StringBuilder._DEFAULT_CAPACITY;
			
			// Copy characters over
			char[] extra = Arrays.copyOf(buffer, newCapacity);


			
			this._buffer = (buffer = extra);
			this._limit = newCapacity;
		}
		
		return buffer;
	}
}

Changes to modules/cldc-compact/src/main/java/java/lang/System.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90




91
92
93
94
95
96










97
98
99
100
101
102




103






104
105
106
107

108



109
110
111

112
113
114
115

116
117
118
119
120
121
122
123
124

125
126
127
128

129
130
131
132

133
134




135


136
137
138
139
140
141
142
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.runtime.cldc.SquirrelJME;
import cc.squirreljme.runtime.cldc.asm.ConsoleOutput;


import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import cc.squirreljme.runtime.cldc.asm.SystemProperties;
import cc.squirreljme.runtime.cldc.io.CodecFactory;
import cc.squirreljme.runtime.cldc.io.ConsoleOutputStream;
import cc.squirreljme.runtime.cldc.lang.ApiLevel;
import java.io.PrintStream;

/**
 * This class contains methods which are used to interact with the system and
 * the environment.
 *
 * @since 2018/10/14
 */
public final class System
{
	/** Standard error stream (stderr). */

	public static final PrintStream err =
		new __CanSetPrintStream__(new PrintStream(
			new ConsoleOutputStream(ConsoleOutput.ERROR), true));
	
	/** Standard output stream (stdout). */

	public static final PrintStream out =
		new __CanSetPrintStream__(new PrintStream(
			new ConsoleOutputStream(ConsoleOutput.OUTPUT), true));
	
	/**
	 * Not used.
	 *
	 * @since 2018/03/01
	 */
	private System()
	{
	}
	
	/**
	 * Copies from the source array to the destination.
	 *
	 * @param __src The source array.
	 * @param __srcoff The source offset.
	 * @param __dest The destination array.
	 * @param __destoff The destination offset.
	 * @param __copylen The number of elements to copy.
	 * @throws ArrayStoreException If the destination array cannot contain
	 * the given data.
	 * @throws IndexOutOfBoundsException If the offset and or/lengths are
	 * negative or exceed the array bounds.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/27
	 */
	public static void arraycopy(Object __src, int __srcoff,
		Object __dest, int __destoff, int __copylen)
		throws ArrayStoreException, IndexOutOfBoundsException,
			NullPointerException
	{
		if (__src == null || __dest == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ1w Negative offsets and/or length cannot be
		// specified. (The source offset; The destination offset; The copy
		// length)}
		if (__srcoff < 0 || __destoff < 0 || __copylen < 0)
			throw new IndexOutOfBoundsException(String.format("ZZ1w %d %d %d",
				__srcoff, __destoff, __copylen));
		
		// {@squirreljme.error ZZ1x Copy operation would exceed the bounds of
		// the array. (Source offset; Source length; Destination offset;
		// Destination length; The copy length)}
		int srclen = Assembly.arrayLength(__src),
			destlen = Assembly.arrayLength(__dest);
		if (__srcoff + __copylen > srclen ||
			__destoff + __copylen > destlen)
			throw new IndexOutOfBoundsException(String.format(
				"ZZ1x %d %d %d %d %d", __srcoff, srclen, __destoff, destlen,
				__copylen));




		
		// {@squirreljme.error ZZ1y The source array type is not compatible
		// with destination array. (The source array; The destination array)}
		if (!__dest.getClass().isAssignableFrom(__src.getClass()))
			throw new ArrayStoreException(String.format(
				"ZZ1y %s %s", __src, __dest));










		
		// These offsets for the loops are the same
		int i = __srcoff,
			o = __destoff,
			end = __srcoff + __copylen;
		




		// Copy depending on the type






		if (__src instanceof boolean[])
			for (boolean[] s = (boolean[])__src, d = (boolean[])__dest;
				i < end; i++, o++)
			d[o] = s[i];

		else if (__src instanceof byte[])



			for (byte[] s = (byte[])__src, d = (byte[])__dest;
				i < end; i++, o++)
			d[o] = s[i];

		else if (__src instanceof short[])
			for (short[] s = (short[])__src, d = (short[])__dest;
				i < end; i++, o++)
			d[o] = s[i];

		else if (__src instanceof char[])
			for (char[] s = (char[])__src, d = (char[])__dest;
				i < end; i++, o++)
			d[o] = s[i];
		else if (__src instanceof int[])
			for (int[] s = (int[])__src, d = (int[])__dest;
				i < end; i++, o++)
			d[o] = s[i];
		else if (__src instanceof long[])

			for (long[] s = (long[])__src, d = (long[])__dest;
				i < end; i++, o++)
			d[o] = s[i];
		else if (__src instanceof float[])

			for (float[] s = (float[])__src, d = (float[])__dest;
				i < end; i++, o++)
			d[o] = s[i];
		else if (__src instanceof double[])

			for (double[] s = (double[])__src, d = (double[])__dest;
				i < end; i++, o++)




			d[o] = s[i];


		else
			for (Object[] s = (Object[])__src, d = (Object[])__dest;
				i < end; i++, o++)
			d[o] = s[i];
	}
	
	/**












|
|
|
|
>
>
|
|


|











>


|


>


|














|

|
|







|
|









|

|




|
|
|
|

|
|
>
>
>
>



|


>
>
>
>
>
>
>
>
>
>


|
|
|

>
>
>
>
|
>
>
>
>
>
>
|
|
<
<
>
|
>
>
>
|
<
<
>
|
|
|
|
>
|
|
<
<
<
|
<
<
|
>
|
<
<
|
>
|
<
<
|
>
|
|
>
>
>
>
|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133


134
135
136
137
138
139


140
141
142
143
144
145
146
147



148


149
150
151


152
153
154


155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.jvm.mle.brackets.TypeBracket;
import cc.squirreljme.jvm.mle.constants.StandardPipeType;
import cc.squirreljme.jvm.mle.constants.VMDescriptionType;
import cc.squirreljme.runtime.cldc.SquirrelJME;
import cc.squirreljme.runtime.cldc.i18n.DefaultLocale;
import cc.squirreljme.runtime.cldc.io.CodecFactory;
import cc.squirreljme.runtime.cldc.io.ConsoleOutputStream;
import cc.squirreljme.runtime.cldc.lang.LineEndingUtils;
import java.io.PrintStream;

/**
 * This class contains methods which are used to interact with the system and
 * the environment.
 *
 * @since 2018/10/14
 */
public final class System
{
	/** Standard error stream (stderr). */
	@SuppressWarnings("resource")
	public static final PrintStream err =
		new __CanSetPrintStream__(new PrintStream(
			new ConsoleOutputStream(StandardPipeType.STDERR), true));
	
	/** Standard output stream (stdout). */
	@SuppressWarnings("resource")
	public static final PrintStream out =
		new __CanSetPrintStream__(new PrintStream(
			new ConsoleOutputStream(StandardPipeType.STDOUT), true));
	
	/**
	 * Not used.
	 *
	 * @since 2018/03/01
	 */
	private System()
	{
	}
	
	/**
	 * Copies from the source array to the destination.
	 *
	 * @param __src The source array.
	 * @param __srcOff The source offset.
	 * @param __dest The destination array.
	 * @param __destOff The destination offset.
	 * @param __copyLen The number of elements to copy.
	 * @throws ArrayStoreException If the destination array cannot contain
	 * the given data.
	 * @throws IndexOutOfBoundsException If the offset and or/lengths are
	 * negative or exceed the array bounds.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/27
	 */
	public static void arraycopy(Object __src, int __srcOff,
		Object __dest, int __destOff, int __copyLen)
		throws ArrayStoreException, IndexOutOfBoundsException,
			NullPointerException
	{
		if (__src == null || __dest == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ1w Negative offsets and/or length cannot be
		// specified. (The source offset; The destination offset; The copy
		// length)}
		if (__srcOff < 0 || __destOff < 0 || __copyLen < 0)
			throw new IndexOutOfBoundsException(String.format("ZZ1w %d %d %d",
				__srcOff, __destOff, __copyLen));
		
		// {@squirreljme.error ZZ1x Copy operation would exceed the bounds of
		// the array. (Source offset; Source length; Destination offset;
		// Destination length; The copy length)}
		int srcLen = ObjectShelf.arrayLength(__src),
			destLen = ObjectShelf.arrayLength(__dest);
		if (__srcOff + __copyLen > srcLen ||
			__destOff + __copyLen > destLen)
			throw new IndexOutOfBoundsException(String.format(
				"ZZ1x %d %d %d %d %d", __srcOff, srcLen, __destOff, destLen,
				__copyLen));
		
		// Get both respective classes
		Class<?> srcClass = __src.getClass();
		Class<?> destClass = __dest.getClass();
		
		// {@squirreljme.error ZZ1y The source array type is not compatible
		// with destination array. (The source array; The destination array)}
		if (!destClass.isAssignableFrom(srcClass))
			throw new ArrayStoreException(String.format(
				"ZZ1y %s %s", __src, __dest));
		
		// If we are copying nothing then we need not even bother with anything
		// else and we do not have to check the array types as well.
		if (__copyLen == 0)
			return;
		
		// Also as well, if the source and destination are the same and the
		// offsets are the same then nothing will happen at all.
		if (__src == __dest && __srcOff == __destOff)
			return;
		
		// These offsets for the loops are the same
		int i = __srcOff,
			o = __destOff,
			end = __srcOff + __copyLen;
		
		// We can use the native type system within MLE to knock off a few
		// branch possibilities
		TypeBracket srcType = TypeShelf.classToType(srcClass);
		TypeBracket component = TypeShelf.component(srcType);
		
		// Primitive types can be copied at full speed as they do not require
		// any references are otherwise to be counted or garbage collection to
		// be managed
		if (TypeShelf.isPrimitive(component))
		{
			// More common primitives
			if (__src instanceof byte[])
				ObjectShelf.arrayCopy((byte[])__src, __srcOff,


					(byte[])__dest, __destOff, __copyLen);
			else if (__src instanceof char[])
				ObjectShelf.arrayCopy((char[])__src, __srcOff,
					(char[])__dest, __destOff, __copyLen);
			else if (__src instanceof int[])
				ObjectShelf.arrayCopy((int[])__src, __srcOff,


					(int[])__dest, __destOff, __copyLen);
			else if (__src instanceof short[])
				ObjectShelf.arrayCopy((short[])__src, __srcOff,
					(short[])__dest, __destOff, __copyLen);
			
			// Less common types
			else if (__src instanceof boolean[])
				ObjectShelf.arrayCopy((boolean[])__src, __srcOff,



					(boolean[])__dest, __destOff, __copyLen);


			else if (__src instanceof long[])
				ObjectShelf.arrayCopy((long[])__src, __srcOff,
					(long[])__dest, __destOff, __copyLen);


			else if (__src instanceof float[])
				ObjectShelf.arrayCopy((float[])__src, __srcOff,
					(float[])__dest, __destOff, __copyLen);


			else if (__src instanceof double[])
				ObjectShelf.arrayCopy((double[])__src, __srcOff,
					(double[])__dest, __destOff, __copyLen);
			
			// {@squirreljme.error ZZ1h Not a primitive array type.}
			else
				throw new Error("ZZ1h");
		}
		
		// There is no native handler for manual object array copies due to
		// references and otherwise
		else
			for (Object[] s = (Object[])__src, d = (Object[])__dest;
				i < end; i++, o++)
			d[o] = s[i];
	}
	
	/**
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
	 *
	 * @return The number of milliseconds since the epoch.
	 * @since 2017/11/10
	 */
	public static long currentTimeMillis()
	{
		// Returns the current time in UTC, not local time zone.
		return Assembly.sysCallPVL(SystemCallIndex.TIME_MILLI_WALL);
	}
	
	/**
	 * Indicates that the application exits with the given code.
	 *
	 * @param __e The exit code, the value of this code may change according
	 * to the host operating system and the resulting process might not exit







|







182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	 *
	 * @return The number of milliseconds since the epoch.
	 * @since 2017/11/10
	 */
	public static long currentTimeMillis()
	{
		// Returns the current time in UTC, not local time zone.
		return RuntimeShelf.currentTimeMillis();
	}
	
	/**
	 * Indicates that the application exits with the given code.
	 *
	 * @param __e The exit code, the value of this code may change according
	 * to the host operating system and the resulting process might not exit
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314
315
316
317

318
319
320
321

322
323
324
325

326
327
328
329

330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

392














393
394
395
396
397
398
399
400
401
402
403
		// Not allowed to do this?
		System.getSecurityManager().checkPropertyAccess(__k);
		
		// Depends on the property
		String rv;
		switch (__k)
		{
				// API level of SquirrelJME
			case "cc.squirreljme.apilevel":
				return ApiLevel.levelToString(ApiLevel.CURRENT_LEVEL);
			
				// SquirrelJME guest depth
			case "cc.squirreljme.guests":
				return Integer.toString(SystemProperties.guestDepth());
				
				// SquirrelJME VM executable path
			case "cc.squirreljme.vm.execpath":
				return SystemProperties.executablePath();

				
				// SquirrelJME free memory
			case "cc.squirreljme.vm.freemem":
				return Long.toString(Runtime.getRuntime().freeMemory());
				
				// SquirrelJME total memory
			case "cc.squirreljme.vm.totalmem":
				return Long.toString(Runtime.getRuntime().totalMemory());
				
				// SquirrelJME free memory
			case "cc.squirreljme.vm.maxmem":
				return Long.toString(Runtime.getRuntime().maxMemory());
			
				// The version of the Java virtual machine (fixed value)
			case "java.version":
				return "1.8.0";
				
				// The version of the JVM (full)
			case "java.vm.version":
				return SystemProperties.javaVMVersion();

				
				// The name of the JVM
			case "java.vm.name":
				return SystemProperties.javaVMName();

				
				// The vendor of the JVM
			case "java.vm.vendor":
				return SystemProperties.javaVMVendor();

			
				// The e-mail of the JVM
			case "java.vm.vendor.email":
				return SystemProperties.javaVMEmail();

			
				// The URL of the JVM
			case "java.vm.vendor.url":
				return SystemProperties.javaVMURL();

				
				// The vendor of the class libraries
			case "java.vendor":
				return "Stephanie Gawroriski";
				
				// Non-standard e-mail address
			case "java.vendor.email":
				return "xerthesquirrel@gmail.com";
				
				// The URL to the virtual machine's site
			case "java.vendor.url":
				return "http://squirreljme.cc/";
				
				// The name of the runtime library
			case "java.runtime.name":
				return "SquirrelJME";
				
				// The version of the run-time
			case "java.runtime.version":
				return SystemProperties.javaRuntimeVersion();
				
				// End of line character
			case "line.separator":
				rv = SystemProperties.systemProperty("line.separator");
				if (rv == null)
					return "\n";
				return rv;
				
				// The current configuration, must be set!
			case "microedition.configuration":
				rv = SystemProperties.systemProperty(
					"microedition.configuration");
				if (rv == null)
					try
					{
						Class<?> file = Class.forName("java.nio.FileSystem");
						if (file == null)
							return "CLDC-1.8-Compact";
						return "CLDC-1.8";
					}
					catch (ClassNotFoundException e)
					{
						return "CLDC-1.8-Compact";
					}
				return rv;
				
				// The current encoding
			case "microedition.encoding":
				rv = SystemProperties.systemProperty("microedition.encoding");
				if (rv == null)
					return CodecFactory.FALLBACK_ENCODING;
				return rv;
				
				// The current local, must be set!
			case "microedition.locale":
				rv = SystemProperties.systemProperty("microedition.locale");
				if (rv == null)
					return "en-US";
				return rv;
				
				// The current platform
			case "microedition.platform":

				return "SquirrelJME/" + SquirrelJME.RUNTIME_VERSION;














				
				// Unknown, use system call
			default:
				return SystemProperties.systemProperty(__k);
		}
	}
	
	/**
	 * Obtains the specified system property and if it has not been set then
	 * the default value will be returned instead.
	 *







<
<
<
<
<
<
<
<


|
>



















|
>



|
>



|
>



|
>



|
>



















|



<
<
|
<



<
<
<
|
|
|
|
|
|
|
|
|
|
|
<



<
<
|
<

|

<
<
<
|



>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|







306
307
308
309
310
311
312








313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380


381

382
383
384



385
386
387
388
389
390
391
392
393
394
395

396
397
398


399

400
401
402



403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
		// Not allowed to do this?
		System.getSecurityManager().checkPropertyAccess(__k);
		
		// Depends on the property
		String rv;
		switch (__k)
		{








				// SquirrelJME VM executable path
			case "cc.squirreljme.vm.execpath":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.EXECUTABLE_PATH);
				
				// SquirrelJME free memory
			case "cc.squirreljme.vm.freemem":
				return Long.toString(Runtime.getRuntime().freeMemory());
				
				// SquirrelJME total memory
			case "cc.squirreljme.vm.totalmem":
				return Long.toString(Runtime.getRuntime().totalMemory());
				
				// SquirrelJME free memory
			case "cc.squirreljme.vm.maxmem":
				return Long.toString(Runtime.getRuntime().maxMemory());
			
				// The version of the Java virtual machine (fixed value)
			case "java.version":
				return "1.8.0";
				
				// The version of the JVM (full)
			case "java.vm.version":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.VM_VERSION);
				
				// The name of the JVM
			case "java.vm.name":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.VM_NAME);
				
				// The vendor of the JVM
			case "java.vm.vendor":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.VM_VENDOR);
			
				// The e-mail of the JVM
			case "java.vm.vendor.email":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.VM_EMAIL);
			
				// The URL of the JVM
			case "java.vm.vendor.url":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.VM_URL);
				
				// The vendor of the class libraries
			case "java.vendor":
				return "Stephanie Gawroriski";
				
				// Non-standard e-mail address
			case "java.vendor.email":
				return "xerthesquirrel@gmail.com";
				
				// The URL to the virtual machine's site
			case "java.vendor.url":
				return "http://squirreljme.cc/";
				
				// The name of the runtime library
			case "java.runtime.name":
				return "SquirrelJME";
				
				// The version of the run-time
			case "java.runtime.version":
				return SquirrelJME.RUNTIME_VERSION;
				
				// End of line character
			case "line.separator":


				return LineEndingUtils.toString(RuntimeShelf.lineEnding());

				
				// The current configuration, must be set!
			case "microedition.configuration":



				try
				{
					Class<?> file = Class.forName("java.nio.FileSystem");
					if (file == null)
						return "CLDC-1.8-Compact";
					return "CLDC-1.8";
				}
				catch (ClassNotFoundException e)
				{
					return "CLDC-1.8-Compact";
				}

				
				// The current encoding
			case "microedition.encoding":


				return CodecFactory.toString(RuntimeShelf.encoding());

				
				// The current locale, must be set!
			case "microedition.locale":



				return DefaultLocale.toString(RuntimeShelf.locale());
				
				// The current platform
			case "microedition.platform":
				return SquirrelJME.MICROEDITION_PLATFORM;
				
				// The operating system architecture
			case "os.arch":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.OS_ARCH);
				
				// The operating system name
			case "os.name":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.OS_NAME);
				
				// The operating system name
			case "os.version":
				return RuntimeShelf.vmDescription(
					VMDescriptionType.OS_VERSION);
				
				// Unknown, use system call
			default:
				return RuntimeShelf.systemProperty(__k);
		}
	}
	
	/**
	 * Obtains the specified system property and if it has not been set then
	 * the default value will be returned instead.
	 *
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
	 */
	public static int identityHashCode(Object __o)
	{
		// If null, this is zero
		if (__o == null)
			return 0;
		
		return ObjectAccess.identityHashCode(__o);
	}
	
	/**
	 * Returns the number of nanoseconds which have passed from a previously
	 * unspecified time. The returned value might not be accurate to the
	 * nanosecond. This clock is monotonic and does not suffer from time
	 * shifts caused by clock adjustments.







|







484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
	 */
	public static int identityHashCode(Object __o)
	{
		// If null, this is zero
		if (__o == null)
			return 0;
		
		return ObjectShelf.identityHashCode(__o);
	}
	
	/**
	 * Returns the number of nanoseconds which have passed from a previously
	 * unspecified time. The returned value might not be accurate to the
	 * nanosecond. This clock is monotonic and does not suffer from time
	 * shifts caused by clock adjustments.
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
	 *
	 * @return The number of nanoseconds which have passed.
	 * @since 2016/06/16
	 */
	public static long nanoTime()
	{
		// Returns the current monotonic clock time
		return Assembly.sysCallPVL(SystemCallIndex.TIME_NANO_MONO);
	}
	
	/**
	 * Sets the new destination for standard error.
	 *
	 * Note that the {@link System#err} field is not changed, a wrapper class
	 * is used to prevent reflective abuse.







|







511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
	 *
	 * @return The number of nanoseconds which have passed.
	 * @since 2016/06/16
	 */
	public static long nanoTime()
	{
		// Returns the current monotonic clock time
		return RuntimeShelf.nanoTime();
	}
	
	/**
	 * Sets the new destination for standard error.
	 *
	 * Note that the {@link System#err} field is not changed, a wrapper class
	 * is used to prevent reflective abuse.

Changes to modules/cldc-compact/src/main/java/java/lang/Thread.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

107
108
109

110
111
112
113

114
115
116
117
118
119
120
121
122
123
124
125


126


127
128
129
130
131
132
133
134
135
136
137


138


139
140
141
142
143
144
145
146
147
148
149
150
151


152





153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;
import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import cc.squirreljme.runtime.cldc.asm.StaticMethod;
import cc.squirreljme.runtime.cldc.asm.TaskAccess;
import cc.squirreljme.runtime.cldc.lang.UncaughtExceptionHandler;
import java.util.HashMap;
import java.util.Map;

/**
 * A thread represents literally a single stream of execution that can
 * execute concurrently (or not).
 *
 * SquirrelJME may be running with multiple threads executing at once or it
 * may also be executing cooperatively (only a single thread at a time). If
 * SquirrelJME is running cooperatively then only locking,
 * {@link Thread#sleep(long, int)}, or {@link Thread#yield()} will allow
 * another thread to run.
 *
 * @since 2018/12/07
 */
@ImplementationNote("Internally all threads start in the Thread.__start() " +
	"method which sets up the thread and such.")
public class Thread
	implements Runnable
{
	/** Use fake name for string? */
	private static final String _USE_FAKE_NAME =
		new String();
	
	/** Maximum supported priority. */
	public static final int MAX_PRIORITY =
		10;
	
	/** Minimum supported priority. */
	public static final int MIN_PRIORITY =
		1;
	
	/** Default priority. */
	public static final int NORM_PRIORITY =
		5;
	
	/** Start kind: Self Runnable */
	private static final int _START_SELF_RUNNABLE =
		1;
	
	/** Start kind: Specified Runnable. */
	private static final int _START_GIVEN_RUNNABLE =
		2;
	
	/** Start kind: MIDlet (construct then run startApp()). */
	private static final int _START_MIDLET =
		3;
	
	/** Start kind: main() method (is String[] argument). */
	private static final int _START_MAIN =
		4;
	
	/** Threads by virtual ID. */
	private static final Map<Integer, Thread> _BY_VIRTID =
		new HashMap<>();
	
	/** Threads by real ID. */
	private static final Map<Integer, Thread> _BY_REALID =
		new HashMap<>();
	
	/** The next virtual thread ID. */
	private static volatile int _NEXT_VIRTUAL_ID =
		0;
	
	/** The active number of threads. */
	private static volatile int _ACTIVE_THREADS;
	
	/** Which kind of start are we doing? */
	private final int _startkind;
	
	/** The method to execute. */
	private final StaticMethod _runmethod;
	
	/** The argument to the method. */
	private final Object _runargument;
	
	/** The virtual thread ID. */
	private final int _virtid;
	
	/** The real thread ID. */
	private volatile int _realid =
		-1;
	
	/** The name of this thread. */
	private volatile String _name;
	
	/** Has this thread been started? */

	private volatile boolean _started;
	
	/** Is this thread alive? */

	private volatile boolean _isalive;
	
	/** The priority of the thread. */
	private volatile int _priority = Thread.NORM_PRIORITY;

	
	/** Is this thread interrupted? */
	volatile boolean _interrupted;
	
	/**
	 * Initializes the thread which invokes this object's {@link #run()} and
	 * uses a default thread name.
	 *
	 * @since 2018/11/17
	 */
	public Thread()
	{


		this(null, Thread._USE_FAKE_NAME);


	}
	
	/**
	 * Initializes the thread which invokes this object's {@link #run()} and
	 * uses a default thread name.
	 *
	 * @param __r The runnable to execute.
	 * @since 2018/11/17
	 */
	public Thread(Runnable __r)
	{


		this(__r, Thread._USE_FAKE_NAME);


	}
	
	/**
	 * Initializes the thread which invokes this object's {@link #run()} and
	 * uses the specified thread name.
	 *
	 * @param __n The thread's name.
	 * @throws NullPointerException If the thread name is null.
	 * @since 2018/11/17
	 */
	public Thread(String __n)
		throws NullPointerException
	{


		this(null, __n);





	}
	
	/**
	 * Initializes the thread which invokes the given {@link Runnable} and uses
	 * the given name.
	 *
	 * @param __r The runnable to execute.
	 * @param __n The thread's name.
	 * @throws NullPointerException If the thread name is null.
	 * @since 2018/11/17
	 */
	public Thread(Runnable __r, String __n)
		throws NullPointerException
	{
		this(__n, (__r == null ? Thread._START_SELF_RUNNABLE :
				Thread._START_GIVEN_RUNNABLE),
			null, __r);
	}
	
	/**
	 * Initializes a thread which is registered in this constructor and
	 * additionally has the given name and real ID.
	 *
	 * The thread is started in the started state and technically is not
	 * removed ever. This is generally used by the native display thread
	 * since there has to be a thread running as the VM sees it otherwise
	 * things will break much. A thread started this way never terminates
	 * unless that termination is explicit.
	 *
	 * @param __n The thread name.
	 * @param __rid The real ID.
	 * @since 2018/12/03
	 */
	private Thread(int __rid, String __n)
	{
		this._startkind = -1;
		this._runmethod = null;
		this._runargument = null;
		this._realid = __rid;
		this._name = __n;
		this._started = true;
		this._isalive = true;
		
		// Obtain the next virtual ID to use
		int virtid;
		synchronized (Thread.class)
		{
			this._virtid = (virtid = Thread._NEXT_VIRTUAL_ID++);
		}
		
		// Now register this thread in the main objects
		this.__registerThread();
	}
	
	/**
	 * Initializes the thread to execute the given static method.
	 *
	 * @param __n The name of the thread.
	 * @param __rk How is this method to be run?
	 * @param __mm The static method to call.
	 * @param __ma The argument to use.
	 * @throws NullPointerException If no name was specified.
	 * @since 2018/11/20
	 */
	private Thread(String __n, int __rk, StaticMethod __mm, Object __ma)
		throws NullPointerException
	{
		if (__n == null)
			throw new NullPointerException("NARG");
		
		// Obtain the next virtual ID to use
		int virtid;
		synchronized (Thread.class)
		{
			this._virtid = (virtid = Thread._NEXT_VIRTUAL_ID++);
		}
		
		// Set
		this._name = (__n == Thread._USE_FAKE_NAME ? "Thread-" + virtid : __n);
		this._startkind = __rk;
		this._runmethod = __mm;
		this._runargument = __ma;
		
		// The main thread is implicitly started
		boolean implicitstart = (__rk == Thread._START_MAIN || __rk == Thread._START_MIDLET);
		this._started = implicitstart;
	}
	
	/**
	 * Checks that the thread has access to perform some operations.
	 *
	 * @throws SecurityException If access is denied.
	 * @since 2018/11/21












|
|
<
<
<
|
<
<
<













<
<



<
<
<
<












<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<

<
<
<
|
<
<
<
|
<
<
<
<
|

<
<
<
<
<
<
|
|

<
<
<
<




>



>
|


|
>












>
>
|
>
>











>
>
|
>
>













>
>
|
>
>
>
>
>














<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<
<
|
<
|
|
<
<
<
<
|
<
|
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14



15



16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31




32
33
34
35
36
37
38
39
40
41
42
43



44









45

46



47



48



49




50
51






52
53
54




55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136





















































137
138
139


140

141
142




143

144



145
146
147
148
149
150
151
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.ThreadShelf;



import cc.squirreljme.jvm.mle.brackets.VMThreadBracket;




/**
 * A thread represents literally a single stream of execution that can
 * execute concurrently (or not).
 *
 * SquirrelJME may be running with multiple threads executing at once or it
 * may also be executing cooperatively (only a single thread at a time). If
 * SquirrelJME is running cooperatively then only locking,
 * {@link Thread#sleep(long, int)}, or {@link Thread#yield()} will allow
 * another thread to run.
 *
 * @since 2018/12/07
 */


public class Thread
	implements Runnable
{




	/** Maximum supported priority. */
	public static final int MAX_PRIORITY =
		10;
	
	/** Minimum supported priority. */
	public static final int MIN_PRIORITY =
		1;
	
	/** Default priority. */
	public static final int NORM_PRIORITY =
		5;
	



	/** Second in nano seconds. */









	private static final long _NS_SECOND =

		1_000_000L;



	



	/** The runnable that this thread uses for its main code, if applicable. */



	@SuppressWarnings("unused")




	private final Runnable _runnable;
	






	/** The virtual machine thread this uses. */
	private final VMThreadBracket _vmThread;
	




	/** The name of this thread. */
	private volatile String _name;
	
	/** Has this thread been started? */
	@SuppressWarnings("unused")
	private volatile boolean _started;
	
	/** Is this thread alive? */
	@SuppressWarnings("unused")
	private volatile boolean _isAlive;
	
	/** The priority of the thread. */
	private volatile int _priority =
		Thread.NORM_PRIORITY;
	
	/** Is this thread interrupted? */
	volatile boolean _interrupted;
	
	/**
	 * Initializes the thread which invokes this object's {@link #run()} and
	 * uses a default thread name.
	 *
	 * @since 2018/11/17
	 */
	public Thread()
	{
		VMThreadBracket vmThread = ThreadShelf.createVMThread(this);
		this._vmThread = vmThread;
		
		this._runnable = null;
		this._name = Thread.__defaultName(null, vmThread);
	}
	
	/**
	 * Initializes the thread which invokes this object's {@link #run()} and
	 * uses a default thread name.
	 *
	 * @param __r The runnable to execute.
	 * @since 2018/11/17
	 */
	public Thread(Runnable __r)
	{
		VMThreadBracket vmThread = ThreadShelf.createVMThread(this);
		this._vmThread = vmThread;
		
		this._runnable = __r;
		this._name = Thread.__defaultName(null, vmThread);
	}
	
	/**
	 * Initializes the thread which invokes this object's {@link #run()} and
	 * uses the specified thread name.
	 *
	 * @param __n The thread's name.
	 * @throws NullPointerException If the thread name is null.
	 * @since 2018/11/17
	 */
	public Thread(String __n)
		throws NullPointerException
	{
		if (__n == null)
			throw new NullPointerException("NARG");
		
		VMThreadBracket vmThread = ThreadShelf.createVMThread(this);
		this._vmThread = vmThread;
		
		this._runnable = null;
		this._name = Thread.__defaultName(__n, vmThread);
	}
	
	/**
	 * Initializes the thread which invokes the given {@link Runnable} and uses
	 * the given name.
	 *
	 * @param __r The runnable to execute.
	 * @param __n The thread's name.
	 * @throws NullPointerException If the thread name is null.
	 * @since 2018/11/17
	 */
	public Thread(Runnable __r, String __n)
		throws NullPointerException
	{





















































		if (__n == null)
			throw new NullPointerException("NARG");
		


		VMThreadBracket vmThread = ThreadShelf.createVMThread(this);

		this._vmThread = vmThread;
		




		this._runnable = __r;

		this._name = Thread.__defaultName(__n, vmThread);



	}
	
	/**
	 * Checks that the thread has access to perform some operations.
	 *
	 * @throws SecurityException If access is denied.
	 * @since 2018/11/21
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
	 * Returns the ID of this thread.
	 *
	 * @return The thread ID.
	 * @since 2018/11/20
	 */
	public long getId()
	{
		return this._virtid;
	}
	
	/**
	 * Returns the name of this thread.
	 *
	 * @return The thread name.
	 * @since 2018/11/17







|







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
	 * Returns the ID of this thread.
	 *
	 * @return The thread ID.
	 * @since 2018/11/20
	 */
	public long getId()
	{
		return ThreadShelf.vmThreadId(this._vmThread);
	}
	
	/**
	 * Returns the name of this thread.
	 *
	 * @return The thread name.
	 * @since 2018/11/17
283
284
285
286
287
288
289
290





291
292
293

294





295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327



328
329
330
331
332
333
334
335
336
337
338
339
340



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358



359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385

386
387
388
389
390
391

392
393
394
395
396
397
398
	public final int getPriority()
	{
		return this._priority;
	}
	
	/**
	 * Interrupts the thread.
	 *





	 * @since 2018/11/21
	 */
	public void interrupt()

	{





		// Signal software interrupt
		this._interrupted = true;
		
		// Signal hardware interrupt
		int realid = this._realid;
		if (realid >= 0)
			TaskAccess.signalInterrupt(realid);
	}
	
	/**
	 * Is this thread currently alive?
	 *
	 * @return If this thread is alive.
	 * @since 2018/11/20
	 */
	public final boolean isAlive()
	{
		return this._isalive;
	}
	
	/**
	 * Is this thread interrupted?
	 *
	 * @return If this thread is interrupted.
	 * @since 2018/11/21
	 */
	public boolean isInterrupted()
	{
		return this._interrupted;
	}
	
	/**
	 * Waits forever for a thread to die or until interrupted.



	 *
	 * @throws InterruptedException If the thread was interrupted while
	 * waiting.
	 * @since 2018/12/07
	 */
	public final void join()
		throws InterruptedException
	{
		this.join(0, 0);
	}
	
	/**
	 * Waits for a thread to die.



	 *
	 * @param __ms The milliseconds to wait for, if this is zero then this
	 * will wait forever.
	 * @throws IllegalArgumentException If the timeout is negative.
	 * @throws InterruptedException If the thread was interrupted while
	 * waiting.
	 * @since 2018/12/07
	 */
	public final void join(long __ms)
		throws IllegalArgumentException, InterruptedException
	{
		this.join(__ms, 0);
	}
	
	/**
	 * Waits for a thread to die.
	 *
	 * If both milliseconds and nanoseconds are zero this will wait forever.



	 *
	 * @param __ms The milliseconds to wait for.
	 * @param __ns The nanoseconds to wait for.
	 * @throws IllegalArgumentException If the timeout is negative.
	 * @throws InterruptedException If the thread was interrupted while
	 * waiting.
	 * @since 2018/12/07
	 */
	public final void join(long __ms, int __ns)
		throws IllegalArgumentException, InterruptedException
	{
		// The end time, since our thread could be notified
		long end = (__ms == 0 && __ns == 0 ? Long.MAX_VALUE :
			System.nanoTime() + (__ms * 1_000_000L) + __ns);
		
		// Lock on self
		synchronized (this)
		{
			// Loop constantly until the thread is dead
			for (;;)
			{
				// Time ended?
				long now;
				if ((now = System.nanoTime()) >= end)
					return;
				
				// Did the thread die yet?

				if (this._started && !this._isalive)
					return;
				
				// Otherwise wait on our own monitor
				long diff = end - now;
				this.wait(diff / 1_000_000L, (int)(diff % 1_000_000L));

			}
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/17







|
>
>
>
>
>



>

>
>
>
>
>




<
<
|










|















>
>
>













>
>
>


















>
>
>













|













>
|




|
>







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215


216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
	public final int getPriority()
	{
		return this._priority;
	}
	
	/**
	 * Interrupts the thread.
	 * 
	 * This will call {@link #checkAccess()} if this thread is not the current
	 * thread.
	 *
	 * @throws SecurityException If the current thread is not permitted to
	 * interrupt this thread.
	 * @since 2018/11/21
	 */
	public void interrupt()
		throws SecurityException
	{
		// If this is not the current thread, we need to talk to the security
		// manager
		if (ThreadShelf.currentJavaThread() != this)
			this.checkAccess();
		
		// Signal software interrupt
		this._interrupted = true;
		
		// Signal hardware interrupt


		ThreadShelf.vmThreadInterrupt(this._vmThread);
	}
	
	/**
	 * Is this thread currently alive?
	 *
	 * @return If this thread is alive.
	 * @since 2018/11/20
	 */
	public final boolean isAlive()
	{
		return this._isAlive;
	}
	
	/**
	 * Is this thread interrupted?
	 *
	 * @return If this thread is interrupted.
	 * @since 2018/11/21
	 */
	public boolean isInterrupted()
	{
		return this._interrupted;
	}
	
	/**
	 * Waits forever for a thread to die or until interrupted.
	 * 
	 * If the current thread is interrupted, then the interrupt status will
	 * be cleared for the current thread.
	 *
	 * @throws InterruptedException If the thread was interrupted while
	 * waiting.
	 * @since 2018/12/07
	 */
	public final void join()
		throws InterruptedException
	{
		this.join(0, 0);
	}
	
	/**
	 * Waits for a thread to die.
	 * 
	 * If the current thread is interrupted, then the interrupt status will
	 * be cleared for the current thread.
	 *
	 * @param __ms The milliseconds to wait for, if this is zero then this
	 * will wait forever.
	 * @throws IllegalArgumentException If the timeout is negative.
	 * @throws InterruptedException If the thread was interrupted while
	 * waiting.
	 * @since 2018/12/07
	 */
	public final void join(long __ms)
		throws IllegalArgumentException, InterruptedException
	{
		this.join(__ms, 0);
	}
	
	/**
	 * Waits for a thread to die.
	 *
	 * If both milliseconds and nanoseconds are zero this will wait forever.
	 * 
	 * If the current thread is interrupted, then the interrupt status will
	 * be cleared for the current thread.
	 *
	 * @param __ms The milliseconds to wait for.
	 * @param __ns The nanoseconds to wait for.
	 * @throws IllegalArgumentException If the timeout is negative.
	 * @throws InterruptedException If the thread was interrupted while
	 * waiting.
	 * @since 2018/12/07
	 */
	public final void join(long __ms, int __ns)
		throws IllegalArgumentException, InterruptedException
	{
		// The end time, since our thread could be notified
		long end = (__ms == 0 && __ns == 0 ? Long.MAX_VALUE :
			System.nanoTime() + (__ms * Thread._NS_SECOND) + __ns);
		
		// Lock on self
		synchronized (this)
		{
			// Loop constantly until the thread is dead
			for (;;)
			{
				// Time ended?
				long now;
				if ((now = System.nanoTime()) >= end)
					return;
				
				// Did the thread die yet?
				if (ThreadShelf.javaThreadIsStarted(this) &&
					!this.isAlive())
					return;
				
				// Otherwise wait on our own monitor
				long diff = end - now;
				this.wait(diff / Thread._NS_SECOND,
					(int)(diff % Thread._NS_SECOND));
			}
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/17
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
		
		// Check access
		this.checkAccess();
		
		// Store for later
		this._priority = __p;
		
		// Only set the priority if the thread is active
		int realid = this._realid;
		if (realid >= 0)
			TaskAccess.setThreadPriority(realid, __p);
	}
	
	/**
	 * Starts the specified thread.
	 *
	 * @throws IllegalThreadStateException If the thread was already started
	 * or failed to start.
	 * @since 2018/11/17
	 */
	public void start()
		throws IllegalThreadStateException
	{
		synchronized (this)
		{
			// {@squirreljme.error ZZ21 A thread may only be started once.}
			if (this._started)
				throw new IllegalThreadStateException("ZZ21");
			this._started = true;
			
			// Start the thread
			int realid = TaskAccess.startThread(this, this._name);
			this._realid = realid;
			
			// {@squirreljme.error ZZ22 Could not start the thread.}
			if (realid < 0)
				throw new RuntimeException("ZZ22");
			
			// Set the initial priority of the thread
			TaskAccess.setThreadPriority(realid, this._priority);
			this._isalive = true;
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/20
	 */







|
<
<
|















|

<

<
<
<
<
|
|
|
<
<
<
<







369
370
371
372
373
374
375
376


377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

395




396
397
398




399
400
401
402
403
404
405
		
		// Check access
		this.checkAccess();
		
		// Store for later
		this._priority = __p;
		
		// Set the thread's hardware priority


		ThreadShelf.vmThreadSetPriority(this._vmThread, __p);
	}
	
	/**
	 * Starts the specified thread.
	 *
	 * @throws IllegalThreadStateException If the thread was already started
	 * or failed to start.
	 * @since 2018/11/17
	 */
	public void start()
		throws IllegalThreadStateException
	{
		synchronized (this)
		{
			// {@squirreljme.error ZZ21 A thread may only be started once.}
			if (ThreadShelf.javaThreadIsStarted(this))
				throw new IllegalThreadStateException("ZZ21");

			




			// {@squirreljme.error ZZ22 Failed to start the thread.}
			if (!ThreadShelf.vmThreadStart(this._vmThread))
				throw new IllegalThreadStateException("ZZ22");




		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/20
	 */
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580



581
582
583
584
585
586
587
588

589
590
591
592
593
594
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774


775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
	 * Returns the number of threads which are currently alive.
	 *
	 * @return The number of alive threads.
	 * @since 2018/11/20
	 */
	public static int activeCount()
	{
		return Thread._ACTIVE_THREADS;

	}
	
	/**
	 * Returns the current thread.
	 *
	 * @return The current thread.
	 * @since 2018/11/20
	 */
	public static Thread currentThread()
	{
		int rid = TaskAccess.currentThread();
		
		// If the map is not initialized yet, ignore
		Map<Integer, Thread> byrealid = Thread._BY_REALID;
		if (byrealid == null)
			return null;
		
		// Lock, it should be in the map
		synchronized (Thread.class)
		{
			return byrealid.get(rid);
		}
	}
	
	/**
	 * Checks if the current thread holds the monitor for the given object.
	 *
	 * @param __o The object to check.
	 * @return If the thread owns the monitor.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/21
	 */
	public static boolean holdsLock(Object __o)
		throws NullPointerException
	{
		if (__o == null)
			throw new NullPointerException("NARG");
		
		return ObjectAccess.holdsLock(TaskAccess.currentThread(), __o);
	}
	
	/**
	 * Checks if the current thread was interrupted, if it was then the
	 * interrupt status will be cleared.
	 *
	 * @return If this thread was interrupted.
	 * @since 2018/11/21
	 */
	public static boolean interrupted()
	{
		Thread self = Thread.currentThread();
		
		// Check interrupt?
		boolean rv = self._interrupted;
		self._interrupted = false;
		return rv;
	}
	
	/**
	 * Causes the thread to sleep for the given amount of milliseconds.
	 *
	 * @param __ms The number of milliseconds to sleep for.
	 * @throws InterruptedException If the thread was interrupted.
	 * @since 2018/11/04
	 */
	public static void sleep(long __ms)
		throws InterruptedException
	{
		Thread.sleep(__ms, 0);
	}
	
	/**
	 * Causes the thread to sleep for the given milliseconds and nanoseconds.



	 *
	 * @param __ms The milliseconds to sleep for.
	 * @param __ns The nanoseconds to sleep for, in the range of 0-999999.
	 * @throws IllegalArgumentException If the milliseconds and/or nanoseconds
	 * are out of range.
	 * @throws InterruptedException If the thread was interrupted.
	 * @since 2018/11/04
	 */

	public static void sleep(long __ms, int __ns)
		throws IllegalArgumentException, InterruptedException
	{
		// {@squirreljme.error ZZ23 Invalid sleep arguments.}
		if (__ms < 0 || __ns < 0 || __ns > 999999)
			throw new IllegalArgumentException("ZZ23");
		
		// Convert to integer but do not sleep for too long
		int ims = (__ms > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)__ms);
		
		// Perform sleep, if it was interrupted then the return status will
		// be non-zero!
		if (Assembly.sysCallV(SystemCallIndex.SLEEP, ims, __ns) != 0)
		{

			Thread.currentThread()._interrupted = false;
			
			// {@squirreljme.error ZZ24 Sleep was interrupted.}
			throw new InterruptedException("ZZ24");
		}
	}
	
	/**
	 * Yields the current thread giving up its execution slice, but allowing
	 * it to continue instantly resuming as needed.
	 *
	 * @since 2018/12/05
	 */
	public static void yield()
	{
		// Zero times means to yield
		Assembly.sysCallV(SystemCallIndex.SLEEP, 0, 0);
	}
	
	/**
	 * Registers this thread so that way it is in the thread list and can be
	 * obtained and such.
	 *
	 * @since 2018/12/03
	 */
	final void __registerThread()
	{
		// Lock
		synchronized (Thread.class)
		{
			// Increase the active thread count
			Thread._ACTIVE_THREADS++;
			
			// Add threads to the thread list
			Map<Integer, Thread> byvirtid = Thread._BY_VIRTID,
				byrealid = Thread._BY_REALID;
			byvirtid.put(this._virtid, this);
			byrealid.put(this._realid, this);
		}
	}
	
	/**
	 * Ends the current thread and cleans up its registration.
	 *
	 * @since 2018/12/03
	 */
	final void __revokeThread()
	{
		// Thread no longer alive
		this._isalive = false;
		
		// Lock
		synchronized (Thread.class)
		{
			// Decrease the active count
			Thread._ACTIVE_THREADS--;
			
			// Remove from the thread list
			Map<Integer, Thread> byvirtid = Thread._BY_VIRTID,
				byrealid = Thread._BY_REALID;
			byvirtid.remove(this._virtid);
			byrealid.remove(this._realid);
		}
		
		// Signal all threads which are waiting on a join for this thread
		// only
		synchronized (this)
		{
			this.notifyAll();
		}
		
		// Signal anything waiting on the class itself, to indicate that
		// a thread has finished
		int startkind = this._startkind;
		if (startkind != Thread._START_MAIN && startkind != Thread._START_MIDLET)
			synchronized (Thread.class)
			{
				Thread.class.notifyAll();
			}
	}
	
	/**
	 * This is the starting point for all threads, including the main thread
	 * and such.
	 *
	 * @throws IllegalThreadStateException If the thread has already been
	 * started.
	 * @since 2018/11/20
	 */
	@ImplementationNote("This is the starting point of all threads.")
	final void __start()
		throws IllegalThreadStateException
	{
		// Get the kind and determine if this is a main entry point
		int startkind = this._startkind;
		boolean ismain = (startkind == Thread._START_MAIN ||
			startkind == Thread._START_MIDLET);
		
		// We need to lock because the real ID might just not get assigned
		// yet here.
		int realid;
		int virtid = this._virtid;
		if (!ismain)
			synchronized (this)
			{
				// {@squirreljme.error ZZ25 Real ID has not been set yet while
				// in the lock, this should not occur unless the virtual
				// machine is very broken.}
				if ((realid = this._realid) < 0)
					throw new Error("ZZ25");
			}
		
		// Main thread, so set our real ID to the current thread the VM says
		// we are since it will still be negatively initialized 
		else
		{
			realid = TaskAccess.currentThread();
			this._realid = realid;
		}
		
		// The exit code is something that is only handled by the main thread
		// It will exit with the given code 
		int exitcode = 0;
		
		// Execution setup
		try
		{
			// Register this thread
			this.__registerThread();
				
			// Set the thread as alive
			this._isalive = true;
			
			// The main method and/or its arguments
			StaticMethod runmethod = this._runmethod;
			Object runargument = this._runargument;
			
			// How do we run this thread?
			switch (this._startkind)
			{
					// Start Runnable in this instance (extended from)
				case Thread._START_SELF_RUNNABLE:
					this.run();
					break;
					
					// Start the given runnable
				case Thread._START_GIVEN_RUNNABLE:
					((Runnable)runargument).run();
					break;
					
					// Start MIDlet, construct then startApp()
				case Thread._START_MIDLET:
					ObjectAccess.invokeStatic(runmethod,
						ObjectAccess.classByName((String)runargument).
						__newInstance());
					break;
					
					// Start main(String[]) method
				case Thread._START_MAIN:
					ObjectAccess.invokeStatic(runmethod, runargument);
					break;
					
					// Unknown
				default:
					throw new todo.OOPS();
			}
		}
		
		// Uncaught exception
		catch (Throwable t)
		{
			// Set the exit code for the process to some error number, if


			// the VM does not exit in this thread but exits in another
			// it would at least be set for the main thread
			// But this is only needed for the main thread
			if (ismain)
				exitcode = 127;
			
			// Handle uncaught exception
			UncaughtExceptionHandler.handle(t);
		}
		
		// Cleanup after the thread:
		//  * Signal joins (for those that are waiting)
		//  * Remove the thread from the thread list
		//  * Decrease the active count
		//  * Set thread as not alive
		finally
		{
			// Revoke this thread
			this.__revokeThread();
		}
		
		// If this is the main thread, wait for every other thread to
		// stop execution. This saves the VM execution code itself from
		// worrying about which threads are running or not.
		if (ismain)
		{
			// Wait for threads to go away
			for (;;)
			{
				// No threads are active, so that works
				if (Thread._ACTIVE_THREADS == 0)
					break;
				
				// Wait a bit until trying again, unless we get notified
				synchronized (Thread.class)
				{
					try
					{
						// Three seconds is short enough to not be forever
						// but long enough to where we can get a notify to
						// quit
						Thread.class.wait(3_000);
					}
					catch (InterruptedException e)
					{
					}
				}
			}
			
			// Exit the VM with our normal exit code, since no other
			// thread called exit at all for this point
			Assembly.sysCall(SystemCallIndex.EXIT, exitcode);
		}
	}
}








|
>










<
<
<
<
<
|
<
<
<
<
<
<
















|











<
|
<
<
<
<

















>
>
>








>












|

>
|















<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<

<
|
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
|
<
<
<
|
|
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
|
<
<
|
<
<
<
<
|
<
<
<
<
<
|
|
<
|
<
>
>
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<



415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433





434






435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

463




464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523


524







525





526





527

528






529



530




531





532




























































533





534


535



536
537






538




539



540


541




542





543
544

545

546
547





548



549





550




551




552






553















554




555
556
557
	 * Returns the number of threads which are currently alive.
	 *
	 * @return The number of alive threads.
	 * @since 2018/11/20
	 */
	public static int activeCount()
	{
		return ThreadShelf.aliveThreadCount(
			true, true);
	}
	
	/**
	 * Returns the current thread.
	 *
	 * @return The current thread.
	 * @since 2018/11/20
	 */
	public static Thread currentThread()
	{





		return ThreadShelf.currentJavaThread();






	}
	
	/**
	 * Checks if the current thread holds the monitor for the given object.
	 *
	 * @param __o The object to check.
	 * @return If the thread owns the monitor.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/21
	 */
	public static boolean holdsLock(Object __o)
		throws NullPointerException
	{
		if (__o == null)
			throw new NullPointerException("NARG");
		
		return ObjectShelf.holdsLock(ThreadShelf.currentJavaThread(), __o);
	}
	
	/**
	 * Checks if the current thread was interrupted, if it was then the
	 * interrupt status will be cleared.
	 *
	 * @return If this thread was interrupted.
	 * @since 2018/11/21
	 */
	public static boolean interrupted()
	{

		return ThreadShelf.javaThreadClearInterrupt(Thread.currentThread());




	}
	
	/**
	 * Causes the thread to sleep for the given amount of milliseconds.
	 *
	 * @param __ms The number of milliseconds to sleep for.
	 * @throws InterruptedException If the thread was interrupted.
	 * @since 2018/11/04
	 */
	public static void sleep(long __ms)
		throws InterruptedException
	{
		Thread.sleep(__ms, 0);
	}
	
	/**
	 * Causes the thread to sleep for the given milliseconds and nanoseconds.
	 * 
	 * If the current thread is interrupted, then the interrupt status will
	 * be cleared for the current thread.
	 *
	 * @param __ms The milliseconds to sleep for.
	 * @param __ns The nanoseconds to sleep for, in the range of 0-999999.
	 * @throws IllegalArgumentException If the milliseconds and/or nanoseconds
	 * are out of range.
	 * @throws InterruptedException If the thread was interrupted.
	 * @since 2018/11/04
	 */
	@SuppressWarnings("MagicNumber")
	public static void sleep(long __ms, int __ns)
		throws IllegalArgumentException, InterruptedException
	{
		// {@squirreljme.error ZZ23 Invalid sleep arguments.}
		if (__ms < 0 || __ns < 0 || __ns > 999999)
			throw new IllegalArgumentException("ZZ23");
		
		// Convert to integer but do not sleep for too long
		int ims = (__ms > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)__ms);
		
		// Perform sleep, if it was interrupted then the return status will
		// be non-zero!
		if (ThreadShelf.sleep(ims, __ns))
		{
			// The interrupt status becomes cleared for our current thread
			ThreadShelf.javaThreadClearInterrupt(Thread.currentThread());
			
			// {@squirreljme.error ZZ24 Sleep was interrupted.}
			throw new InterruptedException("ZZ24");
		}
	}
	
	/**
	 * Yields the current thread giving up its execution slice, but allowing
	 * it to continue instantly resuming as needed.
	 *
	 * @since 2018/12/05
	 */
	public static void yield()
	{
		// Zero times means to yield


		try







		{





			Thread.sleep(0, 0);





		}

		catch (InterruptedException ignored)






		{



			// Ignore




		}





	}




























































	





	/**


	 * Determines a default name for the given thread.



	 *
	 * @param __name The supplied name of the thread.






	 * @param __vm The virtual machine thread.




	 * @return The name to use for the thread.



	 * @throws NullPointerException On null arguments.


	 * @since 2020/06/17




	 */





	private static String __defaultName(String __name, VMThreadBracket __vm)
		throws NullPointerException

	{

		if (__vm == null)
			throw new NullPointerException("NARG");





		



		// Use the given name





		if (__name != null)




			return __name;




		






		// Otherwise it is just the attached thread ID















		return "Thread-" + ThreadShelf.vmThreadId(__vm);




	}
}

Changes to modules/cldc-compact/src/main/java/java/lang/Throwable.java.

1
2
3
4
5
6
7
8
9
10
11
12


13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69
70

71

72
73
74
75
76
77
78
79
80
81

82

83
84
85
86
87
88
89
90
91
92

93




94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;



import cc.squirreljme.runtime.cldc.debug.CallTraceElement;
import java.io.PrintStream;


/**
 * This class is the base class for all types which are thrown, itself being a
 * checked exception handled by the compiler.
 *
 * Each {@link Throwable} contains internal stack trace information which is
 * initialized when the {@link Throwable} is.
 *
 * A {@link Throwable} may have suppressed exceptions, which are exceptions
 * which may be added to a {@link Throwable} to indicate that there was an
 * exception that was caused in a try-with-resources when the resource was
 * attempted to be closed.
 *
 * @since 2018/09/15
 */
public class Throwable
{
	/** Exception message. */
	private static final int _TYPE_EXCEPTION =
		0;
	
	/** Caused by message. */
	private static final int _TYPE_CAUSED_BY =
		1;
	
	/** Suppressed message. */
	private static final int _TYPE_SUPPRESSED =
		2;
	
	/** The message for this exception. */
	private final String _message;
	
	/** Suppressed exceptions. */
	private volatile Throwable[] _suppressed;
	
	/** Was a cause initialized already? */
	private volatile boolean _initcause;
	
	/**
	 * The cause of this exception, note this is writeable because of
	 * {@link #initCause(Throwable)}. This is mostly just for older versions
	 * of the class library which did not have a cause specified in the
	 * constructor.
	 */
	private volatile Throwable _cause;
	
	/** The stack trace for this throwable (in raw form). */

	private volatile int[] _stack;
	
	/**
	 * Initializes a throwable with no cause or message.
	 *
	 * @since 2018/09/15
	 */
	public Throwable()
	{

		this(false, 2, null, null);

	}
	
	/**
	 * Initializes a throwable with the given message and no cause.
	 *
	 * @param __m The message.
	 * @since 2018/09/15
	 */
	public Throwable(String __m)
	{

		this(false, 2, __m, null);

	}
	
	/**
	 * Initializes a throwable with the given cause and no message.
	 *
	 * @param __t The cause.
	 * @since 2018/09/15
	 */
	public Throwable(Throwable __t)
	{

		this(true, 2, null, __t);




	}
	
	/**
	 * Initializes a throwable with the given cause and cause.
	 *
	 * @param __m The message.
	 * @param __t The cause.
	 * @since 2018/09/15
	 */
	public Throwable(String __m, Throwable __t)
	{
		this(true, 2, __m, __t);
	}
	
	/**
	 * Since the cause can only be set once, this constructor needs to keep
	 * track of whether it was set by a constructor or not.
	 *
	 * @param __ic Is the cause initialized?
	 * @param __clip The number of stack trace entries to clip.
	 * @param __m The exception message.
	 * @param __t The cause.
	 * @since 2018/09/15
	 */
	private Throwable(boolean __ic, int __clip, String __m, Throwable __t)
	{
		// These are trivially set
		this._message = __m;
		this._cause = __t;
		this._initcause = __ic;
		
		// The stack trace is implicitly filled in by this constructor, it
		// matches the stack trace of the current thread of execution
		this._stack = this.__getStackTrace(this, __clip, true);
	}
	
	/**
	 * Adds a suppressed throwable which will be thrown alongside this
	 * throwable. This is mainly used with try-with-resources although a
	 * programmer may wish to add related throwables that additionally
	 * happened.
	 *
	 * This method is thread safe.
	 *
	 * @param __t The throwable to suppress.
	 * @throws IllegalArgumentException If the passed throwable is this.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/15
	 */
	public final void addSuppressed(Throwable __t)
		throws IllegalArgumentException, NullPointerException
	{
		if (__t == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ26 Cannot add a suppressed exception which
		// is this exception.}
		if (__t == this)
			throw new IllegalArgumentException("ZZ26");
		
		// Just lock on this to add suppressed exceptions, it is unspecified
		// where the lock is done, but this prevent creation of an object just
		// to hold a lock.
		synchronized (this)
		{
			// No suppressed exceptions were set, initialize
			Throwable[] suppressed = this._suppressed;
			if (suppressed == null)
				this._suppressed = new Throwable[]{__t};
			
			// Otherwise rebuild the array and add it
			else
			{

				int n = suppressed.length;
				Throwable[] copy = new Throwable[n + 1];
				for (int i = 0; i < n; i++)
					copy[i] = suppressed[i];
				copy[n] = __t;
				
				// Use this instead
				this._suppressed = copy;
			}
		}
	}
	
	/**
	 * Fills in the stack trace of this throwable for the current thread.
	 *
	 * @return {@code this}.
	 * @since 2018/09/15
	 */
	public Throwable fillInStackTrace()
	{
		// Get stack trace, ignore this method
		this._stack = this.__getStackTrace(this, 1, false);
		
		// Returns self
		return this;
	}
	
	/**
	 * Returns the throwable which caused this throwable to occur.
	 *
	 * @return The throwable which caused this throwable.












>
>
|

>

















<
<
<
<
<
<
<
<
<
<
<
<




|


|







|

|
>
|








>
|
>










>
|
>










>
|
>
>
>
>











<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
|

<

<
<
|





|




















<
<
<
<
<
|
|
|
|
|
|
|
|
>
|
|
|
<
|
|
|
|
<












|

<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34












35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105


106



107









108
109

110


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137





138
139
140
141
142
143
144
145
146
147
148
149

150
151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.DebugShelf;
import cc.squirreljme.jvm.mle.brackets.TracePointBracket;
import cc.squirreljme.runtime.cldc.debug.CallTraceUtils;
import java.io.PrintStream;
import java.util.Arrays;

/**
 * This class is the base class for all types which are thrown, itself being a
 * checked exception handled by the compiler.
 *
 * Each {@link Throwable} contains internal stack trace information which is
 * initialized when the {@link Throwable} is.
 *
 * A {@link Throwable} may have suppressed exceptions, which are exceptions
 * which may be added to a {@link Throwable} to indicate that there was an
 * exception that was caused in a try-with-resources when the resource was
 * attempted to be closed.
 *
 * @since 2018/09/15
 */
public class Throwable
{












	/** The message for this exception. */
	private final String _message;
	
	/** Suppressed exceptions. */
	private Throwable[] _suppressed;
	
	/** Was a cause initialized already? */
	private boolean _initCause;
	
	/**
	 * The cause of this exception, note this is writeable because of
	 * {@link #initCause(Throwable)}. This is mostly just for older versions
	 * of the class library which did not have a cause specified in the
	 * constructor.
	 */
	private Throwable _cause;
	
	/** The stack trace for this throwable (in mostly-raw form). */
	@SuppressWarnings("unused")
	private TracePointBracket[] _stack;
	
	/**
	 * Initializes a throwable with no cause or message.
	 *
	 * @since 2018/09/15
	 */
	public Throwable()
	{
		this._message = null;
		
		this._stack = DebugShelf.traceStack();
	}
	
	/**
	 * Initializes a throwable with the given message and no cause.
	 *
	 * @param __m The message.
	 * @since 2018/09/15
	 */
	public Throwable(String __m)
	{
		this._message = __m;
		
		this._stack = DebugShelf.traceStack();
	}
	
	/**
	 * Initializes a throwable with the given cause and no message.
	 *
	 * @param __t The cause.
	 * @since 2018/09/15
	 */
	public Throwable(Throwable __t)
	{
		this._message = null;
		
		this._initCause = true;
		this._cause = __t;
		
		this._stack = DebugShelf.traceStack();
	}
	
	/**
	 * Initializes a throwable with the given cause and cause.
	 *
	 * @param __m The message.
	 * @param __t The cause.
	 * @since 2018/09/15
	 */
	public Throwable(String __m, Throwable __t)
	{


		this._message = __m;



		









		this._initCause = true;
		this._cause = __t;

		


		this._stack = DebugShelf.traceStack();
	}
	
	/**
	 * Adds a suppressed throwable which will be thrown alongside this
	 * throwable. This is mainly used with try-with-resources although a
	 * programmer may wish to add related {@link Throwable}s that additionally
	 * happened.
	 *
	 * This method is thread safe.
	 *
	 * @param __t The throwable to suppress.
	 * @throws IllegalArgumentException If the passed throwable is this.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/15
	 */
	public final void addSuppressed(Throwable __t)
		throws IllegalArgumentException, NullPointerException
	{
		if (__t == null)
			throw new NullPointerException("NARG");
		
		// {@squirreljme.error ZZ26 Cannot add a suppressed exception which
		// is this exception.}
		if (__t == this)
			throw new IllegalArgumentException("ZZ26");
		





		// No suppressed exceptions were set, initialize
		Throwable[] suppressed = this._suppressed;
		if (suppressed == null)
			this._suppressed = new Throwable[]{__t};
		
		// Otherwise rebuild the array and add it
		else
		{
			// Add one extra spot to this array
			int n = suppressed.length;
			suppressed = Arrays.copyOf(suppressed, n + 1);
			

			suppressed[n] = __t;
			
			// Use this new one instead
			this._suppressed = suppressed;

		}
	}
	
	/**
	 * Fills in the stack trace of this throwable for the current thread.
	 *
	 * @return {@code this}.
	 * @since 2018/09/15
	 */
	public Throwable fillInStackTrace()
	{
		// Get stack trace, ignore this method
		this._stack = DebugShelf.traceStack();
		

		return this;
	}
	
	/**
	 * Returns the throwable which caused this throwable to occur.
	 *
	 * @return The throwable which caused this throwable.
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
	 */
	public String getMessage()
	{
		return this._message;
	}
	
	/**
	 * Returns an array of all the throwables which were suppressed.
	 *
	 * This method is thread safe.
	 *
	 * @return An array of all the suppresed throwables.
	 * @since 2018/09/15
	 */
	public final Throwable[] getSuppressed()
	{
		// Since this is volatile we can just read whatever value is here
		// without needing to lock
		Throwable[] rv = this._suppressed;
		if (rv == null)
			return new Throwable[0];
		return rv.clone();
	}
	
	/**
	 * Initializes the cause of the throwable if it has not been set.
	 *
	 * Calls to {@link #initCause(Throwable)}, {@link #Throwable(Throwable)},
	 * or {@link #Throwable(String, Throwable)} will cause the cause to be
	 * initialized, preventing this from being called or called again.
	 *
	 * @param __t The cause of the throwable.
	 * @return {@code this}.
	 * @throws IllegalArgumentException If the cause is this throwable.
	 * @throws IllegalStateException If a cause has already been set.
	 * @since 2018/09/15
	 */
	public Throwable initCause(Throwable __t)
		throws IllegalArgumentException, IllegalStateException
	{
		// {@squirreljme.error ZZ27 Cannot initialize the cause of the
		// throwable with itself as the cause.}
		if (__t == this)
			throw new IllegalArgumentException("ZZ27");
		
		// {@squirreljme.error ZZ28 The cause of the throwable has already
		// been initialized.}
		if (this._initcause)
			throw new IllegalStateException("ZZ28");
		
		// Set
		this._initcause = true;
		this._cause = __t;
		
		return this;
	}
	
	/**
	 * Prints the stack trace to the standard error stream.
	 *
	 * @since 2018/09/15
	 */
	public void printStackTrace()
	{
		Throwable.__printStackTrace(this, System.err, 0,
			Throwable._TYPE_EXCEPTION);
	}
	
	/**
	 * Prints the stack trace to the specified stream.
	 *
	 * @param __ps The stream to print to.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/15
	 */
	public void printStackTrace(PrintStream __ps)
		throws NullPointerException
	{
		if (__ps == null)
			throw new NullPointerException("NARG");
		
		Throwable.__printStackTrace(this, __ps, 0, Throwable._TYPE_EXCEPTION);
	}
	
	/**
	 * Returns a string representation of this throwable.
	 *
	 * If there is a localized message, the form is {@code <class>: <message>}.
	 * If there is no message, the form is {@code <class>}.
	 *
	 * @return A string representing this throwable.
	 * @since 2018/09/15
	 */
	@Override
	public String toString()
	{
		String clname = this.getClass().getName(),
			lm = this.getLocalizedMessage();
		
		if (lm == null)
			return clname;
		return clname + ": " + lm;
	}
	
	/**
	 * Obtains the stack trace for the current thread in raw format.
	 *
	 * @param __this The this throwable object.
	 * @param __clip The number of entries on the top to clip.
	 * @param __initclip Clip off initializers?
	 * @return The stack trace for the current stack.
	 * @throws IllegalArgumentException If the clip is negative.
	 * @since 2018/09/16
	 */
	private static int[] __getStackTrace(Throwable __this,
		int __clip, boolean __initclip)
		throws IllegalArgumentException
	{
		// {@squirreljme.error ZZ29 Cannot specify a negative clip for a
		// stack trace.}
		if (__clip < 0)
			throw new IllegalArgumentException("ZZ29");
		
		// Get the raw trace here
		int[] rawstack = CallTraceElement.traceRaw();
		
		// Just use the raw stack
		return rawstack;
	}
	
	/**
	 * Prints the indentation of the stack trace.
	 *
	 * @param __ps The stream to print to.
	 * @param __indent The current indentation.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/11
	 */
	private static void __printStackIndent(PrintStream __ps, int __indent)
		throws NullPointerException
	{
		if (__ps == null)
			throw new NullPointerException("NARG");
		
		// Doing nothing
		if (__indent == 0)
			return;
		
		// Base space indent
		__ps.print("  ");
		
		// Print bars for indentation level
		for (int i = 0; i < __indent; i++)
			__ps.print('|');
	}
	
	/**
	 * Prints the stack trace to the specified stream. This is internal so that
	 * one stack printing does not call the other since it is not specified if
	 * it actually does it.
	 *
	 * @param __t The throwable to print for.
	 * @param __ps The stream to print to.
	 * @param __indent The indentation level.
	 * @param __type The string type to use for the message base.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/15
	 */
	private static void __printStackTrace(Throwable __t, PrintStream __ps,
		int __indent, int __type)
		throws NullPointerException
	{
		if (__t == null || __ps == null)
			throw new NullPointerException("NARG");
		
		// Internally raw stacks are stored since that is the fastest way
		// to generate a stack trace, which will only be resolved when this
		// method is called to print.
		int[] rawstack = __t._stack;
		if (rawstack == null)
		{
			__ps.println("<No stack trace>");
			return;
		}
		
		// Resolve the stack trace so it is easier to work with
		CallTraceElement[] stack = CallTraceElement.traceResolve(rawstack);
		
		// Indent and print exception type
		Throwable.__printStackIndent(__ps, __indent);
		switch (__type)
		{
			case Throwable._TYPE_CAUSED_BY:
				__ps.print("> CAUSED BY ");
				break;
			
			case Throwable._TYPE_SUPPRESSED:
				__ps.print("> SUPPRESSED ");
				break;
			
			case Throwable._TYPE_EXCEPTION:
			default:
				__ps.print("EXCEPTION ");
				break;
		}
		
		// Then the string representation of it, which may be replaced
		__ps.println(__t.toString());
		
		// Increase indentation to get more bars
		__indent++;
		
		// The first entry is the top of the stack so it gets printed first 
		String wasclass = "<Unknown>";
		for (int i = 0, n = stack.length; i < n; i++)
		{
			// Ignore any elements that may happen to be null
			CallTraceElement e = stack[i];
			if (e == null)
				continue;
			
			// Get the element class, always make sure the class is valid
			// even if it is not known
			String nowclass = e.className();
			if (nowclass == null)
				nowclass = "<Unknown>";
			
			// If the class changed, specify that it has
			if (!nowclass.equals(wasclass))
			{
				// Indent
				Throwable.__printStackIndent(__ps, __indent);
				
				__ps.print(" IN ");
				__ps.println(e.toClassHeaderString());
				
				// Changed
				wasclass = nowclass;
			}
			
			// Indent and print the at line
			Throwable.__printStackIndent(__ps, __indent);
			__ps.print("- ");
			__ps.println(e.toAtLineString());
		}
		
		// Print cause of the exception
		Throwable cause = __t.getCause();
		if (cause != null)
			Throwable.__printStackTrace(cause, __ps, __indent,
				Throwable._TYPE_CAUSED_BY);
		
		// Print suppressed exceptions
		for (Throwable sup : __t.getSuppressed())
			Throwable.__printStackTrace(sup, __ps, __indent,
				Throwable._TYPE_SUPPRESSED);
	}
}








|



|




<
<









|



















|



|












|
<















|














|
|


|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215


216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298


























































































































































299
300
301
	 */
	public String getMessage()
	{
		return this._message;
	}
	
	/**
	 * Returns an array of all the {@link Throwable}s which were suppressed.
	 *
	 * This method is thread safe.
	 *
	 * @return An array of all the suppressed {@link Throwable}s.
	 * @since 2018/09/15
	 */
	public final Throwable[] getSuppressed()
	{


		Throwable[] rv = this._suppressed;
		if (rv == null)
			return new Throwable[0];
		return rv.clone();
	}
	
	/**
	 * Initializes the cause of the throwable if it has not been set.
	 *
	 * Calls to this method, {@link #Throwable(Throwable)},
	 * or {@link #Throwable(String, Throwable)} will cause the cause to be
	 * initialized, preventing this from being called or called again.
	 *
	 * @param __t The cause of the throwable.
	 * @return {@code this}.
	 * @throws IllegalArgumentException If the cause is this throwable.
	 * @throws IllegalStateException If a cause has already been set.
	 * @since 2018/09/15
	 */
	public Throwable initCause(Throwable __t)
		throws IllegalArgumentException, IllegalStateException
	{
		// {@squirreljme.error ZZ27 Cannot initialize the cause of the
		// throwable with itself as the cause.}
		if (__t == this)
			throw new IllegalArgumentException("ZZ27");
		
		// {@squirreljme.error ZZ28 The cause of the throwable has already
		// been initialized.}
		if (this._initCause)
			throw new IllegalStateException("ZZ28");
		
		// Set
		this._initCause = true;
		this._cause = __t;
		
		return this;
	}
	
	/**
	 * Prints the stack trace to the standard error stream.
	 *
	 * @since 2018/09/15
	 */
	public void printStackTrace()
	{
		CallTraceUtils.printStackTrace(System.err, this, 0);

	}
	
	/**
	 * Prints the stack trace to the specified stream.
	 *
	 * @param __ps The stream to print to.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/15
	 */
	public void printStackTrace(PrintStream __ps)
		throws NullPointerException
	{
		if (__ps == null)
			throw new NullPointerException("NARG");
		
		CallTraceUtils.printStackTrace(__ps, this, 0);
	}
	
	/**
	 * Returns a string representation of this throwable.
	 *
	 * If there is a localized message, the form is {@code <class>: <message>}.
	 * If there is no message, the form is {@code <class>}.
	 *
	 * @return A string representing this throwable.
	 * @since 2018/09/15
	 */
	@Override
	public String toString()
	{
		String className = this.getClass().getName();
		String lm = this.getLocalizedMessage();
		
		if (lm == null)
			return className;
		return className + ": " + lm;


























































































































































	}
}

Added modules/cldc-compact/src/main/java/java/lang/__Start__.java.











































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.ThreadShelf;
import cc.squirreljme.jvm.mle.brackets.VMThreadBracket;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.cldc.lang.UncaughtExceptionHandler;

/**
 * This is the starting point for every thread regardless of if it is a main
 * thread or a non-main thread.
 *
 * @since 2020/05/31
 */
@SuppressWarnings("unused")
final class __Start__
{
	/** One second in milliseconds. */
	private static final int _MS_SECOND =
		1_000;
	
	/** Exit code for un-handled main exceptions. */
	private static final int _UNHANDLED_EXIT_CODE =
		61;
	
	/**
	 * This is the entry point for any thread which is not a main thread.
	 *
	 * @since 2020/05/31
	 */
	static void __base()
	{
		// Get both of our thread infos
		Thread javaThread = ThreadShelf.currentJavaThread();
		VMThreadBracket vmThread = ThreadShelf.toVMThread(javaThread);
		
		// We will need to catch any exceptions that the thread throws and
		// have some fallback logic for handling it
		try
		{
			// Mark the thread as alive
			ThreadShelf.javaThreadFlagStarted(javaThread);
			ThreadShelf.javaThreadSetAlive(javaThread, true);
			
			// Execute the thread, if we are the main thread we use an
			// alternative run
			if (ThreadShelf.vmThreadIsMain(vmThread))
				ThreadShelf.runProcessMain();
			
			// Use normal run logic
			else
			{
				// Use the thread's runnable or otherwise run the thread itself
				// if none was used
				Runnable run = ThreadShelf.javaThreadRunnable(javaThread);
				if (run == null)
					run = javaThread;
				
				// Execute it
				run.run();
			}
			
			// Mark the thread as dead
			ThreadShelf.javaThreadSetAlive(javaThread, false);
		}
		
		// Missed an exception, so handle it there
		catch (Throwable t)
		{
			// Mark the thread as dead
			ThreadShelf.javaThreadSetAlive(javaThread, false);
			
			// Use the other exception handler
			UncaughtExceptionHandler.handle(t);
			
			// If this is the main thread, now that this thread is exiting
			// unless another exit condition happens this will effectively
			// mean the process fails
			if (ThreadShelf.vmThreadIsMain(vmThread))
				ThreadShelf.setCurrentExitCode(__Start__._UNHANDLED_EXIT_CODE);
		}
	}
	
	/**
	 * This is the entry point for main threads.
	 *
	 * @since 2020/05/31
	 */
	static void __main()
	{
		// Debug
		Debugging.debugNote("Starting main thread...");
		
		// Enter the base thread logic as every thread does the same logic
		__Start__.__base();
		
		// Main thread has terminated, so wait until all other threads have
		// terminated. Only count non-main and non-daemon threads here since
		// otherwise we might have trouble counting everything
		while (ThreadShelf.aliveThreadCount(
			false, false) > 0)
			ThreadShelf.waitForUpdate(__Start__._MS_SECOND);
		
		// Now that the main thread exited, use whatever exit code that was
		// set. This should be zero in most cases.
		RuntimeShelf.exit(ThreadShelf.currentExitCode());
	}
}

Added modules/cldc-compact/src/main/java/java/lang/package-info.java.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This contains the core Java Language libraries which are at the heart of
 * the virtual machine.
 *
 * @since 2020/05/31
 */

package java.lang;

Changes to modules/cldc-compact/src/main/java/java/lang/ref/Reference.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48







49





50





51
52







53






54











55
56
57
58
59
60
61
62
63








64





65


66







67
68

69
70
71
72
73
74
75
76
77
78
79





80
81
82


83




84



85




86
87

88


89
90





91
92
93
94
95
96
97
98
99
100
101
102
103


104








105















106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122


123































// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang.ref;

import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import cc.squirreljme.runtime.cldc.ref.PrimitiveReference;


/**
 * This class represents references which may be referred to using various
 * different means of attachment, as such this family of classes integrates
 * with the garbage collector.
 *
 * @param <T> The type of object to store.
 * @since 2018/09/23
 */

public abstract class Reference<T>
{
	/** The primitive reference used to access the object. */
	private final PrimitiveReference _ref;
	
	/** The queue this reference is in, volatile to be clearned. */
	private volatile ReferenceQueue<? super T> _queue;
	
	/** Has this been enqueued? */
	private volatile boolean _enqueued;
	
	/**
	 * Initializes a reference pointing to the given object and an optionally
	 * specified queue to place this reference into when garbage collection
	 * occurs.
	 *
	 * @param __r The primitive reference storage.
	 * @param __v The object to point to, may be {@code null}.
	 * @param __q When the given object is garbage collected the specified
	 * queue will be given this reference (not {@code __v} itself}, may be
	 * {@code null}
	 * @since 2018/09/23
	 */
	Reference(PrimitiveReference __r, T __v, ReferenceQueue<? super T> __q)
	{







		// Set





		this._ref = __r;





		this._queue = __q;
		







		// Set primitive reference data






		ObjectAccess.referenceSet(__r, __v);











	}
	
	/**
	 * Clears this reference without placing it in the queue.
	 *
	 * @since 2018/09/23
	 */
	public void clear()
	{








		ObjectAccess.referenceSet(this._ref, null);





	}


	







	/**
	 * Places this reference in the queue.

	 *
	 * @return If it was added to the queue then this will return true,
	 * otherwise if there is no queue or it was already added this will
	 * return false.
	 * @since 2018/09/23
	 */
	public boolean enqueue()
	{
		// Already been enqueued
		ReferenceQueue<? super T> queue = this._queue;
		if (this._enqueued || queue == null)





			return false;
		
		// Enqueue it


		queue.__enqueue(this);




		



		// The queue is not needed anymore so there is no need to keep a




		// reference to it around, this will help remove circular references
		// if one forgets to drain the queues.

		this._enqueued = true;


		this._queue = null;
		





		// Was enqueued
		return true;
	}
	
	/**
	 * Returns the object that this reference refers to.
	 *
	 * @return The reference of this object.
	 * @since 2018/09/23
	 */
	@SuppressWarnings({"unchecked"})
	public T get()
	{


		// If the reference was cleared, enqueue it!








		Object rv = ObjectAccess.referenceGet(this._ref);















		if (rv == null)
			this.enqueue();
		
		return (T)rv;
	}
	
	/**
	 * Returns if this reference was enqueued into the reference queue.
	 *
	 * @return If this object was enqueued.
	 * @since 2018/09/23
	 */
	public boolean isEnqueued()
	{
		return this._enqueued;
	}
}














































|
|
>









>


|
|

|
|









<




|

|

>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>


>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>









>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>

|
>








|

|
>
>
>
>
>

|
|
>
>
|
>
>
>
>
|
>
>
>
|
>
>
>
>
|
<
>
|
>
>
|
|
>
>
>
>
>
|
|











>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
















|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang.ref;

import cc.squirreljme.jvm.mle.AtomicShelf;
import cc.squirreljme.jvm.mle.ReferenceShelf;
import cc.squirreljme.jvm.mle.brackets.RefLinkBracket;

/**
 * This class represents references which may be referred to using various
 * different means of attachment, as such this family of classes integrates
 * with the garbage collector.
 *
 * @param <T> The type of object to store.
 * @since 2018/09/23
 */
@SuppressWarnings("AbstractClassWithOnlyOneDirectInheritor")
public abstract class Reference<T>
{
	/** The chain-link for this reference. */
	private final RefLinkBracket _link;
	
	/** The reference queue which this reference will be sent to when freed. */
	private final ReferenceQueue<? super T> _queue;
	
	/** Has this been enqueued? */
	private volatile boolean _enqueued;
	
	/**
	 * Initializes a reference pointing to the given object and an optionally
	 * specified queue to place this reference into when garbage collection
	 * occurs.
	 *

	 * @param __v The object to point to, may be {@code null}.
	 * @param __q When the given object is garbage collected the specified
	 * queue will be given this reference (not {@code __v} itself}, may be
	 * {@code null}
	 * @since 2020/05/30
	 */
	Reference(T __v, ReferenceQueue<? super T> __q)
	{
		// There is no point in reference counting the null object, so have
		// no effect happen here
		if (__v == null)
		{
			this._link = null;
			this._queue = null;
			this._enqueued = true;
			
			return;
		}
		
		// It should be safe to create a new link outside of the lock
		RefLinkBracket link = ReferenceShelf.newLink();
		this._link = link;
		
		// Since nothing else knows about our link yet, we may set the object
		ReferenceShelf.linkSetObject(link, __v);
		
		// Although there is an optimization
		this._queue = __q;
		
		// Must lock the GC since we will be adding a chain to an object
		int key = 0;
		try
		{
			// Spinlock on the GC
			for (int c = 0; (0 == (key = AtomicShelf.gcLock())); c++)
				AtomicShelf.spinLock(c);
			
			// If the object has an existing link, then we need to chain links
			RefLinkBracket oldLink = ReferenceShelf.objectGet(__v);
			if (oldLink != null)
			{
				// New link -> Old link
				ReferenceShelf.linkSetNext(link, oldLink);
				
				// New link <- Old link
				ReferenceShelf.linkSetPrev(oldLink, link);
			}
			
			// The object uses the current link as the head now
			ReferenceShelf.objectSet(__v, link);
		}
		finally
		{
			AtomicShelf.gcUnlock(key);
		}
	}
	
	/**
	 * Clears this reference without placing it in the queue.
	 *
	 * @since 2018/09/23
	 */
	public void clear()
	{
		// Lock the GC just in case this link is being used that it does not
		// mess up anything else
		int key = 0;
		try
		{
			// Spinlock on the GC
			for (int c = 0; (0 == (key = AtomicShelf.gcLock())); c++)
				AtomicShelf.spinLock(c);
			
			// Only unlink once
			if (!this._enqueued)
			{
				// Un-link this link
				this.__unLinkAndClear();
				
				// Mark this reference as enqueued
				this._enqueued = true;
			}
		}
		finally
		{
			AtomicShelf.gcUnlock(key);
		}
	}
	
	/**
	 * Places this reference in the queue and removes the reference, if there
	 * is no queue this will be the same as {@link #clear()}.
	 *
	 * @return If it was added to the queue then this will return true,
	 * otherwise if there is no queue or it was already added this will
	 * return false.
	 * @since 2018/09/23
	 */
	public boolean enqueue()
	{
		// If there is no queue then this has the same effect as clear
		ReferenceQueue<? super T> queue = this._queue;
		if (queue == null)
		{
			this.clear();
			
			// Was not actually pushed to the queue, but the reference is now
			// invalid
			return false;
		}
		
		// Will this get pushed to the queue?
		boolean pushToQueue;
		
		// Lock the GC just in case this link is being used that it does not
		// mess up anything else
		int key = 0;
		try
		{
			// Spinlock on the GC
			for (int c = 0; (0 == (key = AtomicShelf.gcLock())); c++)
				AtomicShelf.spinLock(c);
			
			// Placing this in the queue invalidates it
			pushToQueue = !this._enqueued;
			if (pushToQueue)
			{
				// The reference no longer is valid

				this.__unLinkAndClear();
				this._enqueued = true;
			}
		}
		finally
		{
			AtomicShelf.gcUnlock(key);
		}
		
		// Only push to the queue if was requested
		if (pushToQueue)
			queue.__enqueue(this);
		return pushToQueue;
	}
	
	/**
	 * Returns the object that this reference refers to.
	 *
	 * @return The reference of this object.
	 * @since 2018/09/23
	 */
	@SuppressWarnings({"unchecked"})
	public T get()
	{
		// The return value, if this is null then this gets enqueued
		Object rv;
		
		// Lock the GC just in case this link is being used that it does not
		// mess up anything else
		int key = 0;
		try
		{
			// Spinlock on the GC
			for (int c = 0; (0 == (key = AtomicShelf.gcLock())); c++)
				AtomicShelf.spinLock(c);
			
			// If this was enqueued, then just return nothing
			if (this._enqueued)
				return null;
			
			// Otherwise use what the link says our object is
			rv = ReferenceShelf.linkGetObject(this._link);
		}
		finally
		{
			AtomicShelf.gcUnlock(key);
		}
		
		// If no object was set or was cleared out (perhaps by unlink) then
		// just inform that enqueue happened. Since this enqueue is here, it
		// is very possible that enqueuing happens at the last moment.
		if (rv == null)
			this.enqueue();
		
		return (T)rv;
	}
	
	/**
	 * Returns if this reference was enqueued into the reference queue.
	 *
	 * @return If this object was enqueued.
	 * @since 2018/09/23
	 */
	public boolean isEnqueued()
	{
		return this._enqueued;
	}
	
	/**
	 * Un-links this chain.
	 *
	 * @since 2020/05/30
	 */
	private void __unLinkAndClear()
	{
		RefLinkBracket link = this._link;
		
		// Get the previous and next links to re-chain
		RefLinkBracket prev = ReferenceShelf.linkGetPrev(link);
		RefLinkBracket next = ReferenceShelf.linkGetNext(link);
		
		// Have the previous link point to our next
		if (prev != null)
			ReferenceShelf.linkSetNext(prev, next);
		
		// Have the next link point to our previous
		if (next != null)
			ReferenceShelf.linkSetPrev(next, prev);
		
		// Clear our links because they are no longer valid
		ReferenceShelf.linkSetPrev(link, null);
		ReferenceShelf.linkSetNext(link, null);
		
		// Clear the object this links to
		ReferenceShelf.linkSetObject(link, null);
		
		// We can delete our link now and free any associated memory because
		// it is dangling and serves no purpose otherwise
		ReferenceShelf.deleteLink(link);
	}
}

Changes to modules/cldc-compact/src/main/java/java/lang/ref/ReferenceQueue.java.

122
123
124
125
126
127
128

129
130
131
132
133
134
135
	
	/**
	 * Enqueues the reference into this queue.
	 *
	 * @param __ref The reference to enqueue.
	 * @since 2018/09/23
	 */

	final void __enqueue(Reference<? extends T> __ref)
	{
		// Just ignore and do nothing
		if (__ref == null)
			return;
		
		// Lock on the queue to add it







>







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
	
	/**
	 * Enqueues the reference into this queue.
	 *
	 * @param __ref The reference to enqueue.
	 * @since 2018/09/23
	 */
	@SuppressWarnings("unused")
	final void __enqueue(Reference<? extends T> __ref)
	{
		// Just ignore and do nothing
		if (__ref == null)
			return;
		
		// Lock on the queue to add it

Changes to modules/cldc-compact/src/main/java/java/lang/ref/WeakReference.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang.ref;

import cc.squirreljme.runtime.cldc.asm.ObjectAccess;

/**
 * A weak reference is one which is garbage collected when there are no strong
 * references to it.
 *
 * @param <T> The type of object to store.
 * @since 2018/09/23
 */
public class WeakReference<T>
	extends Reference<T>
{
	/**
	 * Initializes a reference pointing to the given object.
	 *
	 * @param __v The object to point to, may be {@code null}.
	 * @since 2018/09/23
	 */
	public WeakReference(T __v)
	{
		super(ObjectAccess.newWeakReference(), __v, null);
	}
	
	/**
	 * Initializes a reference pointing to the given object and an optionally
	 * specified queue to place this reference into when garbage collection
	 * occurs.
	 *
	 * @param __v The object to point to, may be {@code null}.
	 * @param __q When the given object is garbage collected the specified
	 * queue will be given this reference (not {@code __v} itself}, may be
	 * {@code null}
	 * @since 2018/09/23
	 */
	public WeakReference(T __v, ReferenceQueue<? super T> __q)
	{
		super(ObjectAccess.newWeakReference(), __v, __q);
	}
}













<
<


















|















|



1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.lang.ref;



/**
 * A weak reference is one which is garbage collected when there are no strong
 * references to it.
 *
 * @param <T> The type of object to store.
 * @since 2018/09/23
 */
public class WeakReference<T>
	extends Reference<T>
{
	/**
	 * Initializes a reference pointing to the given object.
	 *
	 * @param __v The object to point to, may be {@code null}.
	 * @since 2018/09/23
	 */
	public WeakReference(T __v)
	{
		super(__v, null);
	}
	
	/**
	 * Initializes a reference pointing to the given object and an optionally
	 * specified queue to place this reference into when garbage collection
	 * occurs.
	 *
	 * @param __v The object to point to, may be {@code null}.
	 * @param __q When the given object is garbage collected the specified
	 * queue will be given this reference (not {@code __v} itself}, may be
	 * {@code null}
	 * @since 2018/09/23
	 */
	public WeakReference(T __v, ReferenceQueue<? super T> __q)
	{
		super(__v, __q);
	}
}

Changes to modules/cldc-compact/src/main/java/java/util/AbstractCollection.java.

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
	 * @since 2018/12/06
	 */
	@Override
	public boolean contains(Object __v)
	{
		// Slow as it checks each entry
		for (E e : this)
			if (__v == null ? e == null : __v.equals(e))
				return true;
		
		// Not found
		return false;
	}
	
	/**







|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
	 * @since 2018/12/06
	 */
	@Override
	public boolean contains(Object __v)
	{
		// Slow as it checks each entry
		for (E e : this)
			if (Objects.equals(__v, e))
				return true;
		
		// Not found
		return false;
	}
	
	/**
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	@Override
	public boolean remove(Object __v)
	{
		// Find it and remove it
		for (Iterator<E> it = this.iterator(); it.hasNext();)
		{
			E e = it.next();
			if (__v == null ? e == null : __v.equals(e))
			{
				it.remove();
				return true;
			}
		}
		
		// No changes







|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	@Override
	public boolean remove(Object __v)
	{
		// Find it and remove it
		for (Iterator<E> it = this.iterator(); it.hasNext();)
		{
			E e = it.next();
			if (Objects.equals(__v, e))
			{
				it.remove();
				return true;
			}
		}
		
		// No changes
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
	 */
	@Override
	public Object[] toArray()
	{
		int n = this.size();
		Object[] rv = new Object[n];
		int i = 0;
		for (Iterator<E> it = this.iterator(); it.hasNext();)
			rv[i++] = it.next();
		
		return rv;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/10/10







|
|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
	 */
	@Override
	public Object[] toArray()
	{
		int n = this.size();
		Object[] rv = new Object[n];
		int i = 0;
		for (E __e : this)
			rv[i++] = __e;
		
		return rv;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/10/10
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
	@Override
	public String toString()
	{
		StringBuilder sb = new StringBuilder("[");
		
		// Build string
		boolean comma = false;
		for (Iterator<E> it = this.iterator(); it.hasNext();)
		{
			// Add comma
			if (comma)
				sb.append(", ");
			comma = true;
			
			// Add item
			sb.append(it.next());
		}
		
		sb.append("]");
		return sb.toString();
	}
}








|







|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
	@Override
	public String toString()
	{
		StringBuilder sb = new StringBuilder("[");
		
		// Build string
		boolean comma = false;
		for (E __e : this)
		{
			// Add comma
			if (comma)
				sb.append(", ");
			comma = true;
			
			// Add item
			sb.append(__e);
		}
		
		sb.append("]");
		return sb.toString();
	}
}

Changes to modules/cldc-compact/src/main/java/java/util/ArrayDeque.java.

1
2
3
4
5
6
7
8
9
10
11
12













13
14
15
16












17
18
19
20
21







22

23




24


25
26








27

28

29
30














31





32
33

34

35
36


37





38
39

40

41
42

43





44
45

46

47
48

49





50
51
52
53
54
55





56
57
58

59
60
61




62
63
64
65

66
67




68
69
70
71
72
73




74
75

76



77

78
79




80
81

82



83

84
85




86
87

88


89
90
91
92
93
94
95
96
97




98
99
100
101
102
103




104
105

106

107
108


109





110
111

112

113
114


115





116
117

118

119
120


121





122
123
124



125

126
127




128
129
130



131

132
133




134
135
136



137

138
139




140
141
142



143

144
145




146
147
148



149

150
151




152
153
154



155

156
157




158
159

160



161

162
163




164
165

166

167
168

169





170
171

172


173
174
175
176
177
178
179
180
181




182
183

184



185

186
187




188
189
190



191

192
193




194
195

196



197

198
199




200
201
202



203

204
205




206
207
208




209













210

211



212





























































































// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;














public class ArrayDeque<E>
	extends AbstractCollection<E>
	implements Deque<E>, Cloneable
{












	public ArrayDeque()
	{
		throw new todo.TODO();
	}
	







	public ArrayDeque(int __a)

	{




		throw new todo.TODO();


	}
	








	public ArrayDeque(Collection<? extends E> __a)

	{

		throw new todo.TODO();
	}














	





	@Override
	public boolean add(E __a)

	{

		throw new todo.TODO();
	}


	





	@Override
	public void addFirst(E __a)

	{

		throw new todo.TODO();
	}

	





	@Override
	public void addLast(E __a)

	{

		throw new todo.TODO();
	}

	





	@Override
	public void clear()
	{
		throw new todo.TODO();
	}
	





	@Override
	public ArrayDeque<E> clone()
	{

		throw new todo.TODO();
	}
	




	@Override
	public boolean contains(Object __a)
	{
		throw new todo.TODO();

	}
	




	@Override
	public Iterator<E> descendingIterator()
	{
		throw new todo.TODO();
	}
	




	@Override
	public E element()

	{



		throw new todo.TODO();

	}
	




	@Override
	public E getFirst()

	{



		throw new todo.TODO();

	}
	




	@Override
	public E getLast()

	{


		throw new todo.TODO();
	}
	
	@Override
	public boolean isEmpty()
	{
		throw new todo.TODO();
	}
	




	@Override
	public Iterator<E> iterator()
	{
		throw new todo.TODO();
	}
	




	@Override
	public boolean offer(E __a)

	{

		throw new todo.TODO();
	}


	





	@Override
	public boolean offerFirst(E __a)

	{

		throw new todo.TODO();
	}


	





	@Override
	public boolean offerLast(E __a)

	{

		throw new todo.TODO();
	}


	





	@Override
	public E peek()
	{



		throw new todo.TODO();

	}
	




	@Override
	public E peekFirst()
	{



		throw new todo.TODO();

	}
	




	@Override
	public E peekLast()
	{



		throw new todo.TODO();

	}
	




	@Override
	public E poll()
	{



		throw new todo.TODO();

	}
	




	@Override
	public E pollFirst()
	{



		throw new todo.TODO();

	}
	




	@Override
	public E pollLast()
	{



		throw new todo.TODO();

	}
	




	@Override
	public E pop()

	{



		throw new todo.TODO();

	}
	




	@Override
	public void push(E __a)

	{

		throw new todo.TODO();
	}

	





	@Override
	public E remove()

	{


		throw new todo.TODO();
	}
	
	@Override
	public boolean remove(Object __a)
	{
		throw new todo.TODO();
	}
	




	@Override
	public E removeFirst()

	{



		throw new todo.TODO();

	}
	




	@Override
	public boolean removeFirstOccurrence(Object __a)
	{



		throw new todo.TODO();

	}
	




	@Override
	public E removeLast()

	{



		throw new todo.TODO();

	}
	




	@Override
	public boolean removeLastOccurrence(Object __a)
	{



		throw new todo.TODO();

	}
	




	@Override
	public int size()
	{




		throw new todo.TODO();













	}

}













































































































>
>
>
>
>
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>


|

|
>
>
>
>
>
>
>
|
>

>
>
>
>
|
>
>

|
>
>
>
>
>
>
>
>
|
>

>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>

|
>

>
|
|
>
>
|
>
>
>
>
>

|
>

>
|
|
>
|
>
>
>
>
>

|
>

>
|
|
>
|
>
>
>
>
>



|


>
>
>
>
>



>
|

|
>
>
>
>

|

<
>

|
>
>
>
>



|

|
>
>
>
>


>

>
>
>
|
>

|
>
>
>
>


>

>
>
>
|
>

|
>
>
>
>


>

>
>
|
|
|
<
<
<
<

|
>
>
>
>



|

|
>
>
>
>

|
>

>
|
|
>
>
|
>
>
>
>
>

|
>

>
|
|
>
>
|
>
>
>
>
>

|
>

>
|
|
>
>
|
>
>
>
>
>



>
>
>
|
>

|
>
>
>
>



>
>
>
|
>

|
>
>
>
>



>
>
>
|
>

|
>
>
>
>



>
>
>
|
>

|
>
>
>
>



>
>
>
|
>

|
>
>
>
>



>
>
>
|
>

|
>
>
>
>


>

>
>
>
|
>

|
>
>
>
>

|
>

>
|
|
>
|
>
>
>
>
>


>

>
>
|
|
|
<
<
<
<

|
>
>
>
>


>

>
>
>
|
>


>
>
>
>

|

>
>
>
|
>


>
>
>
>


>

>
>
>
|
>

|
>
>
>
>

|

>
>
>
|
>


>
>
>
>



>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223




224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406




407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

import cc.squirreljme.runtime.cldc.annotation.ImplementationNote;

/**
 * This is a double-ended queue which is backed by an array, this grows
 * accordingly as elements are added and otherwise. This collection does
 * not allow {@code null} elements.
 *
 * @param <E> The type of element in the queue.
 * @since 2020/06/19
 */
@SuppressWarnings("UseOfClone")
@ImplementationNote("In SquirrelJME, the current implementation is naive " +
	"in that it uses an ArrayList, a more optimal solution should be added.")
public class ArrayDeque<E>
	extends AbstractCollection<E>
	implements Deque<E>, Cloneable
{
	/** The default capacity. */
	private static final int _DEFAULT_CAPACITY =
		16;
	
	/** The backing contents. */
	private final ArrayList<E> _elements;
	
	/**
	 * Initializes an empty queue with a default capacity of 16.
	 *
	 * @since 2020/06/19
	 */
	public ArrayDeque()
	{
		this(ArrayDeque._DEFAULT_CAPACITY);
	}

	/**
	 * Initializes an empty queue with the given initial capacity.
	 *
	 * @param __initialCap The initial capacity.
	 * @throws IllegalArgumentException If the capacity is negative.
	 * @since 2020/06/19
	 */
	public ArrayDeque(int __initialCap)
		throws IllegalArgumentException
	{
		// {@squirreljme.error ZZxx Cannot have an initial capacity that is
		// negative. (The initial capacity)}
		if (__initialCap < 0)
			throw new IllegalArgumentException("ZZxx " + __initialCap);

		// Setup storage
		this._elements = new ArrayList<>(__initialCap);
	}

	/**
	 * Initializes the queue with the given collection, the first iterated
	 * element is at the front of the queue.
	 *
	 * @param __c The initial collection to use.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/19
	 */
	public ArrayDeque(Collection<? extends E> __c)
		throws NullPointerException
	{
		if (__c == null)
			throw new NullPointerException("NARG");
		
		// Initialize empty list with the correct capacity
		int size = __c.size();
		ArrayList<E> elements = new ArrayList<>(size);
		
		// Check for null and add
		for (E element : __c)
		{
			if (element == null)
				throw new NullPointerException("NARG");
			
			elements.add(element);
		}
		
		this._elements = elements;
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public boolean add(E __v)
		throws NullPointerException
	{
		if (__v == null)
			throw new NullPointerException("NARG");
		
		this.__elementAdd(true, __v);
		return true;
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public void addFirst(E __v)
		throws NullPointerException
	{
		if (__v == null)
			throw new NullPointerException("NARG");
		
		this.__elementAdd(false, __v);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public void addLast(E __v)
		throws NullPointerException
	{
		if (__v == null)
			throw new NullPointerException("NARG");

		this.__elementAdd(true, __v);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public void clear()
	{
		this._elements.clear();
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/21
	 */
	@SuppressWarnings("MethodDoesntCallSuperMethod")
	@Override
	public ArrayDeque<E> clone()
	{
		// Just use copy constructor here, for simplicity
		return new ArrayDeque<>(this);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public boolean contains(Object __v)
	{

		return this._elements.contains(__v);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public Iterator<E> descendingIterator()
	{
		return this.__iterator(true);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E element()
		throws NoSuchElementException
	{
		// Queue is empty
		if (this._elements.isEmpty())
			throw new NoSuchElementException("NSEE");
		
		return this.__elementGet(false, false);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E getFirst()
		throws NoSuchElementException
	{
		// Queue is empty
		if (this._elements.isEmpty())
			throw new NoSuchElementException("NSEE");
		
		return this.__elementGet(false, false);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E getLast()
		throws NoSuchElementException
	{
		// Queue is empty
		if (this._elements.isEmpty())
			throw new NoSuchElementException("NSEE");
		
		return this.__elementGet(true, false);




	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public Iterator<E> iterator()
	{
		return this.__iterator(false);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public boolean offer(E __v)
		throws NullPointerException
	{
		if (__v == null)
			throw new NullPointerException("NARG");

		this.__elementAdd(true, __v);
		return true;
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public boolean offerFirst(E __v)
		throws NullPointerException
	{
		if (__v == null)
			throw new NullPointerException("NARG");

		this.__elementAdd(false, __v);
		return true;
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public boolean offerLast(E __v)
		throws NullPointerException
	{
		if (__v == null)
			throw new NullPointerException("NARG");
		
		this.__elementAdd(true, __v);
		return true;
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E peek()
	{
		// Queue is empty
		if (this._elements.isEmpty())
			return null;
		
		return this.__elementGet(false, false);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E peekFirst()
	{
		// Queue is empty
		if (this._elements.isEmpty())
			return null;
		
		return this.__elementGet(false, false);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E peekLast()
	{
		// Queue is empty
		if (this._elements.isEmpty())
			return null;
		
		return this.__elementGet(true, false);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E poll()
	{
		// Queue is empty
		if (this._elements.isEmpty())
			return null;
		
		return this.__elementGet(false, true);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E pollFirst()
	{
		// Queue is empty
		if (this._elements.isEmpty())
			return null;
		
		return this.__elementGet(false, true);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E pollLast()
	{
		// Queue is empty
		if (this._elements.isEmpty())
			return null;
		
		return this.__elementGet(true, true);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E pop()
		throws NoSuchElementException
	{
		// Queue is empty
		if (this._elements.isEmpty())
			throw new NoSuchElementException("NSEE");
		
		return this.__elementGet(false, true);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public void push(E __v)
		throws NullPointerException
	{
		if (__v == null)
			throw new NullPointerException("NARG");

		this.__elementAdd(false, __v);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E remove()
		throws NoSuchElementException
	{
		// Queue is empty
		if (this._elements.isEmpty())
			throw new NoSuchElementException("NSEE");
		
		return this.__elementGet(false, true);




	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E removeFirst()
		throws NoSuchElementException
	{
		// Queue is empty
		if (this._elements.isEmpty())
			throw new NoSuchElementException("NSEE");
		
		return this.__elementGet(false, true);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public boolean removeFirstOccurrence(Object __v)
	{
		// Will never contain null
		if (__v == null)
			return false;
		
		return this.__removeFirst(this.__iterator(false), __v);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public E removeLast()
		throws NoSuchElementException
	{
		// Queue is empty
		if (this._elements.isEmpty())
			throw new NoSuchElementException("NSEE");
		
		return this.__elementGet(true, true);
	}

	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public boolean removeLastOccurrence(Object __v)
	{
		// Will never contain null
		if (__v == null)
			return false;
		
		return this.__removeFirst(this.__iterator(true), __v);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/20
	 */
	@Override
	public int size()
	{
		// Use the pre-cached size, since we cannot use the pivot positions
		// as it would be confusing for empty dequeue
		return this._elements.size();
	}
	
	/**
	 * Adds a value to the queue on a given side.
	 * 
	 * @param __rightSide Add to the right side? 
	 * @param __value The value to add.
	 * @throws NullPointerException On a null value.
	 * @since 2020/06/20
	 */
	private void __elementAdd(boolean __rightSide, E __value)
		throws NullPointerException
	{
		if (__value == null)
			throw new NullPointerException("NARG");
		
		ArrayList<E> elements = this._elements;
		
		// Add to end
		if (__rightSide)
			elements.add(__value);
		
		// Add to start
		else
			elements.add(0, __value);
	}
	
	/**
	 * Removes an element from the queue.
	 * 
	 * @param __rightSide Remove from the right side?
	 * @param __delete Is the element to be deleted?
	 * @return The element to remove.
	 * @since 2020/06/20
	 */
	private E __elementGet(boolean __rightSide, boolean __delete)
	{
		ArrayList<E> elements = this._elements;
		
		// {@squirreljme.error ZZ37 Get of element from an empty deque?}
		int size = elements.size();
		if (size <= 0)
			throw new IllegalStateException("ZZ37");
		
		// From right?
		if (__rightSide)
		{
			if (__delete)
				return elements.remove(size - 1);
			else
				return elements.get(size - 1);
		}
		
		// From left?
		else
		{
			if (__delete)
				return elements.remove(0);
			else
				return elements.get(0);
		}
	}
	
	/**
	 * Returns the element iterator.
	 * 
	 * @param __descending Is this descending?
	 * @return The iterator.
	 * @since 2020/06/21
	 */
	private Iterator<E> __iterator(boolean __descending)
	{
		// If descending, use the list iterator but start from the end
		ArrayList<E> elements = this._elements;
		if (__descending)
			return new __DescendingIteratorViaListIterator__<E>(
				elements.listIterator(elements.size()));
		
		// Use normal iterator, do not expose the ListIterator!
		else
			return new __HideIterator__<E>(elements.iterator());
	}
	
	/**
	 * Removes the first occurrence of an item with an iterator.
	 * 
	 * @param __iterator The iterator.
	 * @param __v The item to remove.
	 * @return If it was found and removed.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/20
	 */
	private boolean __removeFirst(Iterator<E> __iterator, Object __v)
		throws NullPointerException
	{
		if (__iterator == null)
			throw new NullPointerException("NARG");
		
		// Go through every element
		while (__iterator.hasNext())
		{
			E element = __iterator.next();
			
			// Was this found?
			if (Objects.equals(element, __v))
			{
				__iterator.remove();
				return true;
			}
		}
		
		// Was not found
		return false;
	}
}

Changes to modules/cldc-compact/src/main/java/java/util/ArrayList.java.

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	 * @since 2018/09/15
	 */
	@SuppressWarnings({"unchecked"})
	public ArrayList(int __cap)
		throws IllegalArgumentException
	{
		// {@squirreljme.error ZZ2e Attempt to initialize array list with
		// a negative capacity. (The capicity)}
		if (__cap < 0)
			throw new IllegalArgumentException(
				String.format("ZZ2e %d", __cap));
		
		this._elements = (E[])new Object[__cap];
	}
	







|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	 * @since 2018/09/15
	 */
	@SuppressWarnings({"unchecked"})
	public ArrayList(int __cap)
		throws IllegalArgumentException
	{
		// {@squirreljme.error ZZ2e Attempt to initialize array list with
		// a negative capacity. (The capacity)}
		if (__cap < 0)
			throw new IllegalArgumentException(
				String.format("ZZ2e %d", __cap));
		
		this._elements = (E[])new Object[__cap];
	}
	

Changes to modules/cldc-compact/src/main/java/java/util/Arrays.java.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;


import cc.squirreljme.runtime.cldc.asm.ObjectAccess;
import cc.squirreljme.runtime.cldc.util.ByteIntegerArray;
import cc.squirreljme.runtime.cldc.util.CharacterIntegerArray;
import cc.squirreljme.runtime.cldc.util.DoubleArrayList;
import cc.squirreljme.runtime.cldc.util.FloatArrayList;
import cc.squirreljme.runtime.cldc.util.IntegerArrays;
import cc.squirreljme.runtime.cldc.util.IntegerIntegerArray;
import cc.squirreljme.runtime.cldc.util.LongArrayList;












>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.runtime.cldc.util.ByteIntegerArray;
import cc.squirreljme.runtime.cldc.util.CharacterIntegerArray;
import cc.squirreljme.runtime.cldc.util.DoubleArrayList;
import cc.squirreljme.runtime.cldc.util.FloatArrayList;
import cc.squirreljme.runtime.cldc.util.IntegerArrays;
import cc.squirreljme.runtime.cldc.util.IntegerIntegerArray;
import cc.squirreljme.runtime.cldc.util.LongArrayList;
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343
344
345
346
347








































































































348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544

545
546
547
548
549
550
551
552
	}
	
	/**
	 * Returns a copy of the given array but using the specified type.
	 *
	 * @param <T> The resulting type of the array to use.
	 * @param __src The source array.
	 * @param __newlen The new length of the array.
	 * @return The copy of the array with the new length and type.
	 * @throws ArrayStoreException If an element being copied from the source
	 * array is not compatible with the destination array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/04
	 */
	@SuppressWarnings({"unchecked"})
	public static <T> T[] copyOf(T[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		return Arrays.<T, T>copyOf(__src, __newlen,
			(Class<T[]>)__src.getClass());
	}
	
	/**
	 * Returns a copy of the given array but using the specified type.
	 *
	 * @param <T> The resulting type of the array to use.
	 * @param <U> The input array type.
	 * @param __src The source array.
	 * @param __newlen The new length of the array.
	 * @param __targettype The type type.
	 * @return The copy of the array with the new length and type.
	 * @throws ArrayStoreException If an element being copied from the source
	 * array is not compatible with the destination array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/04
	 */
	@SuppressWarnings({"unchecked"})
	public static <T, U> T[] copyOf(U[] __src, int __newlen,
		Class<? extends T[]> __targettype)
		throws ArrayStoreException, NegativeArraySizeException,
			NullPointerException
	{
		if (__src == null || __targettype == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		// Allocate array in the target type
		Object[] rv = (Object[])ObjectAccess.arrayNew(__targettype, __newlen);

		
		// Copy source to destination
		for (int i = 0, n = Math.min(__src.length, __newlen); i < n; i++)
			rv[i] = __src[i];
		
		return (T[])rv;








































































































	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newlen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static byte[] copyOf(byte[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		byte[] rv = new byte[__newlen];
		for (int i = 0, n = Math.min(__newlen, __src.length); i < n; i++)

			rv[i] = __src[i];
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newlen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static short[] copyOf(short[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		short[] rv = new short[__newlen];
		for (int i = 0, n = Math.min(__newlen, __src.length); i < n; i++)

			rv[i] = __src[i];
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newlen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static int[] copyOf(int[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		int[] rv = new int[__newlen];
		for (int i = 0, n = Math.min(__newlen, __src.length); i < n; i++)
			rv[i] = __src[i];
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newlen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static long[] copyOf(long[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		long[] rv = new long[__newlen];
		for (int i = 0, n = Math.min(__newlen, __src.length); i < n; i++)
			rv[i] = __src[i];
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newlen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static char[] copyOf(char[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		char[] rv = new char[__newlen];
		for (int i = 0, n = Math.min(__newlen, __src.length); i < n; i++)
			rv[i] = __src[i];
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newlen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static float[] copyOf(float[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		float[] rv = new float[__newlen];
		for (int i = 0, n = Math.min(__newlen, __src.length); i < n; i++)
			rv[i] = __src[i];
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newlen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static double[] copyOf(double[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		double[] rv = new double[__newlen];
		for (int i = 0, n = Math.min(__newlen, __src.length); i < n; i++)
			rv[i] = __src[i];
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newlen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static boolean[] copyOf(boolean[] __src, int __newlen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newlen < 0)
			throw new NegativeArraySizeException("NASE");
		
		boolean[] rv = new boolean[__newlen];
		for (int i = 0, n = Math.min(__newlen, __src.length); i < n; i++)

			rv[i] = __src[i];
		
		return rv;
	}
	
	/**
	 * Checks if both arrays are equal to each other.
	 *







|








|


|









|
|








|
|



|

|



|
>


|
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|





|




|


|
|
>
|








|





|




|


|
|
>
|








|





|




|


|
<
<

<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<








|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|




|


|
|
>
|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526


527


528

















529



530
531
532
533
534
535
536
537
538
539
540
541
542
543











































































544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
	}
	
	/**
	 * Returns a copy of the given array but using the specified type.
	 *
	 * @param <T> The resulting type of the array to use.
	 * @param __src The source array.
	 * @param __newLen The new length of the array.
	 * @return The copy of the array with the new length and type.
	 * @throws ArrayStoreException If an element being copied from the source
	 * array is not compatible with the destination array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/04
	 */
	@SuppressWarnings({"unchecked"})
	public static <T> T[] copyOf(T[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		return Arrays.<T, T>copyOf(__src, __newLen,
			(Class<T[]>)__src.getClass());
	}
	
	/**
	 * Returns a copy of the given array but using the specified type.
	 *
	 * @param <T> The resulting type of the array to use.
	 * @param <U> The input array type.
	 * @param __src The source array.
	 * @param __newLen The new length of the array.
	 * @param __newType The type type.
	 * @return The copy of the array with the new length and type.
	 * @throws ArrayStoreException If an element being copied from the source
	 * array is not compatible with the destination array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/04
	 */
	@SuppressWarnings({"unchecked"})
	public static <T, U> T[] copyOf(U[] __src, int __newLen,
		Class<? extends T[]> __newType)
		throws ArrayStoreException, NegativeArraySizeException,
			NullPointerException
	{
		if (__src == null || __newType == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		// Allocate array in the target type
		T[] rv = ObjectShelf.<T[]>arrayNew(TypeShelf.classToType(__newType),
			__newLen);
		
		// Copy source to destination
		for (int i = 0, n = Math.min(__src.length, __newLen); i < n; i++)
			rv[i] = (T)__src[i];
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newLen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static byte[] copyOf(byte[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		byte[] rv = new byte[__newLen];
		
		ObjectShelf.arrayCopy(__src, 0, rv, 0,
			Math.min(__newLen, __src.length));
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newLen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static short[] copyOf(short[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		short[] rv = new short[__newLen];
		
		ObjectShelf.arrayCopy(__src, 0, rv, 0,
			Math.min(__newLen, __src.length));
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newLen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static int[] copyOf(int[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		int[] rv = new int[__newLen];
		
		ObjectShelf.arrayCopy(__src, 0, rv, 0,
			Math.min(__newLen, __src.length));
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newLen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static long[] copyOf(long[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		long[] rv = new long[__newLen];
		
		ObjectShelf.arrayCopy(__src, 0, rv, 0,
			Math.min(__newLen, __src.length));
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newLen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static char[] copyOf(char[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		char[] rv = new char[__newLen];
		
		ObjectShelf.arrayCopy(__src, 0, rv, 0,
			Math.min(__newLen, __src.length));
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newLen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static float[] copyOf(float[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		float[] rv = new float[__newLen];
		
		ObjectShelf.arrayCopy(__src, 0, rv, 0,
			Math.min(__newLen, __src.length));
		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newLen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */
	public static double[] copyOf(double[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		double[] rv = new double[__newLen];


		


		ObjectShelf.arrayCopy(__src, 0, rv, 0,

















			Math.min(__newLen, __src.length));



		
		return rv;
	}
	
	/**
	 * Returns a new copy of the given array of the given length.
	 *
	 * @param __src The array to copy.
	 * @param __newLen The new length of the array.
	 * @return The copied array.
	 * @throws NegativeArraySizeException If the new length is negative.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/11/06
	 */











































































	public static boolean[] copyOf(boolean[] __src, int __newLen)
		throws NegativeArraySizeException, NullPointerException
	{
		if (__src == null)
			throw new NullPointerException("NARG");
		if (__newLen < 0)
			throw new NegativeArraySizeException("NASE");
		
		boolean[] rv = new boolean[__newLen];
		
		ObjectShelf.arrayCopy(__src, 0, rv, 0,
			Math.min(__newLen, __src.length));
		
		return rv;
	}
	
	/**
	 * Checks if both arrays are equal to each other.
	 *

Changes to modules/cldc-compact/src/main/java/java/util/LinkedList.java.

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
	 * {@inheritDoc}
	 * @since 2016/09/05
	 */
	@Override
	public E pollLast()
	{
		if (this._size == 0)
			throw new NoSuchElementException("NSEE");
		
		ListIterator<E> it = this.listIterator(this._size);
		
		// Remove the last element
		E rv = it.previous();
		it.remove();
		return rv;







|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
	 * {@inheritDoc}
	 * @since 2016/09/05
	 */
	@Override
	public E pollLast()
	{
		if (this._size == 0)
			return null;
		
		ListIterator<E> it = this.listIterator(this._size);
		
		// Remove the last element
		E rv = it.previous();
		it.remove();
		return rv;

Changes to modules/cldc-compact/src/main/java/java/util/ServiceLoader.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

import cc.squirreljme.runtime.cldc.asm.SuiteAccess;
import cc.squirreljme.runtime.cldc.io.ResourceInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * The service loader is used to lookup services which may be defined in the
 * classpath.
 *
 * Services are stored as a list of class in resources within the JAR, these
 * services lists are declared in files specifying the class name. So the
 * format is {@code META-INF/services/fully.qualified.class.name}.
 *
 * The iterator may throw {@code ServiceConfigurationError}.
 *
 * @param <S> The class to provide a service for.
 * @since 2018/12/06
 */
public final class ServiceLoader<S>
	implements Iterable<S>
{
	/** The class to search for. */
	private final Class<S> _search;
	
	/** The service cache. */
	private final __Cache__<S> _cache =
		new __Cache__<S>();
	
	/**
	 * Initializes the service loader.
	 *
	 * @param __cl The class to search.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/06












<
<
<
<
<
<
<




















|
|







1
2
3
4
5
6
7
8
9
10
11
12







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;








/**
 * The service loader is used to lookup services which may be defined in the
 * classpath.
 *
 * Services are stored as a list of class in resources within the JAR, these
 * services lists are declared in files specifying the class name. So the
 * format is {@code META-INF/services/fully.qualified.class.name}.
 *
 * The iterator may throw {@code ServiceConfigurationError}.
 *
 * @param <S> The class to provide a service for.
 * @since 2018/12/06
 */
public final class ServiceLoader<S>
	implements Iterable<S>
{
	/** The class to search for. */
	private final Class<S> _search;
	
	/** The service cache. */
	private final __ServiceLoaderCache__<S> _cache =
		new __ServiceLoaderCache__<S>();
	
	/**
	 * Initializes the service loader.
	 *
	 * @param __cl The class to search.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/06
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
	 * {@inheritDoc}
	 * @since 2018/12/06
	 */
	@Override
	public Iterator<S> iterator()
	{
		Class<S> search = this._search;
		__Cache__<S> cache = this._cache;
		
		// Use the cached array?
		Object[] use = cache._cache;
		if (use != null)
			return new __CachedIterator__<S>(search, use);
		
		// Cache it
		else
			return new __FreshIterator__<S>(search, cache);
	}
	
	/**
	 * Clears the cache of services.
	 *
	 * @since 2018/12/06
	 */







|




|



|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
	 * {@inheritDoc}
	 * @since 2018/12/06
	 */
	@Override
	public Iterator<S> iterator()
	{
		Class<S> search = this._search;
		__ServiceLoaderCache__<S> cache = this._cache;
		
		// Use the cached array?
		Object[] use = cache._cache;
		if (use != null)
			return new __ServiceLoaderCachedIterator__<S>(search, use);
		
		// Cache it
		else
			return new __ServiceLoaderFreshIterator__<S>(search, cache);
	}
	
	/**
	 * Clears the cache of services.
	 *
	 * @since 2018/12/06
	 */
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		return new ServiceLoader<S>(__cl);
	}
	
	/**
	 * Cache for the service loader.
	 *
	 * @param <S> The class type.
	 * @since 2018/12/06
	 */
	private static final class __Cache__<S>
	{
		/** The cache of services. */
		volatile Object[] _cache;
	}
	
	/**
	 * Iterator over the cached set.
	 *
	 * @param <S> The class type.
	 * @since 2018/12/06
	 */
	private static final class __CachedIterator__<S>
		implements Iterator<S>
	{
		/** The search class. */
		private final Class<S> _search;
		
		/** The array to use for this. */
		private final Object[] _items;
		
		/** The next index. */
		private int _next;
		
		/**
		 * Wraps the given array and provides an iterator of it.
		 *
		 * @param __s The search class.
		 * @param __it The iterator to wrap.
		 * @throws NullPointerException On null arguments.
		 * @since 2018/12/06
		 */
		__CachedIterator__(Class<S> __s, Object[] __it)
			throws NullPointerException
		{
			if (__s == null || __it == null)
				throw new NullPointerException("NARG");
			
			this._search = __s;
			this._items = __it;
		}
		
		/**
		 * {@inheritDoc}
		 * @since 2018/12/06
		 */
		@Override
		public final boolean hasNext()
		{
			return this._next < this._items.length;
		}
		
		/**
		 * {@inheritDoc}
		 * @since 2018/12/06
		 */
		@Override
		public final S next()
		{
			Object[] items = this._items;
			int next = this._next;
			
			// No more?
			if (next >= items.length)
				throw new NoSuchElementException("NSEE");
			
			// Get and iterator
			Object rv = items[next];
			this._next = next + 1;
			return this._search.cast(rv);
		}
		
		/**
		 * {@inheritDoc}
		 * @since 2018/12/06
		 */
		@Override
		public final void remove()
		{
			throw new UnsupportedOperationException("RORO");
		}
	}
	
	/**
	 * Iterator over a fresh search pouring into the cache.
	 *
	 * @param <S> The class type.
	 * @since 2018/12/06
	 */
	private static final class __FreshIterator__<S>
		implements Iterator<S>
	{
		/** The search class. */
		private final Class<S> _search;
		
		/** The cache to put in. */
		private final __Cache__<S> _cache;
		
		/** Temporary cache building. */
		private final List<Object> _cachebuild =
			new ArrayList<>();
		
		/** Suites left to parse. */
		private final Queue<String> _suites =
			new LinkedList<>();
		
		/** Classes left to create and scan. */
		private final Queue<String> _classes =
			new LinkedList<>();
		
		/** The next service to run. */
		private S _next;
		
		/** Is this finished? */
		private boolean _finished;
		
		/**
		 * Initializes the iterator for fresh service lookup.
		 *
		 * @param __s The search class.
		 * @param __c The cache class.
		 * @throws NullPointerException On null arguments.
		 * @since 2018/12/06
		 */
		__FreshIterator__(Class<S> __s, __Cache__<S> __c)
			throws NullPointerException
		{
			if (__s == null || __c == null)
				throw new NullPointerException("NARG");
			
			this._search = __s;
			this._cache = __c;
			
			// Seed suites left with the
			Queue<String> suites = this._suites;
			for (String s : SuiteAccess.currentClassPath())
				suites.add(s);
		}
		
		/**
		 * {@inheritDoc}
		 * @since 2018/12/06
		 */
		@Override
		public final boolean hasNext()
		{
			// If already finished, nothing can be done
			if (this._finished)
				return false;
			
			// Already cached?
			if (this._next != null)
				return true;
			
			Queue<String> suites = this._suites;
			Queue<String> classes = this._classes;
			
			// Loops until an element was found
			for (;;)
			{
				// If there is an entry in the class list, try to load that
				// class
				String maybe = classes.poll();
				if (maybe != null)
				{
					// Try to load this class
					try
					{
						// If this fails an exception is thrown
						Class<?> cl = Class.forName(maybe);
						
						// Try to create a new instance since this is new,
						// any exceptions thrown cause errors
						Object rv = cl.newInstance();
						
						// Cache this instance for later
						this._cachebuild.add(rv);
						
						// Cast this class
						this._next = this._search.cast(rv);
						return true;
					}
					
					// {@squirreljme.error ZZ30 Could not load the service
					// class.}
					catch (ClassCastException|IllegalAccessException|
						InstantiationException|ClassNotFoundException e)
					{
						throw new ServiceConfigurationError("ZZ30", e);
					}
				}
				
				// Nothing is in the classes, so we need to pull a suite
				// resource
				String pull = suites.poll();
				if (pull == null)
				{
					// Mark as finished
					this._finished = true;
					
					// Store in the cache for later since it is all done
					// now
					List<Object> cb = this._cachebuild;
					this._cache._cache = cb.<Object>toArray(
						new Object[cb.size()]);
					
					// Clear from this iterator
					cb.clear();
					
					// Nothing else to do
					return false;
				}
				
				// Could services list
				else
				{
					// Load resources
					try (InputStream in = ResourceInputStream.open(pull,
						"META-INF/services/" + this._search.getName()))
					{
						// Ignore unknown resources
						if (in == null)
							continue;
						
						// Read by line
						Set<String> pushy = new LinkedHashSet<>();
						try (BufferedReader br = new BufferedReader(
							new InputStreamReader(in, "utf-8")))
						{
							for (;;)
							{
								// Stop on EOF
								String ln = br.readLine();
								if (ln == null)
									break;
								
								// Trim the line
								ln = ln.trim();
								
								// Ignore blank lines
								if (ln.isEmpty())
									continue;
								
								// Ignore comments
								if (ln.startsWith("#"))
									continue;
								
								// Add otherwise
								pushy.add(ln);
							}
						}
						
						// Add unique entries
						for (String ln : pushy)
							classes.add(ln);
					}
					
					// {@squirreljme.error ZZ31 Could not read the services
					// list}
					catch (IOException e)
					{
						throw new ServiceConfigurationError("ZZ31", e);
					}
				}
			}
		}
		
		/**
		 * {@inheritDoc}
		 * @since 2018/12/06
		 */
		@Override
		public final S next()
		{
			// Cache
			if (!this.hasNext())
				throw new NoSuchElementException("NSEE");
			
			// Return the cached element
			S rv = this._next;
			this._next = null;
			return rv;
		}
		
		/**
		 * {@inheritDoc}
		 * @since 2018/12/06
		 */
		@Override
		public final void remove()
		{
			throw new UnsupportedOperationException("RORO");
		}
	}
}








|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
104
105
106
107
108
109
110
111














































































































































































































































































































		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		return new ServiceLoader<S>(__cl);
	}
}














































































































































































































































































































Changes to modules/cldc-compact/src/main/java/java/util/Vector.java.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;


import cc.squirreljme.runtime.cldc.util.IteratorToEnumeration;
import cc.squirreljme.runtime.cldc.util.SynchronizedIterator;

/**
 * This is similar to {@link ArrayList} except that it is synchronized and
 * thread-safe by default.
 *
 * @see ArrayList
 * @since 2019/05/13
 */

public class Vector<E>
	extends AbstractList<E>
	implements RandomAccess, Cloneable
{
	/** The number of elements to add if the size is too small. */
	protected int capacityIncrement;
	












>










>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.cldc.util.IteratorToEnumeration;
import cc.squirreljme.runtime.cldc.util.SynchronizedIterator;

/**
 * This is similar to {@link ArrayList} except that it is synchronized and
 * thread-safe by default.
 *
 * @see ArrayList
 * @since 2019/05/13
 */
@SuppressWarnings("UseOfClone")
public class Vector<E>
	extends AbstractList<E>
	implements RandomAccess, Cloneable
{
	/** The number of elements to add if the size is too small. */
	protected int capacityIncrement;
	
71
72
73
74
75
76
77







78

79

80








81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
	 * @since 2019/05/13
	 */
	public Vector()
	{
		this(10, 0);
	}
	







	public Vector(Collection<? extends E> __a)

	{

		throw new todo.TODO();








	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */
	@Override
	public void add(int __i, E __v)
	{
		synchronized (this)
		{
			int size = this.elementCount;
			if (__i < 0 || __i > size)
				throw new IndexOutOfBoundsException("IOOB");
			
			Object[] elements = this.elementData;
			int cap = elements.length,
				nextsize = size + 1;
			
			// Cannot fit in this array
			Object[] source = elements;
			if (nextsize > cap)
			{
				// Grow the list by a bit
				int newcap = nextsize + Math.max(1, this.capacityIncrement);
				elements = new Object[newcap];
				
				// Copy old stuff over, but only up to the index as needed
				for (int i = 0; i < __i; i++)
					elements[i] = source[i];
			}
			
			// Move down to fit
			for (int i = size - 1, o = size; o > __i; i--, o--)
				elements[o] = source[i];
			
			// Store data here
			elements[__i] = __v;
			
			// Store new information
			this.elementCount = nextsize;
			if (elements != source)
				this.elementData = elements;
			
			// Structurally modified
			this.modCount++;
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */







>
>
>
>
>
>
>
|
>

>
|
>
>
>
>
>
>
>
>











<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110



111































112
113
114
115
116
117
118
	 * @since 2019/05/13
	 */
	public Vector()
	{
		this(10, 0);
	}
	
	/**
	 * Initializes a vector which is a copy of the given collection.
	 *
	 * @param __c The collection to initialize with.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/17
	 */
	public Vector(Collection<? extends E> __c)
		throws NullPointerException
	{
		if (__c == null)
			throw new NullPointerException("NARG");
		
		// The initial capacity is always the target collection size
		int initialCap = __c.size();
		
		this.elementData = new Object[initialCap];
		this.capacityIncrement = initialCap;
		
		this.addAll(__c);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */
	@Override
	public void add(int __i, E __v)
	{
		synchronized (this)
		{



			this.__internalAdd(__i, __v);































		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169






170
171
172
173
174
175
176
177
178
179
180
181
	
	/**
	 * Adds an element to the end of the vector.
	 *
	 * @param __v The element to add.
	 * @since 2019/05/14
	 */

	public void addElement(E __v)
	{
		synchronized (this)
		{
			this.add(__v);
		}
	}
	






	public int capacity()
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */







>




|



>
>
>
>
>
>




|







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
	
	/**
	 * Adds an element to the end of the vector.
	 *
	 * @param __v The element to add.
	 * @since 2019/05/14
	 */
	@SuppressWarnings("UnnecessarySuperQualifier")
	public void addElement(E __v)
	{
		synchronized (this)
		{
			super.add(__v);
		}
	}
	
	/**
	 * Returns the capacity of this vector.
	 *
	 * @return The capacity of this vector.
	 * @since 2020/06/17
	 */
	public int capacity()
	{
		synchronized (this)
		{
			return this.elementData.length;
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205




206
207
208
209


210
211





212
213
214
215
216
217

218
219
220
221
222
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
			Object[] elements = this.elementData;
			for (int i = 0, n = elements.length; i < n; i++)
				elements[i] = null;
		}
	}
	
	@Override
	public Object clone()
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	




	@Override
	public boolean contains(Object __a)
	{
		throw new todo.TODO();


	}
	





	@Override
	public boolean containsAll(Collection<?> __a)
	{
		synchronized (this)
		{
			throw new todo.TODO();

		}
	}
	
	/**
	 * Copies this vector to the given array.
	 *
	 * @param __a The target array.
	 * @throws ArrayStoreException If the array cannot store the vector
	 * values.
	 * @throws IndexOutOfBoundsException If the array is too small.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/06/24
	 */

	public void copyInto(Object[] __a)
		throws ArrayStoreException, IndexOutOfBoundsException,
			NullPointerException
	{
		if (__a == null)
			throw new NullPointerException("NARG");
		







|



|



>
>
>
>

|

|
>
>
|
|
>
>
>
>
>

|



<
>













>







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
			Object[] elements = this.elementData;
			for (int i = 0, n = elements.length; i < n; i++)
				elements[i] = null;
		}
	}
	
	@Override
	public Vector<E> clone()
	{
		synchronized (this)
		{
			throw Debugging.todo("Vector clone");
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/17
	 */
	@Override
	public boolean contains(Object __v)
	{
		synchronized (this)
		{
			return super.contains(__v);
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/17
	 */
	@Override
	public boolean containsAll(Collection<?> __c)
	{
		synchronized (this)
		{

			return super.containsAll(__c);
		}
	}
	
	/**
	 * Copies this vector to the given array.
	 *
	 * @param __a The target array.
	 * @throws ArrayStoreException If the array cannot store the vector
	 * values.
	 * @throws IndexOutOfBoundsException If the array is too small.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/06/24
	 */
	@SuppressWarnings("ManualArrayCopy")
	public void copyInto(Object[] __a)
		throws ArrayStoreException, IndexOutOfBoundsException,
			NullPointerException
	{
		if (__a == null)
			throw new NullPointerException("NARG");
		
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274


275

276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
	 * @return The element.
	 * @since 2019/05/14
	 */
	public E elementAt(int __i)
	{
		synchronized (this)
		{
			return this.get(__i);
		}
	}
	
	/**
	 * Returns an enumeration over the elements.
	 *
	 * @return The element enumeration.
	 * @since 2019/05/14
	 */
	public Enumeration<E> elements()
	{


		return new IteratorToEnumeration<E>(this.iterator());

	}
	
	/**
	 * Ensures that the vector can store the given number of elements.
	 *
	 * @param __n The element capacity.
	 * @since 2019/05/14
	 */

	public void ensureCapacity(int __n)
	{
		synchronized (this)
		{
			// Pointless
			if (__n <= 0)
				return;
			
			// Meets or exceeds the desired capacity?
			Object[] elements = this.elementData;
			int nowl = elements.length;
			if (__n <= nowl)
				return;
			
			// Copy values over
			Object[] extra = new Object[__n];
			for (int i = 0; i < nowl; i++)
				extra[i] = elements[i];
			
			// Set
			this.elementData = extra;
		}
	}
	







|











>
>
|
>








>










|
|




|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
	 * @return The element.
	 * @since 2019/05/14
	 */
	public E elementAt(int __i)
	{
		synchronized (this)
		{
			return this.__internalGet(__i);
		}
	}
	
	/**
	 * Returns an enumeration over the elements.
	 *
	 * @return The element enumeration.
	 * @since 2019/05/14
	 */
	public Enumeration<E> elements()
	{
		synchronized (this)
		{
			return new IteratorToEnumeration<E>(this.iterator());
		}
	}
	
	/**
	 * Ensures that the vector can store the given number of elements.
	 *
	 * @param __n The element capacity.
	 * @since 2019/05/14
	 */
	@SuppressWarnings("ManualArrayCopy")
	public void ensureCapacity(int __n)
	{
		synchronized (this)
		{
			// Pointless
			if (__n <= 0)
				return;
			
			// Meets or exceeds the desired capacity?
			Object[] elements = this.elementData;
			int nowLen = elements.length;
			if (__n <= nowLen)
				return;
			
			// Copy values over
			Object[] extra = new Object[__n];
			for (int i = 0; i < nowLen; i++)
				extra[i] = elements[i];
			
			// Set
			this.elementData = extra;
		}
	}
	
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357




358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408








409

410
411
412



413

414
415
416




417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */
	@Override
	@SuppressWarnings({"unchecked"})
	public E get(int __i)
	{
		synchronized (this)
		{
			if (__i < 0 || __i >= this.elementCount)
				throw new ArrayIndexOutOfBoundsException("IOOB");
			
			return (E)this.elementData[__i];
		}
	}
	




	@Override
	public int hashCode()
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/19
	 */
	@Override
	public int indexOf(Object __v)
	{
		synchronized (this)
		{
			return super.indexOf(__v);
		}
	}
	
	public int indexOf(Object __a, int __b)
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	







	public void insertElementAt(E __a, int __b)
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */
	@Override
	public Iterator<E> iterator()
	{
		synchronized (this)
		{
			return new SynchronizedIterator<E>(this, super.iterator());
		}
	}
	








	public E lastElement()

	{
		synchronized (this)
		{



			throw new todo.TODO();

		}
	}
	




	@Override
	public int lastIndexOf(Object __a)
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	
	public int lastIndexOf(Object __a, int __b)
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	







<




<
<
|
<



>
>
>
>





|
















|



|



>
>
>
>
>
>
>
|



|
















>
>
>
>
>
>
>
>

>



>
>
>
|
>



>
>
>
>

|



|



|







347
348
349
350
351
352
353

354
355
356
357


358

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */
	@Override

	public E get(int __i)
	{
		synchronized (this)
		{


			return this.__internalGet(__i);

		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/17
	 */
	@Override
	public int hashCode()
	{
		synchronized (this)
		{
			return super.hashCode();
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/19
	 */
	@Override
	public int indexOf(Object __v)
	{
		synchronized (this)
		{
			return super.indexOf(__v);
		}
	}
	
	public int indexOf(Object __v, int __base)
	{
		synchronized (this)
		{
			throw Debugging.todo();
		}
	}
	
	/**
	 * Performs the same operation as {@link Vector#add(int, E)}.
	 *
	 * @param __v The value to add.
	 * @param __at The index to add at.
	 * @since 2020/06/17
	 */
	public void insertElementAt(E __v, int __at)
	{
		synchronized (this)
		{
			this.__internalAdd(__at, __v);
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/14
	 */
	@Override
	public Iterator<E> iterator()
	{
		synchronized (this)
		{
			return new SynchronizedIterator<E>(this, super.iterator());
		}
	}
	
	/**
	 * Returns the last element.
	 *
	 * @return The last element.
	 * @throws NoSuchElementException If there is none.
	 * @since 2020/06/17
	 */
	@SuppressWarnings("unchecked")
	public E lastElement()
		throws NoSuchElementException
	{
		synchronized (this)
		{
			int count = this.elementCount;
			if (count <= 0)
				throw new NoSuchElementException("NSEE");
			
			return (E)this.elementData[count - 1];
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/17
	 */
	@Override
	public int lastIndexOf(Object __v)
	{
		synchronized (this)
		{
			return super.lastIndexOf(__v);
		}
	}
	
	public int lastIndexOf(Object __v, int __base)
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	
473
474
475
476
477
478
479




480
481
482
483
484
485
486
487
488
489
490
491
492
			this.elementCount = size - 1;
			
			// And the old element
			return (E)rv;
		}
	}
	




	@Override
	public boolean removeAll(Collection<?> __a)
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	
	/**
	 * Removes all elements in the vector.
	 *
	 * @since 2019/05/14







>
>
>
>

|



|







505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
			this.elementCount = size - 1;
			
			// And the old element
			return (E)rv;
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/17
	 */
	@Override
	public boolean removeAll(Collection<?> __c)
	{
		synchronized (this)
		{
			return super.removeAll(__c);
		}
	}
	
	/**
	 * Removes all elements in the vector.
	 *
	 * @since 2019/05/14
643
644
645
646
647
648
649




650
651
652
653
654
655
656
657
658






659
660
661
662


663



664
665
666


667































































	{
		synchronized (this)
		{
			return this.elementCount;
		}
	}
	




	@Override
	public List<E> subList(int __a, int __b)
	{
		synchronized (this)
		{
			throw new todo.TODO();
		}
	}
	






	public void trimToSize()
	{
		synchronized (this)
		{


			throw new todo.TODO();



		}
	}
}









































































>
>
>
>

|



|



>
>
>
>
>
>




>
>
|
>
>
>


|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
	{
		synchronized (this)
		{
			return this.elementCount;
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/17
	 */
	@Override
	public List<E> subList(int __from, int __to)
	{
		synchronized (this)
		{
			return super.subList(__from, __to);
		}
	}
	
	/**
	 * Trims this vector's capacity to the number of elements that are in
	 * the vector.
	 *
	 * @since 2020/06/17
	 */
	public void trimToSize()
	{
		synchronized (this)
		{
			int elementCount = this.elementCount;
			Object[] elementData = this.elementData;
			
			// If this is true then we can just chop the array
			if (elementData.length > elementCount)
				this.elementData = Arrays.copyOf(elementData, elementCount);
		}
	}
	
	/**
	 * Internal logic for adding values.
	 *
	 * @param __i The index to place at.
	 * @param __v The value to add.
	 * @since 2020/06/17
	 */
	@SuppressWarnings("ManualArrayCopy")
	private void __internalAdd(int __i, E __v)
	{
		int size = this.elementCount;
		if (__i < 0 || __i > size)
			throw new IndexOutOfBoundsException("IOOB");
		
		Object[] elements = this.elementData;
		int cap = elements.length;
		int nextSize = size + 1;
		
		// Cannot fit in this array
		Object[] source = elements;
		if (nextSize > cap)
		{
			// Grow the list by a bit
			int newCap = nextSize + Math.max(1, this.capacityIncrement);
			elements = new Object[newCap];
			
			// Copy old stuff over, but only up to the index as needed
			for (int i = 0; i < __i; i++)
				elements[i] = source[i];
		}
		
		// Move down to fit
		for (int i = size - 1, o = size; o > __i; i--, o--)
			elements[o] = source[i];
		
		// Store data here
		elements[__i] = __v;
		
		// Store new information
		this.elementCount = nextSize;
		if (elements != source)
			this.elementData = elements;
		
		// Structurally modified
		this.modCount++;
	}
	
	/**
	 * Internal get logic.
	 *
	 * @param __i The index.
	 * @return The value at the index.
	 * @throws ArrayIndexOutOfBoundsException If the index is out of bounds.
	 * @since 2020/06/17
	 */
	@SuppressWarnings({"unchecked"})
	private E __internalGet(int __i)
		throws ArrayIndexOutOfBoundsException
	{
		if (__i < 0 || __i >= this.elementCount)
			throw new ArrayIndexOutOfBoundsException("IOOB");
		
		return (E)this.elementData[__i];
	}
}

Added modules/cldc-compact/src/main/java/java/util/__HideIterator__.java.











































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

/**
 * This is a hiding iterator which masks functionality.
 *
 * @param <T> The type.
 * @since 2020/06/21
 */
final class __HideIterator__<T>
	implements Iterator<T>
{
	/** The iterator being hidden. */
	private final Iterator<T> _iterator;
	
	/**
	 * Initializes the hiding iterator.
	 * 
	 * @param __iterator The iterator to hide.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/21
	 */
	public __HideIterator__(Iterator<T> __iterator)
		throws NullPointerException
	{
		if (__iterator == null)
			throw new NullPointerException("NARG");
		
		this._iterator = __iterator;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/21
	 */
	@Override
	public boolean hasNext()
	{
		return this._iterator.hasNext();
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/21
	 */
	@Override
	public T next()
	{
		return this._iterator.next();
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/21
	 */
	@Override
	public void remove()
	{
		this._iterator.remove();
	}
}

Added modules/cldc-compact/src/main/java/java/util/__ModCounter__.java.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

/**
 * Modification counter.
 *
 * @since 2020/06/20
 */
@Deprecated
final class __ModCounter__
{
	/** The modification count. */
	public int modCount;
}

Added modules/cldc-compact/src/main/java/java/util/__ServiceLoaderCache__.java.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

/**
 * Cache for the service loader.
 *
 * @param <S> The class type.
 * @since 2018/12/06
 */
final class __ServiceLoaderCache__<S>
{
	/** The cache of services. */
	volatile Object[] _cache;
}

Added modules/cldc-compact/src/main/java/java/util/__ServiceLoaderCachedIterator__.java.















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

/**
 * Iterator over the cached set.
 *
 * @param <S> The class type.
 * @since 2018/12/06
 */
final class __ServiceLoaderCachedIterator__<S>
	implements Iterator<S>
{
	/** The search class. */
	private final Class<S> _search;
	
	/** The array to use for this. */
	private final Object[] _items;
	
	/** The next index. */
	private int _next;
	
	/**
	 * Wraps the given array and provides an iterator of it.
	 *
	 * @param __s The search class.
	 * @param __it The iterator to wrap.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/06
	 */
	__ServiceLoaderCachedIterator__(Class<S> __s, Object[] __it)
		throws NullPointerException
	{
		if (__s == null || __it == null)
			throw new NullPointerException("NARG");
		
		this._search = __s;
		this._items = __it;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/06
	 */
	@Override
	public final boolean hasNext()
	{
		return this._next < this._items.length;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/06
	 */
	@Override
	public final S next()
	{
		Object[] items = this._items;
		int next = this._next;
		
		// No more?
		if (next >= items.length)
			throw new NoSuchElementException("NSEE");
		
		// Get and iterator
		Object rv = items[next];
		this._next = next + 1;
		return this._search.cast(rv);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/06
	 */
	@Override
	public final void remove()
	{
		throw new UnsupportedOperationException("RORO");
	}
}

Added modules/cldc-compact/src/main/java/java/util/__ServiceLoaderFreshIterator__.java.























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package java.util;

import cc.squirreljme.jvm.mle.JarPackageShelf;
import cc.squirreljme.jvm.mle.brackets.JarPackageBracket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * Iterator over a fresh search pouring into the cache.
 *
 * @param <S> The class type.
 * @since 2018/12/06
 */
final class __ServiceLoaderFreshIterator__<S>
	implements Iterator<S>
{
	/** The search class. */
	private final Class<S> _search;
	
	/** The cache to put in. */
	private final __ServiceLoaderCache__<S> _cache;
	
	/** Temporary cache building. */
	private final List<Object> _cacheBuild =
		new ArrayList<>();
	
	/** JARs left to parse. */
	private final Queue<JarPackageBracket> _jarsLeft =
		new LinkedList<>();
	
	/** Classes left to create and scan. */
	private final Queue<String> _classes =
		new LinkedList<>();
	
	/** The next service to run. */
	private S _next;
	
	/** Is this finished? */
	private boolean _finished;
	
	/**
	 * Initializes the iterator for fresh service lookup.
	 *
	 * @param __s The search class.
	 * @param __c The cache class.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/12/06
	 */
	__ServiceLoaderFreshIterator__(Class<S> __s, __ServiceLoaderCache__<S> __c)
		throws NullPointerException
	{
		if (__s == null || __c == null)
			throw new NullPointerException("NARG");
		
		this._search = __s;
		this._cache = __c;
		
		// All of the suites to look within
		this._jarsLeft.addAll(
			Arrays.<JarPackageBracket>asList(JarPackageShelf.classPath()));
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/06
	 */
	@Override
	public final boolean hasNext()
	{
		// If already finished, nothing can be done
		if (this._finished)
			return false;
		
		// Already cached?
		if (this._next != null)
			return true;
		
		// Loops until an element was found
		for (Queue<String> classes = this._classes;;)
		{
			// If there are no classes, consume the next one
			if (classes.isEmpty())
			{
				this.__consumeNextJar();
				
				// Early out when nothing is left
				if (this._finished)
					return false;
			}
			
			// If there is an entry in the class list, try to load that
			// class
			String maybe = classes.poll();
			if (maybe != null)
			{
				// Try to load this class
				try
				{
					// If this fails an exception is thrown
					Class<?> cl = Class.forName(maybe);
					
					// Try to create a new instance since this is new,
					// any exceptions thrown cause errors
					Object rv = cl.newInstance();
					
					// Cache this instance for later
					this._cacheBuild.add(rv);
					
					// Cast this class
					this._next = this._search.cast(rv);
					return true;
				}
				
				// {@squirreljme.error ZZ30 Could not load the service
				// class.}
				catch (ClassCastException|IllegalAccessException|
					InstantiationException|ClassNotFoundException e)
				{
					throw new ServiceConfigurationError("ZZ30", e);
				}
			}
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/06
	 */
	@Override
	public final S next()
	{
		// Cache
		if (!this.hasNext())
			throw new NoSuchElementException("NSEE");
		
		// Return the cached element
		S rv = this._next;
		this._next = null;
		return rv;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2018/12/06
	 */
	@Override
	public final void remove()
	{
		throw new UnsupportedOperationException("RORO");
	}
	
	/**
	 * Consume the next JAR and loads the classes.
	 *
	 * @since 2020/06/18
	 */
	private void __consumeNextJar()
	{
		// If there are no JARs left, then just stop processing
		JarPackageBracket nextJar = this._jarsLeft.poll();
		if (nextJar == null)
		{
			// Mark as done
			this._finished = true;
			
			// Push these services into the cache
			List<Object> cb = this._cacheBuild;
			this._cache._cache = cb.<Object>toArray(
				new Object[cb.size()]);
			
			// Clear from this fresh iterator
			cb.clear();
			
			return;
		}
		
		// Load the Jar otherwise
		this.__loadJar(nextJar);
	}
	
	/**
	 * Loads the specified JAR.
	 *
	 * @param __jar The Jar to load.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/18
	 */
	@SuppressWarnings("UnnecessaryLocalVariable")
	private void __loadJar(JarPackageBracket __jar)
		throws NullPointerException
	{
		if (__jar == null)
			throw new NullPointerException("NARG");
		
		// Load the services for the given Jar
		try (InputStream in = JarPackageShelf.openResource(__jar,
			"META-INF/services/" + this._search.getName()))
		{
			// If this JAR has no services, ignore it
			if (in == null)
				return;
			
			// Read by line
			Queue<String> classes = this._classes;
			try (BufferedReader br = new BufferedReader(
				new InputStreamReader(in, "utf-8")))
			{
				// Read in every service line
				for (;;)
				{
					// Stop on EOF
					String ln = br.readLine();
					if (ln == null)
						break;
					
					// Trim the line to remove useless spaces
					ln = ln.trim();
					
					// Ignore blank lines
					if (ln.isEmpty())
						continue;
					
					// Ignore comments
					if (ln.charAt(0) == '#')
						continue;
					
					// Add otherwise
					classes.add(ln);
				}
			}
		}
		
		// {@squirreljme.error ZZ31 Could not read the services
		// list.}
		catch (IOException e)
		{
			throw new ServiceConfigurationError("ZZ31", e);
		}
	}
}

Added modules/cldc-compact/src/main/java/java/util/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This contains general Java utility classes.
 *
 * @since 2020/06/17
 */

package java.util;

Changes to modules/cldc-compact/src/main/java/todo/DEBUG.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package todo;

import cc.squirreljme.runtime.cldc.Poking;
import cc.squirreljme.runtime.cldc.debug.Debugging;

/**
 * This class contains static methods for debug printing messages as needed.
 *
 * @since 2018/04/09
 */












<







1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package todo;


import cc.squirreljme.runtime.cldc.debug.Debugging;

/**
 * This class contains static methods for debug printing messages as needed.
 *
 * @since 2018/04/09
 */
36
37
38
39
40
41
42
43
44
45
46
47
48
	 * incomplete.
	 *
	 * @param __fmt The format string.
	 * @param __args The arguments to the call.
	 * @since 2018/04/09
	 */
	@Deprecated
	public static final void note(String __fmt, Object... __args)
	{
		Debugging.debugNote(__fmt, __args);
	}
}








|





35
36
37
38
39
40
41
42
43
44
45
46
47
	 * incomplete.
	 *
	 * @param __fmt The format string.
	 * @param __args The arguments to the call.
	 * @since 2018/04/09
	 */
	@Deprecated
	public static void note(String __fmt, Object... __args)
	{
		Debugging.debugNote(__fmt, __args);
	}
}

Changes to modules/cldc-compact/src/main/java/todo/OOPS.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package todo;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import java.io.PrintStream;

/**
 * This is an error which is thrown when a condition which should not occur
 * occurs.
 *
 * @since 2018/11/25
 */

public class OOPS
	extends Error
{
	/**
	 * Generates an oops with no message.
	 *
	 * @since 2018/11/25
	 */

	public OOPS()
	{
		this(null, null);
	}
	
	/**
	 * Generates an oops with the given message.
	 *
	 * @param __m The message to use.
	 * @since 2018/11/25
	 */
	public OOPS(String __m)
	{
		this(__m, null);
	}
	
	/**
	 * Generates an oops with the given cause.
	 *
	 * @param __t The cause to use.
	 * @since 2018/11/25
	 */
	public OOPS(Throwable __t)
	{
		this(null, __t);
	}
	
	/**
	 * Generates an oops with the given message and cause.
	 *
	 * @param __m The message to use.
	 * @param __t The cause.
	 * @since 2018/11/25
	 */
	public OOPS(String __m, Throwable __t)
	{
		super(__m, __t);
		
		// Detect OOPSes/TODOs tripping multiple times and fail
		boolean doubletripped = TODO._DOUBLE_TRIP;
		if (doubletripped)
			Assembly.sysCallP(SystemCallIndex.FATAL_TODO);
		TODO._DOUBLE_TRIP = true;
		
		// Print a starting banner, but only if the error stream exists
		PrintStream ps = System.err;
		if (ps != null)
		{
			// Top banner
			ps.println("****************************************************");
			ps.print("OOPS CONDITION WAS MET: ");
			if (__m != null)
				ps.print(__m);
			ps.println();
			
			// Print the current thread
			ps.print("IN THREAD: ");
			ps.println(Thread.currentThread());
			
			// Spacer
			ps.println();
			
			// Print the trace
			this.printStackTrace(ps);
			
			// Ending banner
			ps.println("****************************************************");
		}
		
		// No streams are currently available, but we would still like to
		// report the trace information to the debugger, we might not be in any
		// condition to actually do printing to the console so this will end
		// here
		else
			Assembly.sysCallP(SystemCallIndex.FATAL_TODO);
		
		// {@squirreljme.property
		// cc.squirreljme.nooopsexit=(boolean)
		// If this is {@code true} then the OOPS exception will not tell the
		// virtual machine to exit.}
		if (!Boolean.valueOf(
			System.getProperty("cc.squirreljme.nooopsexit")))
			try
			{
				System.exit(125);
			}
		
			// Ignore
			catch (SecurityException e)
			{
			}
	}
}













|
<
<







>








>


|








<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41




42


















43
44

45





















































46
47
48
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package todo;

import cc.squirreljme.runtime.cldc.debug.Debugging;



/**
 * This is an error which is thrown when a condition which should not occur
 * occurs.
 *
 * @since 2018/11/25
 */
@Deprecated
public class OOPS
	extends Error
{
	/**
	 * Generates an oops with no message.
	 *
	 * @since 2018/11/25
	 */
	@Deprecated
	public OOPS()
	{
		throw Debugging.todo();
	}
	
	/**
	 * Generates an oops with the given message.
	 *
	 * @param __m The message to use.
	 * @since 2018/11/25
	 */




	@Deprecated


















	public OOPS(String __m)
	{

		throw Debugging.todo(__m);





















































	}
}

Changes to modules/cldc-compact/src/main/java/todo/TODO.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package todo;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.runtime.cldc.Poking;
import cc.squirreljme.runtime.cldc.debug.CallTraceElement;
import cc.squirreljme.runtime.cldc.lang.GuestDepth;
import java.io.PrintStream;

/**
 * This exception is thrown.
 *
 * When constructed, this exception does not normall finish execution.
 *
 * @since 2017/02/28
 */

public class TODO
	extends Error
{
	/** Debug by default? */
	private static final boolean _DEFAULT_DEBUG =
		true;
	
	/** Should messages be squelched? */
	private static final boolean _SQUELCH;
	
	/** Used to detect TODOs recursively being called. */
	static volatile boolean _DOUBLE_TRIP;
	
	/** Suppress infinite note TODOs being printed over and over. */
	private static volatile boolean _notelock;
	
	/** The number of suppressed note TODOs. */
	private static volatile int _supressednotes;
	
	/**
	 * Checks if debug messages should be printed.
	 *
	 * @since 2018/11/04
	 */
	static
	{
		// Poke native VM stuff to make sure it exists before we try to use it
		Poking.poke();
		
		// Debugging?
		boolean debug;
		try
		{
			// {@squirreljme.property cc.squirreljme.debug Set to a boolean
			// value (true or false) which specifies whether todo and debug
			// messages should be printed to the console.}
			debug = Boolean.valueOf(
				System.getProperty("cc.squirreljme.debug",
				Boolean.valueOf(TODO._DEFAULT_DEBUG).toString()));
		}
		
		// Cannot access properties so use the default
		catch (SecurityException e)
		{
			debug = TODO._DEFAULT_DEBUG;
		}
		
		// Squelch based on reverse debug
		_SQUELCH = !debug;
	}
	
	/**
	 * Initializes the exception, prints the trace, and exits the program.
	 *
	 * @since 2017/02/28
	 */

	public TODO()
	{
		this(null);
	}
	
	/**
	 * Initializes the exception, prints the trace, and exits the program.
	 *
	 * @param __s Message input.
	 * @since 2018/09/29
	 */

	public TODO(String __s)
	{
		super(__s);
		
		// Detect TODOs tripping multiple times and fail
		boolean doubletripped = TODO._DOUBLE_TRIP;
		if (doubletripped)
			Assembly.sysCallP(SystemCallIndex.FATAL_TODO);
		TODO._DOUBLE_TRIP = true;
		
		// Print a starting banner, but only if the error stream exists
		PrintStream ps = System.err;
		if (ps != null)
		{
			ps.println("****************************************************");
			ps.print("INCOMPLETE CODE HAS BEEN REACHED: ");
			if (__s != null)
				ps.print(__s);
			ps.println();
			
			// Print the current thread
			ps.print("IN THREAD: ");
			ps.println(Thread.currentThread());
			
			// Spacer
			ps.println();
			
			// Print the trace
			this.printStackTrace(ps);
			
			// Ending banner
			ps.println("****************************************************");
		}
		
		// No streams are currently available, but we would still like to
		// report the trace information to the debugger, we might not be in any
		// condition to actually do printing to the console so this will end
		// here
		else
			Assembly.sysCallP(SystemCallIndex.FATAL_TODO);
		
		// {@squirreljme.property
		// cc.squirreljme.notodoexit=(boolean)
		// If this is {@code true} then the ToDo exception will not tell the
		// virtual machine to exit.}
		if (!Boolean.valueOf(
			System.getProperty("cc.squirreljme.notodoexit")))
			try
			{
				System.exit(126);
			}
		
			// Ignore
			catch (SecurityException e)
			{
			}
	}
	
	/**
	 * Specifies that the integer value is missing.
	 *
	 * @return An integer, but is not returned from.
	 * @since 2017/10/27
	 */

	public static final int missingInteger()
	{
		throw new todo.TODO();
	}
	
	/**
	 * Specifies that the object value is missing.
	 *
	 * @param <T> The object to miss.
	 * @return Should return that object, but never does.
	 * @since 2017/10/24
	 */

	public static final <T> T missingObject()
	{
		throw new todo.TODO();
	}
	
	/**
	 * Prints a note to standard error about something that is incomplete.
	 *
	 * @param __fmt The format string.
	 * @param __args The arguments to the call.
	 * @since 2018/04/02
	 */
	public static final void note(String __fmt, Object... __args)
	{
		TODO.__note("TODO", __fmt, __args);
	}
	
	/**
	 * Formats a call trace element in a condensed form.
	 *
	 * @param __e The element to print out.
	 * @return The condensed string.
	 * @since 2018/05/03
	 */
	static final String __formatCondensedTrace(CallTraceElement __e)
		throws NullPointerException
	{
		if (__e == null)
			throw new NullPointerException("NARG");
		
		String cn = __e.className(),
			mn = __e.methodName(),
			md = __e.methodDescriptor(),
			fi = __e.file();
		long ad = __e.address();
		int ln = __e.line();
		
		StringBuilder sb = new StringBuilder();
		
		// Location
		if (cn != null)
		{
			// Get identifier part
			int ld = cn.lastIndexOf('.');
			if (ld < 0)
				if ((ld = cn.lastIndexOf('/')) < 0)
					ld = 0;
			
			// Print slimmed down packages since they could be guessed
			for (int i = 0, n = cn.length(); i >= 0 && i < n;)
			{
				// Before the last dot, print single and skip ahead
				if (i < ld)
				{
					sb.append(cn.charAt(i));
					
					int ldi = cn.indexOf('.', i);
					if (ldi < 0)
						ldi = cn.indexOf('/', i);
					
					i = ldi + 1;
				}
				
				// Finish string
				else
				{
					if (i > 0)
						sb.append('.');
					sb.append(cn.substring(i));
					break;
				}
			}
		}
		sb.append("::");
		if (mn != null)
			sb.append(mn);
		/*if (md != null)
			sb.append(md);*/
		
		// Address, if it is valid
		if (ad != -1L)
		{
			sb.append(" @ ");
			sb.append(Long.toString(ad, 16).toUpperCase());
			sb.append("h");
		}
		
		// Add file/line information if it is valid
		if (fi != null)
		{
			sb.append(" (");
			
			// Use blank class name if not specified
			if (cn == null)
				cn = "";
			
			// The class will end with the Java extension
			int ld = cn.lastIndexOf('.');
			if (ld < 0)
				ld = cn.lastIndexOf('/');
			if (ld >= 0)
				cn = cn.substring(ld + 1);
			
			// Determine how many charcters the class name and the file
			// name have in common, so that it can be shortened
			int deep = 0;
			for (int n = Math.min(cn.length(), fi.length()); deep < n; deep++)
				if (cn.charAt(deep) != fi.charAt(deep))
					break;
			
			// Use whole name
			if (deep == 0)
				sb.append(fi);
			
			// Use fragment
			else
			{
				// But only if it does not end in .java, this makes it
				// implied since it is always around
				String sub = fi.substring(deep);
				if (!sub.equals(".java"))
				{
					sb.append('*');
					sb.append(sub);
				}
			}
			
			if (ln >= 0)
			{
				sb.append(':');
				sb.append(ln);
			}
			
			sb.append(')');
		}
		
		return sb.toString();
	}
	
	/**
	 * Formats the call trace element.
	 *
	 * @param __e The element to format.
	 * @return The formatted string.
	 * @since 2018/04/02
	 */
	static final String __formatTrace(CallTraceElement __e)
		throws NullPointerException
	{
		if (__e == null)
			throw new NullPointerException("NARG");
		
		String cn = __e.className(),
			mn = __e.methodName(),
			md = __e.methodDescriptor(),
			fi = __e.file();
		long ad = __e.address();
		int ln = __e.line();
		
		StringBuilder sb = new StringBuilder();
		
		// Location
		if (cn != null)
			sb.append(cn);
		sb.append("::");
		if (mn != null)
			sb.append(mn);
		
		if (md != null)
			sb.append(md);
		
		// Address, if it is valid
		if (ad != -1L)
		{
			sb.append(" @ ");
			sb.append(ad);
		}
		
		// Add file/line information if it is valid
		if (fi != null)
		{
			sb.append(" (");
			sb.append(fi);
			
			if (ln >= 0)
			{
				sb.append(':');
				sb.append(ln);
			}
			
			sb.append(')');
		}
		
		return sb.toString();
	}
	
	
	/**
	 * Prints a note to standard error about something that is incomplete.
	 *
	 * @param __fmt The format string.
	 * @param __args The arguments to the call.
	 * @since 2018/04/02
	 */
	static final void __note(String __pfx, String __fmt, Object... __args)
	{
		// If messages are squelched, ignore anything output
		if (TODO._SQUELCH)
			return;
		
		// Only print if the stream is valid
		PrintStream ps = System.err;
		if (ps == null)
			return;
		
		// Prevent infinite recursion when printing notes because things might
		// get stuck here if code that this method calls ends up calling
		// things
		boolean printy = false;
		synchronized (TODO.class)
		{
			// Use simple lock counter
			if (!TODO._notelock)
				try
				{
					// Lock note
					TODO._notelock = true;
					printy = true;
				}
				finally
				{
				}
			
			// Add marker for suppressed notes
			else
				TODO._supressednotes++;
		}
		
		// Print it out?
		if (printy)
			try
			{
				ps.print(__pfx);
				ps.print(GuestDepth.guestDepth());
				ps.print(' ');
				ps.print(TODO.__formatCondensedTrace(TODO.__where()));
				ps.print(" -- ");
				
				ps.printf(__fmt, __args);
				
				// Add markers to indicate the number of notes which were
				// suppressed
				int suppressed = TODO._supressednotes;
				TODO._supressednotes = 0;
				for (int i = 0; i < suppressed; i++)
					ps.print('^');
				
				ps.println();
			}
			finally
			{
				// In case of exceptions, this will always be unlocked
				TODO._notelock = false;
			}
	}
	
	/**
	 * Determines where the code is in the call stack.
	 *
	 * @return The call trace element for the current location.
	 * @since 2018/04/02
	 */
	static final CallTraceElement __where()
	{
		// For the SquirrelJME runtime, use the debug stuff to get the
		// current call trace
		CallTraceElement[] stack = CallTraceElement.traceResolve(
			CallTraceElement.traceRaw());
		
		// Get the first one which is not in this class
		for (CallTraceElement e : stack)
		{
			String cn = e.className();
			if (cn == null)
				cn = "<unknown>";
			
			if (!cn.startsWith("todo/"))
				return e;
		}
		
		// Unknown
		return new CallTraceElement();
	}
}













<
<
<
|
<
<








>



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




>


|








>


|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








>
|

|









>
|

|









<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



1
2
3
4
5
6
7
8
9
10
11
12



13


14
15
16
17
18
19
20
21
22
23
24
25
















26
































27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46





















































47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80




81



























































































































































































82
83










































84











































85
86
87
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package todo;




import cc.squirreljme.runtime.cldc.debug.Debugging;



/**
 * This exception is thrown.
 *
 * When constructed, this exception does not normall finish execution.
 *
 * @since 2017/02/28
 */
@Deprecated
public class TODO
	extends Error
{
















	/**
































	 * Initializes the exception, prints the trace, and exits the program.
	 *
	 * @since 2017/02/28
	 */
	@Deprecated
	public TODO()
	{
		throw Debugging.todo();
	}
	
	/**
	 * Initializes the exception, prints the trace, and exits the program.
	 *
	 * @param __s Message input.
	 * @since 2018/09/29
	 */
	@Deprecated
	public TODO(String __s)
	{
		throw Debugging.todo(__s);





















































	}
	
	/**
	 * Specifies that the integer value is missing.
	 *
	 * @return An integer, but is not returned from.
	 * @since 2017/10/27
	 */
	@Deprecated
	public static int missingInteger()
	{
		throw Debugging.todo();
	}
	
	/**
	 * Specifies that the object value is missing.
	 *
	 * @param <T> The object to miss.
	 * @return Should return that object, but never does.
	 * @since 2017/10/24
	 */
	@Deprecated
	public static <T> T missingObject()
	{
		throw Debugging.todo();
	}
	
	/**
	 * Prints a note to standard error about something that is incomplete.
	 *
	 * @param __fmt The format string.
	 * @param __args The arguments to the call.
	 * @since 2018/04/02
	 */




	@Deprecated



























































































































































































	public static void note(String __fmt, Object... __args)
	{










































		Debugging.todoNote(__fmt, __args);











































	}
}

Changes to modules/cldc-compact/src/test/java/lang/TestMonitorNotify.java.

16
17
18
19
20
21
22




23
24
25
26
27
28
29
 * Tests that monitor notification works.
 *
 * @since 2018/11/21
 */
public class TestMonitorNotify
	extends TestRunnable
{




	/** Counter. */
	volatile int _count;
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/21
	 */







>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * Tests that monitor notification works.
 *
 * @since 2018/11/21
 */
public class TestMonitorNotify
	extends TestRunnable
{
	/** Monitor timeout, so not waiting forever. */
	public static final long TIMEOUT =
		10_000L;
	
	/** Counter. */
	volatile int _count;
	
	/**
	 * {@inheritDoc}
	 * @since 2018/11/21
	 */
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
			
			// Note
			this.secondary("thread-created", this._count++);
			
			// Wait on monitor
			try
			{
				// Wait forever
				this.wait();
				
				// Note
				this.secondary("expected-resume", this._count++);
			}
			
			// Interrupted?
			catch (InterruptedException e)







|
|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
			
			// Note
			this.secondary("thread-created", this._count++);
			
			// Wait on monitor
			try
			{
				// Wait for the time that should be good enough
				this.wait(TestMonitorNotify.TIMEOUT);
				
				// Note
				this.secondary("expected-resume", this._count++);
			}
			
			// Interrupted?
			catch (InterruptedException e)
79
80
81
82
83
84
85
86
87




88
89
90
91
92
93
94
		/**
		 * {@inheritDoc}
		 * @since 2018/11/21
		 */
		@Override
		public void run()
		{
			// Lock on that monitor
			TestMonitorNotify tmn = TestMonitorNotify.this;




			synchronized (tmn)
			{
				// Note
				tmn.secondary("sub-in-lock", tmn._count++);
				
				// Notify other thread
				tmn.notify();







<

>
>
>
>







83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
		/**
		 * {@inheritDoc}
		 * @since 2018/11/21
		 */
		@Override
		public void run()
		{

			TestMonitorNotify tmn = TestMonitorNotify.this;
			
			tmn.secondary("sub-started", true);
			
			// Lock on that monitor
			synchronized (tmn)
			{
				// Note
				tmn.secondary("sub-in-lock", tmn._count++);
				
				// Notify other thread
				tmn.notify();

Changes to modules/cldc-compact/src/test/java/lang/TestVMInterrupt.java.

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
			// Note
			this.secondary("a-thread-created", order++);
			this.secondary("a-before-wait", self.isInterrupted());
			
			// Wait for a notification
			try
			{
				this.lock.wait();
				
				// Note
				this.secondary("a-was-not-interrupted", order++);
			}
			catch (InterruptedException e)
			{
				// Note







|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
			// Note
			this.secondary("a-thread-created", order++);
			this.secondary("a-before-wait", self.isInterrupted());
			
			// Wait for a notification
			try
			{
				this.lock.wait(20000);
				
				// Note
				this.secondary("a-was-not-interrupted", order++);
			}
			catch (InterruptedException e)
			{
				// Note

Name change from modules/cldc-compact/src/test/java/squirreljme/TestArrayLength.java to modules/cldc-compact/src/test/java/squirreljme/mle/TestArrayLength.java.

1
2
3
4
5
6
7
8
9
10
package squirreljme;

import cc.squirreljme.jvm.Assembly;
import net.multiphasicapps.tac.TestRunnable;

public class TestArrayLength
	extends TestRunnable
{
	/**
	 * {@inheritDoc}
|

|







1
2
3
4
5
6
7
8
9
10
package squirreljme.mle;

import cc.squirreljme.jvm.mle.ObjectShelf;
import net.multiphasicapps.tac.TestRunnable;

public class TestArrayLength
	extends TestRunnable
{
	/**
	 * {@inheritDoc}
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
			i = new int[5],
			j = new long[6],
			f = new float[7],
			d = new double[8],
			l = new Object[9],
			o = new Object();
		
		// As pointers
		this.secondary("zp",
			Assembly.arrayLength(Assembly.objectToPointer(z)));
		this.secondary("bp",
			Assembly.arrayLength(Assembly.objectToPointer(b)));
		this.secondary("sp",
			Assembly.arrayLength(Assembly.objectToPointer(s)));
		this.secondary("cp",
			Assembly.arrayLength(Assembly.objectToPointer(c)));
		this.secondary("ip",
			Assembly.arrayLength(Assembly.objectToPointer(i)));
		this.secondary("jp",
			Assembly.arrayLength(Assembly.objectToPointer(j)));
		this.secondary("fp",
			Assembly.arrayLength(Assembly.objectToPointer(f)));
		this.secondary("dp",
			Assembly.arrayLength(Assembly.objectToPointer(d)));
		this.secondary("lp",
			Assembly.arrayLength(Assembly.objectToPointer(l)));
		this.secondary("op",
			Assembly.arrayLength(Assembly.objectToPointer(o)));
		
		// As objects
		this.secondary("z", Assembly.arrayLength(z));
		this.secondary("b", Assembly.arrayLength(b));
		this.secondary("s", Assembly.arrayLength(s));
		this.secondary("c", Assembly.arrayLength(c));
		this.secondary("i", Assembly.arrayLength(i));
		this.secondary("j", Assembly.arrayLength(j));
		this.secondary("f", Assembly.arrayLength(f));
		this.secondary("d", Assembly.arrayLength(d));
		this.secondary("l", Assembly.arrayLength(l));
		this.secondary("o", Assembly.arrayLength(o));
	}
}







|
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
20
21
22
23
24
25
26
27
28

29

30

31

32

33

34

35

36

37

38











39

			i = new int[5],
			j = new long[6],
			f = new float[7],
			d = new double[8],
			l = new Object[9],
			o = new Object();
		
		// As objects
		this.secondary("z", ObjectShelf.arrayLength(z));

		this.secondary("b", ObjectShelf.arrayLength(b));

		this.secondary("s", ObjectShelf.arrayLength(s));

		this.secondary("c", ObjectShelf.arrayLength(c));

		this.secondary("i", ObjectShelf.arrayLength(i));

		this.secondary("j", ObjectShelf.arrayLength(j));

		this.secondary("f", ObjectShelf.arrayLength(f));

		this.secondary("d", ObjectShelf.arrayLength(d));

		this.secondary("l", ObjectShelf.arrayLength(l));

		this.secondary("o", ObjectShelf.arrayLength(o));

	}











}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestArrayInvalidBoolean.java.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;

/**
 * Test boolean array operations.
 *
 * @since 2020/06/22
 */
public class TestArrayInvalidBoolean
	extends __BaseArrayInvalidTest__<boolean[]>
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected boolean[] arrayNew(int __len)
	{
		return new boolean[__len];
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected void arrayOperation(boolean[] __src, int __srcOff,
		boolean[] __dest, int __destOff, int __len)
	{
		ObjectShelf.arrayCopy(__src, __srcOff, __dest, __destOff, __len);
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestArrayInvalidByte.java.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;

/**
 * Test byte array operations.
 *
 * @since 2020/06/22
 */
public class TestArrayInvalidByte
	extends __BaseArrayInvalidTest__<byte[]>
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected byte[] arrayNew(int __len)
	{
		return new byte[__len];
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected void arrayOperation(byte[] __src, int __srcOff, byte[] __dest,
		int __destOff, int __len)
	{
		ObjectShelf.arrayCopy(__src, __srcOff, __dest, __destOff, __len);
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestArrayInvalidCharacter.java.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;

/**
 * Test char array operations.
 *
 * @since 2020/06/22
 */
public class TestArrayInvalidCharacter
	extends __BaseArrayInvalidTest__<char[]>
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected char[] arrayNew(int __len)
	{
		return new char[__len];
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected void arrayOperation(char[] __src, int __srcOff,
		char[] __dest, int __destOff, int __len)
	{
		ObjectShelf.arrayCopy(__src, __srcOff, __dest, __destOff, __len);
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestArrayInvalidDouble.java.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;

/**
 * Test double array operations.
 *
 * @since 2020/06/22
 */
public class TestArrayInvalidDouble
	extends __BaseArrayInvalidTest__<double[]>
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected double[] arrayNew(int __len)
	{
		return new double[__len];
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected void arrayOperation(double[] __src, int __srcOff,
		double[] __dest, int __destOff, int __len)
	{
		ObjectShelf.arrayCopy(__src, __srcOff, __dest, __destOff, __len);
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestArrayInvalidFloat.java.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;

/**
 * Test float array operations.
 *
 * @since 2020/06/22
 */
public class TestArrayInvalidFloat
	extends __BaseArrayInvalidTest__<float[]>
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected float[] arrayNew(int __len)
	{
		return new float[__len];
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected void arrayOperation(float[] __src, int __srcOff,
		float[] __dest, int __destOff, int __len)
	{
		ObjectShelf.arrayCopy(__src, __srcOff, __dest, __destOff, __len);
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestArrayInvalidInteger.java.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;

/**
 * Test int array operations.
 *
 * @since 2020/06/22
 */
public class TestArrayInvalidInteger
	extends __BaseArrayInvalidTest__<int[]>
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected int[] arrayNew(int __len)
	{
		return new int[__len];
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected void arrayOperation(int[] __src, int __srcOff,
		int[] __dest, int __destOff, int __len)
	{
		ObjectShelf.arrayCopy(__src, __srcOff, __dest, __destOff, __len);
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestArrayInvalidLong.java.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;

/**
 * Test long array operations.
 *
 * @since 2020/06/22
 */
public class TestArrayInvalidLong
	extends __BaseArrayInvalidTest__<long[]>
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected long[] arrayNew(int __len)
	{
		return new long[__len];
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected void arrayOperation(long[] __src, int __srcOff,
		long[] __dest, int __destOff, int __len)
	{
		ObjectShelf.arrayCopy(__src, __srcOff, __dest, __destOff, __len);
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestArrayInvalidShort.java.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;

/**
 * Test short array operations.
 *
 * @since 2020/06/22
 */
public class TestArrayInvalidShort
	extends __BaseArrayInvalidTest__<short[]>
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected short[] arrayNew(int __len)
	{
		return new short[__len];
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	protected void arrayOperation(short[] __src, int __srcOff,
		short[] __dest, int __destOff, int __len)
	{
		ObjectShelf.arrayCopy(__src, __srcOff, __dest, __destOff, __len);
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestAtomicShelfInvalid.java.































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.AtomicShelf;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Test invalid {@link AtomicShelf} calls.
 *
 * @since 2020/06/22
 */
public class TestAtomicShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				AtomicShelf.gcUnlock(1234565789);
				break;
			
			case 1:
				AtomicShelf.spinLock(-12345678);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestDebugShelfInvalid.java.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.DebugShelf;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Tests invalid calls in {@link DebugShelf}.
 *
 * @since 2020/06/22
 */
public class TestDebugShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				DebugShelf.getThrowableTrace(null);
				break;
			
			case 1:
				DebugShelf.pointAddress(null);
				break;
			
			case 2:
				DebugShelf.pointClass(null);
				break;
			
			case 3:
				DebugShelf.pointFile(null);
				break;
			
			case 4:
				DebugShelf.pointJavaAddress(null);
				break;
			
			case 5:
				DebugShelf.pointJavaOperation(null);
				break;
			
			case 6:
				DebugShelf.pointLine(null);
				break;
			
			case 7:
				DebugShelf.pointMethodName(null);
				break;
			
			case 8:
				DebugShelf.pointMethodType(null);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestJarPackageShelfInvalid.java.











































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.JarPackageShelf;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Tests {@link JarPackageShelf}.
 *
 * @since 2020/06/22
 */
public class TestJarPackageShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@SuppressWarnings("resource")
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				JarPackageShelf.openResource(null, null);
				break;
			
			case 1:
				JarPackageShelf.openResource(null, "hello");
				break;
			
			case 2:
				JarPackageShelf.openResource(
					JarPackageShelf.classPath()[0], null);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestObjectShelfInvalid.java.





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Tests {@link ObjectShelf}.
 *
 * @since 2020/06/22
 */
public class TestObjectShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				ObjectShelf.arrayNew(null, -1);
				break;
			
			case 1:
				ObjectShelf.arrayNew(
					TypeShelf.typeOfByte(), 1234);
				break;
			
			case 2:
				ObjectShelf.arrayNew(
					TypeShelf.classToType(byte[].class), -1234);
				break;
			
			case 3:
				ObjectShelf.arrayLength(null);
				break;
			
			case 4:
				ObjectShelf.holdsLock(null, null);
				break;
			
			case 5:
				ObjectShelf.holdsLock(Thread.currentThread(), null);
				break;
			
			case 6:
				ObjectShelf.holdsLock(null, new Object());
				break;
			
			case 7:
				ObjectShelf.identityHashCode(null);
				break;
			
			case 8:
				ObjectShelf.newInstance(null);
				break;
			
			case 9:
				ObjectShelf.newInstance(TypeShelf.classToType(byte[].class));
				break;
			
			case 10:
				ObjectShelf.notify(null, false);
				break;
			
			case 11:
				ObjectShelf.wait(null, -1, -1);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestReferenceShelfInvalid.java.























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ReferenceShelf;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Tests {@link ReferenceShelf} for invalid inputs.
 *
 * @since 2020/06/22
 */
public class TestReferenceShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				ReferenceShelf.linkGetObject(null);
				break;
			
			case 1:
				ReferenceShelf.linkGetPrev(null);
				break;
			
			case 2:
				ReferenceShelf.linkGetNext(null);
				break;
			
			case 3:
				ReferenceShelf.objectGet(null);
				break;
			
			case 4:
				ReferenceShelf.objectSet(null, null);
				break;
			
			case 5:
				ReferenceShelf.objectSet(null,
					ReferenceShelf.newLink());
				break;
			
			case 6:
				ReferenceShelf.deleteLink(null);
				break;
			
			case 7:
				ReferenceShelf.linkSetPrev(null, null);
				break;
			
			case 8:
				ReferenceShelf.linkSetPrev(null,
					ReferenceShelf.newLink());
				break;
			
			case 9:
				ReferenceShelf.linkSetNext(null, null);
				break;
			
			case 10:
				ReferenceShelf.linkSetNext(null,
					ReferenceShelf.newLink());
				break;
			
			case 11:
				ReferenceShelf.linkSetObject(null,
					new Object());
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestRuntimeShelfInvalid.java.



























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.VMDescriptionType;
import cc.squirreljme.jvm.mle.constants.VMStatisticType;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Tests {@link RuntimeShelf} for invalid inputs.
 *
 * @since 2020/06/22
 */
public class TestRuntimeShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				RuntimeShelf.vmDescription(-1234);
				break;
			
			case 1:
				RuntimeShelf.vmDescription(VMDescriptionType.NUM_TYPES);
				break;
			
			case 2:
				RuntimeShelf.vmStatistic(-1234);
				break;
			
			case 3:
				RuntimeShelf.vmStatistic(VMStatisticType.NUM_STATISTICS);
				break;
			
			case 4:
				RuntimeShelf.systemProperty(null);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestTerminalShelfInvalid.java.





































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.TerminalShelf;
import cc.squirreljme.jvm.mle.constants.StandardPipeType;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Tests {@link TerminalShelf}.
 *
 * @since 2020/06/22
 */
public class TestTerminalShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				TerminalShelf.flush(-1);
				break;
			
			case 1:
				TerminalShelf.write(-1, 0);
				break;
			
			case 2:
				TerminalShelf.write(-1, null, 0, 0);
				break;
			
			case 3:
				TerminalShelf.write(StandardPipeType.STDERR,
					null, 0, 0);
				break;
			
			case 4:
				TerminalShelf.write(StandardPipeType.STDERR,
					new byte[12], -2, 14);
				break;
			
			case 5:
				TerminalShelf.write(StandardPipeType.STDERR,
					new byte[12], 2, 12);
				break;
			
			case 6:
				TerminalShelf.write(StandardPipeType.STDERR,
					new byte[12], 0, 14);
				break;
			
			case 7:
				TerminalShelf.write(StandardPipeType.STDERR,
					new byte[12], 2, -14);
				break;
			
			case 8:
				TerminalShelf.write(-1,
					new byte[12], 0, 12);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestThreadShelfInvalid.java.



































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ThreadShelf;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Tests that {@link ThreadShelf} invalid parameters fail.
 *
 * @since 2020/06/22
 */
public class TestThreadShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				ThreadShelf.vmThreadIsMain(null);
				break;
			
			case 1:
				ThreadShelf.javaThreadIsStarted(null);
				break;
			
			case 2:
				ThreadShelf.javaThreadSetAlive(null, false);
				break;
			
			case 3:
				ThreadShelf.createVMThread(null);
				break;
			
			case 4:
				ThreadShelf.javaThreadClearInterrupt(null);
				break;
			
			case 5:
				ThreadShelf.javaThreadFlagStarted(null);
				break;
			
			case 6:
				ThreadShelf.javaThreadRunnable(null);
				break;
			
			case 7:
				ThreadShelf.toJavaThread(null);
				break;
			
			case 8:
				ThreadShelf.toVMThread(null);
				break;
			
			case 9:
				ThreadShelf.vmThreadId(null);
				break;
			
			case 10:
				ThreadShelf.vmThreadInterrupt(null);
				break;
			
			case 11:
				ThreadShelf.vmThreadSetPriority(null, 
					Thread.MIN_PRIORITY - 1);
				break;
			
			case 12:
				ThreadShelf.vmThreadStart(null);
				break;
			
			case 13:
				ThreadShelf.waitForUpdate(-1234);
				break;
			
			case 14:
				ThreadShelf.sleep(-1234, 0);
				break;
			
			case 15:
				ThreadShelf.sleep(0, -1234);
				break;
			
			case 16:
				ThreadShelf.sleep(0, Integer.MAX_VALUE);
				break;
			
			case 17:
				ThreadShelf.vmThreadSetPriority(null, 
					Thread.MAX_PRIORITY + 1);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/TestTypeShelfInvalid.java.































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.TypeShelf;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Tests that invalid inputs to {@link TypeShelf} fail.
 *
 * @since 2020/06/22
 */
public class TestTypeShelfInvalid
	extends __BaseMleErrorTest__
{
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		switch (__index)
		{
			case 0:
				TypeShelf.binaryName(null);
				break;
			
			case 1:
				TypeShelf.binaryPackageName(null);
				break;
			
			case 2:
				TypeShelf.typeToClass(null);
				break;
			
			case 3:
				TypeShelf.isArray(null);
				break;
			
			case 4:
				TypeShelf.isPrimitive(null);
				break;
			
			case 5:
				TypeShelf.inJar(null);
				break;
			
			case 6:
				TypeShelf.classToType(null);
				break;
			
			case 7:
				TypeShelf.component(null);
				break;
			
			case 8:
				TypeShelf.component(TypeShelf.typeOfByte());
				break;
			
			case 9:
				TypeShelf.componentRoot(TypeShelf.typeOfByte());
				break;
			
			case 10:
				TypeShelf.findType(null);
				break;
			
			case 11:
				TypeShelf.interfaces(null);
				break;
			
			case 12:
				TypeShelf.isInterface(null);
				break;
			
			case 13:
				TypeShelf.objectType(null);
				break;
			
			case 14:
				TypeShelf.runtimeName(null);
				break;
			
			case 15:
				TypeShelf.superClass(null);
				break;
			
			case 16:
				TypeShelf.isEnum(null);
				break;
			
			case 17:
				TypeShelf.enumValues(null);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/__BaseArrayInvalidTest__.java.































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.ObjectShelf;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;

/**
 * Base test for arrays in {@link ObjectShelf} due to the large amounts of
 * duplicated logic!
 *
 * @param <A> The array type.
 * @since 2020/06/22
 */
abstract class __BaseArrayInvalidTest__<A>
	extends __BaseMleErrorTest__
{
	/**
	 * Allocates the given array.
	 * 
	 * @param __len The length of the array.
	 * @return The created array.
	 * @since 2020/06/22
	 */
	protected abstract A arrayNew(int __len);
	
	/**
	 * Performs the array operation.
	 * 
	 * @param __src The source.
	 * @param __srcOff The source offset.
	 * @param __dest The destination.
	 * @param __destOff The destination offset.
	 * @param __len The length.
	 * @since 2020/06/22
	 */
	protected abstract void arrayOperation(A __src, int __srcOff,
		A __dest, int __destOff, int __len);
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public boolean test(int __index)
		throws MLECallError
	{
		A src = this.arrayNew(4);
		A dest = this.arrayNew(8);
		
		switch (__index)
		{
			case 0:
				this.arrayOperation(null, 0, 
					null, 0, 0);
				break;
			
			case 1:
				this.arrayOperation(src, 0, 
					null, 0, 0);
				break;
			
			case 2:
				this.arrayOperation(null, 0, 
					dest, 0, 0);
				break;
			
			case 3:
				this.arrayOperation(src, 0, 
					dest, 0, -1);
				break;
			
			case 4:
				this.arrayOperation(src, 0, 
					dest, 0, 12);
				break;
			
			case 5:
				this.arrayOperation(src, 0, 
					dest, 6, 4);
				break;
			
			case 6:
				this.arrayOperation(src, 2, 
					dest, 0, 6);
				break;
			
			case 7:
				this.arrayOperation(src, -1, 
					dest, 0, 4);
				break;
			
			case 8:
				this.arrayOperation(src, 0, 
					dest, -1, 4);
				break;
			
			default:
				return true;
		}
		
		return false;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/__BaseMleErrorTest__.java.



















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.mle.errors;

import cc.squirreljme.jvm.mle.exceptions.MLECallError;
import net.multiphasicapps.tac.TestInteger;

/**
 * Base class for MLE error testing, to make sure that invalid inputs are
 * properly blocked.
 *
 * @since 2020/06/22
 */
abstract class __BaseMleErrorTest__
	extends TestInteger
{
	/**
	 * Performs the test by index.
	 * 
	 * @param __index The index.
	 * @return If testing should stop.
	 * @throws MLECallError This should be thrown.
	 * @since 2020/06/22
	 */
	public abstract boolean test(int __index)
		throws MLECallError;
	
	/**
	 * {@inheritDoc}
	 * @since 2020/06/22
	 */
	@Override
	public final int test()
	{
		// Call sub-test methods and make sure they fail
		int callCount = 0;
		int errorCount = 0;
		for (int i = 0;; i++)
		{
			// Perform the call
			try
			{
				callCount++;
				
				// Run the test and stop if this is the end
				if (this.test(i))
				{
					callCount--;
					break;
				}
				
				// Send invalid secondary to flag that something is wrong
				this.secondary("not-thrown-" + i, i);
			}
			
			// Caught exception that we want
			catch (MLECallError ignored)
			{
				errorCount++;
			}
		}
		
		// Report the count
		return errorCount;
	}
}

Added modules/cldc-compact/src/test/java/squirreljme/mle/errors/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * Contains tests to determine if MLEs are correctly erroring.
 *
 * @since 2020/06/22
 */

package squirreljme.mle.errors;

Added modules/cldc-compact/src/test/java/squirreljme/mle/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * Middle layer tests.
 *
 * @since 2020/06/22
 */

package squirreljme.mle;

Name change from modules/cldc-compact/src/test/java/squirreljme/TestErrorGetSet.java to modules/cldc-compact/src/test/java/squirreljme/summercoat/TestErrorGetSet.java.

1
2
3
4
5
6
7
8
package squirreljme;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import net.multiphasicapps.tac.TestRunnable;

/**
 * Tests that error getting and setting works properly.
|







1
2
3
4
5
6
7
8
package squirreljme.summercoat;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import net.multiphasicapps.tac.TestRunnable;

/**
 * Tests that error getting and setting works properly.

Name change from modules/cldc-compact/src/test/java/squirreljme/TestPointerAccess.java to modules/cldc-compact/src/test/java/squirreljme/summercoat/TestPointerAccess.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme;

import cc.squirreljme.jvm.Assembly;
import net.multiphasicapps.tac.TestRunnable;

/**
 * This tests that pointer access makes sense.
 *









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.summercoat;

import cc.squirreljme.jvm.Assembly;
import net.multiphasicapps.tac.TestRunnable;

/**
 * This tests that pointer access makes sense.
 *

Name change from modules/cldc-compact/src/test/java/squirreljme/TestSystemTime.java to modules/cldc-compact/src/test/java/squirreljme/summercoat/TestSystemTime.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import net.multiphasicapps.tac.TestRunnable;

/**
 * This tests that the system time can be obtained without error.









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package squirreljme.summercoat;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.SystemCallIndex;
import net.multiphasicapps.tac.TestRunnable;

/**
 * This tests that the system time can be obtained without error.

Added modules/cldc-compact/src/test/java/squirreljme/summercoat/package-info.java.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

/**
 * This package contains SummerCoat Tests.
 *
 * @since 2020/06/16
 */

package squirreljme.summercoat;

Changes to modules/cldc-compact/src/test/java/util/TestArrayDequeDeque.java.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ---------------------------------------------------------------------------

package util;

import java.util.ArrayDeque;

/**
 * Tests array deques.
 *
 * @since 2019/01/20
 */
public class TestArrayDequeDeque
	extends __TestDeque__
{
	/**
	 * Initializes the test.
	 *
	 * @since 2019/01/20
	 */
	public TestArrayDequeDeque()
	{
		super(new ArrayDeque<Number>(), false);
	}
}







|













|


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ---------------------------------------------------------------------------

package util;

import java.util.ArrayDeque;

/**
 * Tests {@link ArrayDeque}.
 *
 * @since 2019/01/20
 */
public class TestArrayDequeDeque
	extends __TestDeque__
{
	/**
	 * Initializes the test.
	 *
	 * @since 2019/01/20
	 */
	public TestArrayDequeDeque()
	{
		super(new ArrayDeque<Integer>(), false);
	}
}

Changes to modules/cldc-compact/src/test/java/util/TestLinkedListDeque.java.

23
24
25
26
27
28
29
30
31
32
33
	/**
	 * Initializes the test.
	 *
	 * @since 2019/01/20
	 */
	public TestLinkedListDeque()
	{
		super(new LinkedList<Number>(), true);
	}
}








|



23
24
25
26
27
28
29
30
31
32
33
	/**
	 * Initializes the test.
	 *
	 * @since 2019/01/20
	 */
	public TestLinkedListDeque()
	{
		super(new LinkedList<Integer>(), true);
	}
}

Changes to modules/cldc-compact/src/test/java/util/__TestDeque__.java.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package util;

import java.util.Deque;
import java.util.Iterator;

import net.multiphasicapps.tac.TestRunnable;

/**
 * Performs tests on deques.
 *
 * @since 2019/01/20
 */
abstract class __TestDeque__
	extends TestRunnable
{
	/** The deque to test. */
	protected final Deque<Number> deque;
	
	/** Can we hash code? */
	private final boolean _canHashCode;
	
	/**
	 * Initializes the base test.
	 *
	 * @param __d The deque to test on.
	 * @since 2019/01/20
	 */
	public __TestDeque__(Deque<Number> __d, boolean __canHash)
	{
		this.deque = __d;
		this._canHashCode = __canHash;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/01/20
	 */
	@Override
	public void test()
	{
		Deque<Number> q = this.deque;
		
		// Add a bunch of numbers
		for (int i = 0; i < 10; i++)
			this.secondary("init-add-" + i, q.add(i));
		
		// Offer first values
		q.addFirst(100);







>



|







|










|












|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package util;

import java.util.Deque;
import java.util.Iterator;
import java.util.NoSuchElementException;
import net.multiphasicapps.tac.TestRunnable;

/**
 * Performs tests on deque.
 *
 * @since 2019/01/20
 */
abstract class __TestDeque__
	extends TestRunnable
{
	/** The deque to test. */
	protected final Deque<Integer> deque;
	
	/** Can we hash code? */
	private final boolean _canHashCode;
	
	/**
	 * Initializes the base test.
	 *
	 * @param __d The deque to test on.
	 * @since 2019/01/20
	 */
	public __TestDeque__(Deque<Integer> __d, boolean __canHash)
	{
		this.deque = __d;
		this._canHashCode = __canHash;
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/01/20
	 */
	@Override
	public void test()
	{
		Deque<Integer> q = this.deque;
		
		// Add a bunch of numbers
		for (int i = 0; i < 10; i++)
			this.secondary("init-add-" + i, q.add(i));
		
		// Offer first values
		q.addFirst(100);
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
		
		// Size of this
		int size;
		this.secondary("size-b", (size = q.size()));
		
		// Get iterators from both positions
		int[] ita = new int[size];
		Iterator<Number> it = q.iterator();
		for (int i = 0; it.hasNext(); i++)
			ita[i] = it.next().intValue();
		this.secondary("iterator-ascending", ita);
		
		// And descend it
		it = q.descendingIterator();
		for (int i = 0; it.hasNext(); i++)







|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
		
		// Size of this
		int size;
		this.secondary("size-b", (size = q.size()));
		
		// Get iterators from both positions
		int[] ita = new int[size];
		Iterator<Integer> it = q.iterator();
		for (int i = 0; it.hasNext(); i++)
			ita[i] = it.next().intValue();
		this.secondary("iterator-ascending", ita);
		
		// And descend it
		it = q.descendingIterator();
		for (int i = 0; it.hasNext(); i++)
138
139
140
141
142
143
144
145















146


147
















































		for (int i = 1; i < 15; i += 2)
			this.secondary("remove-last-" + i, q.removeLastOccurrence(i));
		this.secondary("array5", q.<Integer>toArray(new Integer[q.size()]));
		
		// Clear it
		q.clear();
		this.secondary("array6", q.<Integer>toArray(new Integer[q.size()]));
	}















}


























































|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
		for (int i = 1; i < 15; i += 2)
			this.secondary("remove-last-" + i, q.removeLastOccurrence(i));
		this.secondary("array5", q.<Integer>toArray(new Integer[q.size()]));
		
		// Clear it
		q.clear();
		this.secondary("array6", q.<Integer>toArray(new Integer[q.size()]));
		
		// Various attempts to add null elements
__outer:
		for (int i = 0;; i++)
		{
			try
			{
				switch (i)
				{
					case 0: q.add(null); break;
					case 1: q.addFirst(null); break;
					case 2: q.addLast(null); break;
					case 3: q.offer(null); break;
					case 4: q.offerFirst(null); break;
					case 5: q.offerLast(null); break;
					case 6: q.push(null); break;
					
					default:
						break __outer;
				}
				
				// Succeeded
				this.secondary("null-add-" + i, false);
			}
			
			// Not found
			catch (NullPointerException e)
			{
				this.secondary("null-add-" + i, true);
			}
		}
		
		// Clear the queue out
		q.clear();
		
		// Various attempts to remove from an empty queue
__outer:
		for (int i = 0;; i++)
		{
			try
			{
				switch (i)
				{
					case 0: q.remove(); break;
					case 1: q.removeFirst(); break;
					case 2: q.removeLast(); break;
					case 3: q.poll(); break;
					case 4: q.pollFirst(); break;
					case 5: q.pollLast(); break;
					case 6: q.pop(); break;
					
					default:
						break __outer;
				}
				
				// Succeeded
				this.secondary("empty-remove-" + i, false);
			}
			
			// Not found
			catch (NoSuchElementException e)
			{
				this.secondary("empty-remove-" + i, true);
			}
		}
	}
}

Changes to modules/cldc-compact/src/test/resources/lang/TestMonitorNotify.in.

1
2
3
4
5
6
7
8
9
10

11
result: NoResult
thrown: NoExceptionThrown
secondary-after--lock: int:7
secondary-before--lock: int:0
secondary-expected--resume: int:6
secondary-in--lock: int:1
secondary-sub--after--notify: int:4
secondary-sub--after--sleep: int:5
secondary-sub--in--lock: int:3
secondary-thread--created: int:2












>

1
2
3
4
5
6
7
8
9
10
11
12
result: NoResult
thrown: NoExceptionThrown
secondary-after--lock: int:7
secondary-before--lock: int:0
secondary-expected--resume: int:6
secondary-in--lock: int:1
secondary-sub--after--notify: int:4
secondary-sub--after--sleep: int:5
secondary-sub--in--lock: int:3
secondary-thread--created: int:2
secondary-sub--started: true

Name change from modules/cldc-compact/src/test/resources/squirreljme/TestArrayLength.in to modules/cldc-compact/src/test/resources/squirreljme/mle/TestArrayLength.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
result: NoResult
thrown: NoExceptionThrown
secondary-o: int:-1
secondary-op: int:-1
secondary-z: int:1
secondary-b: int:2
secondary-s: int:3
secondary-c: int:4
secondary-i: int:5
secondary-j: int:6
secondary-f: int:7
secondary-d: int:8
secondary-l: int:9
secondary-zp: int:1
secondary-bp: int:2
secondary-sp: int:3
secondary-cp: int:4
secondary-ip: int:5
secondary-jp: int:6
secondary-fp: int:7
secondary-dp: int:8
secondary-lp: int:9



<









<
<
<
<
<
<
<
<
<
1
2
3

4
5
6
7
8
9
10
11
12









result: NoResult
thrown: NoExceptionThrown
secondary-o: int:-1

secondary-z: int:1
secondary-b: int:2
secondary-s: int:3
secondary-c: int:4
secondary-i: int:5
secondary-j: int:6
secondary-f: int:7
secondary-d: int:8
secondary-l: int:9









Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestAtomicShelfInvalid.in.



>
1
result: int:2

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestDebugShelfInvalid.in.



>
1
result: int:9

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestJarPackageShelfInvalid.in.



>
1
result: int:3

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestObjectShelfInvalid.in.



>
1
result: int:12

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestReferenceShelfInvalid.in.



>
1
result: int:12

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestRuntimeShelfInvalid.in.



>
1
result: int:5

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestTerminalShelfInvalid.in.



>
1
result: int:9

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestThreadShelfInvalid.in.



>
1
result: int:18

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/TestTypeShelfInvalid.in.



>
1
result: int:18

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/__BaseArrayInvalidTest__.in.



>
1
result: int:9

Added modules/cldc-compact/src/test/resources/squirreljme/mle/errors/__BaseMleErrorTest__.in.





>
>
1
2
thrown: NoExceptionThrown
only-in: anycoat

Name change from modules/cldc-compact/src/test/resources/squirreljme/TestErrorGetSet.in to modules/cldc-compact/src/test/resources/squirreljme/summercoat/TestErrorGetSet.in.

1
2

3
4
result: NoResult
thrown: NoExceptionThrown

secondary-sameasorig: true
secondary-isset: true


>


1
2
3
4
5
result: NoResult
thrown: NoExceptionThrown
only-in: summercoat
secondary-sameasorig: true
secondary-isset: true

Name change from modules/cldc-compact/src/test/resources/squirreljme/TestPointerAccess.in to modules/cldc-compact/src/test/resources/squirreljme/summercoat/TestPointerAccess.in.

1
2

3
4
5
6
result: NoResult
thrown: NoExceptionThrown

secondary-otpnotnull: true
secondary-sameobject: true
secondary-zeroisnull: true
secondary-nulliszero: true


>




1
2
3
4
5
6
7
result: NoResult
thrown: NoExceptionThrown
only-in: summercoat
secondary-otpnotnull: true
secondary-sameobject: true
secondary-zeroisnull: true
secondary-nulliszero: true

Name change from modules/cldc-compact/src/test/resources/squirreljme/TestSystemTime.in to modules/cldc-compact/src/test/resources/squirreljme/summercoat/TestSystemTime.in.

1
2

3
4
result: NoResult
thrown: NoExceptionThrown

secondary-mw: int:0
secondary-nm: int:0


>


1
2
3
4
5
result: NoResult
thrown: NoExceptionThrown
only-in: summercoat
secondary-mw: int:0
secondary-nm: int:0

Changes to modules/cldc-compact/src/test/resources/util/TestArrayDequeDeque.in.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
secondary-null--add--0: true
secondary-null--add--1: true
secondary-null--add--2: true
secondary-null--add--3: true
secondary-null--add--4: true
secondary-null--add--5: true
secondary-null--add--6: true

Changes to modules/cldc-compact/src/test/resources/util/TestLinkedListDeque.in.

1







secondary-hashcode: int:1315173338








>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
secondary-hashcode: int:1315173338
secondary-null--add--0: false
secondary-null--add--1: false
secondary-null--add--2: false
secondary-null--add--3: false
secondary-null--add--4: false
secondary-null--add--5: false
secondary-null--add--6: false

Changes to modules/cldc-compact/src/test/resources/util/__TestDeque__.in.

65
66
67
68
69
70
71







secondary-array4: int[15]:3,5,7,9,300,400,1,2,3,4,5,6,7,8,9
secondary-array5: int[10]:3,5,7,9,300,400,2,4,6,8
secondary-array6: int[0]:
secondary-arrayover: int[34]:1234,200,100,0,1,2,3,4,5,6,7,8,
 9,300,400,500,600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
secondary-arraygrow: int[17]:1234,200,100,0,1,2,3,4,5,6,7,8,
 9,300,400,500,600














>
>
>
>
>
>
>
65
66
67
68
69
70
71
72
73
74
75
76
77
78
secondary-array4: int[15]:3,5,7,9,300,400,1,2,3,4,5,6,7,8,9
secondary-array5: int[10]:3,5,7,9,300,400,2,4,6,8
secondary-array6: int[0]:
secondary-arrayover: int[34]:1234,200,100,0,1,2,3,4,5,6,7,8,
 9,300,400,500,600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
secondary-arraygrow: int[17]:1234,200,100,0,1,2,3,4,5,6,7,8,
 9,300,400,500,600
secondary-empty--remove--0: true
secondary-empty--remove--1: true
secondary-empty--remove--2: true
secondary-empty--remove--3: false
secondary-empty--remove--4: false
secondary-empty--remove--5: false
secondary-empty--remove--6: true

Changes to modules/collections/src/main/java/net/multiphasicapps/collections/MultiSetDeque.java.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
 */
public class MultiSetDeque<V>
{
	/** Sub-queue list. */
	private final List<__Sub__<V>> _subs =
		new ArrayList<>();
	
	/** The master set of added elements. */
	final Set<V> _master =
		new HashSet<>();
	
	/**
	 * Clears the multi-set deque and every sub-deque so that all are empty.
	 *
	 * @since 2017/03/25
	 */
	public final void clear()
	{
		// Clear the master set
		this._master.clear();
		
		// And all the subsets
		for (__Sub__<V> s : this._subs)
			s.__clear();
	}
	
	/**
	 * Checks if the any of the sub-deques contain the specified element.
	 *
	 * @param __v The element to check.
	 * @return {@code true} if the element is any in deque.
	 * @since 2017/04/25
	 */
	public final boolean contains(V __v)
	{
		return this._master.contains(__v);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2017/03/25
	 */
	@Override







|
|









|
|















|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
 */
public class MultiSetDeque<V>
{
	/** Sub-queue list. */
	private final List<__Sub__<V>> _subs =
		new ArrayList<>();
	
	/** The global set of added elements. */
	final Set<V> _global =
		new HashSet<>();
	
	/**
	 * Clears the multi-set deque and every sub-deque so that all are empty.
	 *
	 * @since 2017/03/25
	 */
	public final void clear()
	{
		// Clear the global set
		this._global.clear();
		
		// And all the subsets
		for (__Sub__<V> s : this._subs)
			s.__clear();
	}
	
	/**
	 * Checks if the any of the sub-deques contain the specified element.
	 *
	 * @param __v The element to check.
	 * @return {@code true} if the element is any in deque.
	 * @since 2017/04/25
	 */
	public final boolean contains(V __v)
	{
		return this._global.contains(__v);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2017/03/25
	 */
	@Override
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
	 */
	public final boolean remove(V __v)
	{
		// Null will never be in this deque
		if (__v == null)
			return false;
		
		// If not in the master set then it will not be in any deque
		Set<V> master = this._master;
		if (!master.contains(__v))
			return false;
		
		// Remove in all
		List<__Sub__<V>> subs = this._subs;
		int n = subs.size();
		boolean rv = false;
		for (int i = 0; i < n; i++)
			rv |= subs.get(i).__remove(__v);
		
		// Remove from the master set because it will be no sub-deque
		master.remove(__v);
		
		// Was it removed?
		return rv;
	}
	
	/**
	 * Returns a new sub-{@link Deque} which acts as part of the multi-deque.







|
|
|









|
|







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
	 */
	public final boolean remove(V __v)
	{
		// Null will never be in this deque
		if (__v == null)
			return false;
		
		// If not in the global set then it will not be in any deque
		Set<V> global = this._global;
		if (!global.contains(__v))
			return false;
		
		// Remove in all
		List<__Sub__<V>> subs = this._subs;
		int n = subs.size();
		boolean rv = false;
		for (int i = 0; i < n; i++)
			rv |= subs.get(i).__remove(__v);
		
		// Remove from the global set because it will be no sub-deque
		global.remove(__v);
		
		// Was it removed?
		return rv;
	}
	
	/**
	 * Returns a new sub-{@link Deque} which acts as part of the multi-deque.

Changes to modules/collections/src/main/java/net/multiphasicapps/collections/__Sub__.java.

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
		Set<V> set = this._set;
		if (set.contains(__a))
			return;
		
		// Otherwise add it
		deque.add(__a);
		set.add(__a);
		this._msd._master.add(__a);
	}

	/**
	 * {@inheritDoc}
	 * @since 2016/09/03
	 */
	@Override







|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
		Set<V> set = this._set;
		if (set.contains(__a))
			return;
		
		// Otherwise add it
		deque.add(__a);
		set.add(__a);
		this._msd._global.add(__a);
	}

	/**
	 * {@inheritDoc}
	 * @since 2016/09/03
	 */
	@Override

Changes to modules/demo-hello/src/main/java/net/multiphasicapps/demo/hello/Hello.java.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
		{
			"java.version",
			"java.vendor",
			"java.vendor.email",
			"java.vendor.url",
			"java.vm.name",
			"java.vm.version",
			"cc.squirreljme.apilevel",
			"java.vm.vendor",
			"java.vm.vendor.email",
			"java.vm.vendor.url",
			"java.runtime.name",
			"java.runtime.version",
			"os.name",
			"os.arch",







<







25
26
27
28
29
30
31

32
33
34
35
36
37
38
		{
			"java.version",
			"java.vendor",
			"java.vendor.email",
			"java.vendor.url",
			"java.vm.name",
			"java.vm.version",

			"java.vm.vendor",
			"java.vm.vendor.email",
			"java.vm.vendor.url",
			"java.runtime.name",
			"java.runtime.version",
			"os.name",
			"os.arch",
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	
	/**
	 * Main entry point.
	 *
	 * @param __args Program arguments.
	 * @since 2018/09/22
	 */
	public static final void main(String... __args)
	{
		PrintStream out = System.out;
		
		// Print input message if used
		int an;
		if (__args != null && (an = __args.length) > 0)
		{







|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	
	/**
	 * Main entry point.
	 *
	 * @param __args Program arguments.
	 * @since 2018/09/22
	 */
	public static void main(String... __args)
	{
		PrintStream out = System.out;
		
		// Print input message if used
		int an;
		if (__args != null && (an = __args.length) > 0)
		{

Changes to modules/meep-midlet/src/main/java/javax/microedition/midlet/MIDlet.java.

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
		
			// Cache it?
			if (ref == null || (null == (manifest = ref.get())))
			{
				// Some application properties are inside of the manifest so
				// check that
				InputStream is = this.getClass().getResourceAsStream(
					"META-INF/MANIFEST.MF");
				try
				{
					// Not found, force failure
					if (is == null)
						throw new IOException();
					
					// Load it







|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
		
			// Cache it?
			if (ref == null || (null == (manifest = ref.get())))
			{
				// Some application properties are inside of the manifest so
				// check that
				InputStream is = this.getClass().getResourceAsStream(
					"/META-INF/MANIFEST.MF");
				try
				{
					// Not found, force failure
					if (is == null)
						throw new IOException();
					
					// Load it

Changes to modules/meep-midlet/src/main/java/javax/microedition/midlet/__MainHandler__.java.

1
2
3
4
5
6
7
8
9
10
11

12

13
14
15

16
17
18
19
20




21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37



38
39
40
41
42
43
44
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package javax.microedition.midlet;


import cc.squirreljme.runtime.cldc.Poking;


/**
 * This class

 *
 * @since 2020/02/29
 */
final class __MainHandler__
{




	/**
	 * Main entry point.
	 *
	 * @param __args Program arguments.
	 * @throws Throwable On any exception.
	 * @since 2020/02/29
	 */
	public static void main(String... __args)
		throws Throwable
	{
		// {@squirreljme.error AD02 No main MIDlet class specified.}
		if (__args == null || __args.length < 1 || __args[0] == null)
			throw new IllegalArgumentException("AD02");
		
		// We might be on the emulator
		Poking.poke();
		



		// Locate the main class before we initialize it
		Class<?> classType;
		try
		{
			classType = Class.forName(__args[0]);
		}
		catch (ClassNotFoundException e)











>

>


|
>





>
>
>
>

















>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package javax.microedition.midlet;

import cc.squirreljme.jvm.mle.ThreadShelf;
import cc.squirreljme.runtime.cldc.Poking;
import cc.squirreljme.runtime.cldc.debug.Debugging;

/**
 * This class is the main entry point for anything that implements
 * {@link MIDlet}.
 *
 * @since 2020/02/29
 */
final class __MainHandler__
{
	/** One second in milliseconds. */
	private static final int _MS_SECOND =
		1_000;
	
	/**
	 * Main entry point.
	 *
	 * @param __args Program arguments.
	 * @throws Throwable On any exception.
	 * @since 2020/02/29
	 */
	public static void main(String... __args)
		throws Throwable
	{
		// {@squirreljme.error AD02 No main MIDlet class specified.}
		if (__args == null || __args.length < 1 || __args[0] == null)
			throw new IllegalArgumentException("AD02");
		
		// We might be on the emulator
		Poking.poke();
		
		// Debug where we are going in
		Debugging.debugNote("Entering MIDlet: %s", __args[0]);
		
		// Locate the main class before we initialize it
		Class<?> classType;
		try
		{
			classType = Class.forName(__args[0]);
		}
		catch (ClassNotFoundException e)
72
73
74
75
76
77
78

79









80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97
98
			// {@squirreljme.error AD04 Could not instantiate class.}
			throw new RuntimeException("AD04", e);
		}
		
		// Start the MIDlet and perform any potential handling of it
		try
		{

			instance.startApp();









		}
		finally
		{
			// Always try to destroy the MIDlet
			try
			{
				instance.destroyApp(true);
			}

			catch (MIDletStateChangeException e)
			{
				// Ignore, but still print a trace
				e.printStackTrace(System.err);
			}
			
			// Application is gone now, exit
			instance.notifyDestroyed();
		}
	}
}







>

>
>
>
>
>
>
>
>
>








>
|










82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
			// {@squirreljme.error AD04 Could not instantiate class.}
			throw new RuntimeException("AD04", e);
		}
		
		// Start the MIDlet and perform any potential handling of it
		try
		{
			// Initialize the MIDlet
			instance.startApp();
			
			// Although we did start the application, the startApp only
			// ever does initialization and sets some events and otherwise...
			// So actually stop when the alive count goes to zero
			// If the application did start graphics, then there will be
			// a graphics thread.
			while (ThreadShelf.aliveThreadCount(
				false, false) > 0)
				ThreadShelf.waitForUpdate(__MainHandler__._MS_SECOND);
		}
		finally
		{
			// Always try to destroy the MIDlet
			try
			{
				instance.destroyApp(true);
			}
			catch (@SuppressWarnings("deprecation")
				MIDletStateChangeException e)
			{
				// Ignore, but still print a trace
				e.printStackTrace(System.err);
			}
			
			// Application is gone now, exit
			instance.notifyDestroyed();
		}
	}
}

Changes to modules/meep-rms/src/main/java/cc/squirreljme/runtime/rms/SuiteIdentifier.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.rms;

import cc.squirreljme.runtime.cldc.lang.ApiLevel;
import cc.squirreljme.runtime.midlet.ActiveMidlet;
import javax.microedition.midlet.MIDlet;
import javax.microedition.swm.ManagerFactory;
import javax.microedition.swm.Suite;
import javax.microedition.swm.Task;
import javax.microedition.swm.TaskManager;

/**
 * This is used to help identify suites and such.
 *
 * @since 2019/04/14
 */
public final class SuiteIdentifier











|


<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14




15
16
17
18
19
20
21
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.rms;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.midlet.ActiveMidlet;
import javax.microedition.midlet.MIDlet;





/**
 * This is used to help identify suites and such.
 *
 * @since 2019/04/14
 */
public final class SuiteIdentifier
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
	 */
	public static String currentName()
	{
		String rv = SuiteIdentifier._CURRENT_NAME;
		if (rv != null)
			return rv;
		
		// Use task manager
		if (ApiLevel.minimumLevel(ApiLevel.UNDEFINED))
		{
			// Need to obtain the current suite
			TaskManager tm = ManagerFactory.getTaskManager();
			Task ct = tm.getCurrentTask();
			Suite su = ct.getSuite();
			
			// Get
			rv = su.getName();
		}
		
		// Try through the current MIDlet properties
		if (rv == null)
		{
			MIDlet mid = ActiveMidlet.optional();
			if (mid != null)
				rv = mid.getAppProperty("MIDlet-Name");







<
<
<
|
<
<
<
|
<
<
<







65
66
67
68
69
70
71



72



73



74
75
76
77
78
79
80
	 */
	public static String currentName()
	{
		String rv = SuiteIdentifier._CURRENT_NAME;
		if (rv != null)
			return rv;
		



		// TODO: Better means of getting the current name



		Debugging.todoNote("Better means of currentName()");



		
		// Try through the current MIDlet properties
		if (rv == null)
		{
			MIDlet mid = ActiveMidlet.optional();
			if (mid != null)
				rv = mid.getAppProperty("MIDlet-Name");
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
	 */
	public static String currentVendor()
	{
		String rv = SuiteIdentifier._CURRENT_VENDOR;
		if (rv != null)
			return rv;
		
		// Use task manager
		if (ApiLevel.minimumLevel(ApiLevel.UNDEFINED))
		{
			// Need to obtain the current suite
			TaskManager tm = ManagerFactory.getTaskManager();
			Task ct = tm.getCurrentTask();
			Suite su = ct.getSuite();
			
			// Get
			rv = su.getVendor();
		}
		
		// Try through the current MIDlet properties
		if (rv == null)
		{
			MIDlet mid = ActiveMidlet.optional();
			if (mid != null)
				rv = mid.getAppProperty("MIDlet-Vendor");







<
<
<
|
<
<
<
|
<
<
<







97
98
99
100
101
102
103



104



105



106
107
108
109
110
111
112
	 */
	public static String currentVendor()
	{
		String rv = SuiteIdentifier._CURRENT_VENDOR;
		if (rv != null)
			return rv;
		



		// TODO: Better means of getting the current name



		Debugging.todoNote("Better means of currentVendor()");



		
		// Try through the current MIDlet properties
		if (rv == null)
		{
			MIDlet mid = ActiveMidlet.optional();
			if (mid != null)
				rv = mid.getAppProperty("MIDlet-Vendor");

Changes to modules/midp-lcdui/src/main/java/cc/squirreljme/runtime/lcdui/fbui/UIState.java.

10
11
12
13
14
15
16



17
18
19
20
21
22
23
package cc.squirreljme.runtime.lcdui.fbui;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.Framebuffer;
import cc.squirreljme.jvm.IPCCallback;
import cc.squirreljme.jvm.IPCManager;
import cc.squirreljme.jvm.SystemCallIndex;



import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;

/**
 * This class contains the state of the user interface. It may call the native







>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package cc.squirreljme.runtime.lcdui.fbui;

import cc.squirreljme.jvm.Assembly;
import cc.squirreljme.jvm.Framebuffer;
import cc.squirreljme.jvm.IPCCallback;
import cc.squirreljme.jvm.IPCManager;
import cc.squirreljme.jvm.SystemCallIndex;
import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.VMType;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;

/**
 * This class contains the state of the user interface. It may call the native
55
56
57
58
59
60
61






62
63
64
65
66
67
68
	/**
	 * Only internally initialized.
	 *
	 * @since 2020/01/12
	 */
	private UIState()
	{






		// Get display format
		this.format = (byte)Assembly.sysCallV(SystemCallIndex.FRAMEBUFFER,
			Framebuffer.CONTROL_FORMAT);
		
		// Get display capabilities
		int capabilities = Assembly.sysCallV(SystemCallIndex.FRAMEBUFFER,
			Framebuffer.CONTROL_GET_CAPABILITIES);







>
>
>
>
>
>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
	/**
	 * Only internally initialized.
	 *
	 * @since 2020/01/12
	 */
	private UIState()
	{
		// This will be forwarded at a later date when SpringCoat is more
		// stable
		Debugging.todoNote("Fixup UIState init on non-SummerCoat");
		if (VMType.SUMMERCOAT != RuntimeShelf.vmType())
			throw new IllegalArgumentException("SMCT");
		
		// Get display format
		this.format = (byte)Assembly.sysCallV(SystemCallIndex.FRAMEBUFFER,
			Framebuffer.CONTROL_FORMAT);
		
		// Get display capabilities
		int capabilities = Assembly.sysCallV(SystemCallIndex.FRAMEBUFFER,
			Framebuffer.CONTROL_GET_CAPABILITIES);

Name change from modules/midp-lcdui/src/test/java/display/TestDisplayInitialize.java to modules/midp-lcdui/src/test/java/TestDisplayInitialize.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package display;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import net.multiphasicapps.tac.TestRunnable;

/**
 * Not Described
 *
 * @since 2020/02/29
 */
public class TestDisplayInitialize
	extends TestRunnable
{
	/**
	 * {@inheritDoc}
	 * @since 2020/02/29
	 */
	@Override
	public void test()
	{
		Display display = Display.getDisplays(0)[0];
		
		display.setCurrent(new __BlankCanvas__());
	}
	
	/**
	 * Blank canvas, needed because the display appears when a displayable is
	 * added.









<
<




















|







1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------



import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import net.multiphasicapps.tac.TestRunnable;

/**
 * Not Described
 *
 * @since 2020/02/29
 */
public class TestDisplayInitialize
	extends TestRunnable
{
	/**
	 * {@inheritDoc}
	 * @since 2020/02/29
	 */
	@Override
	public void test()
	{
		Display display = __Utils__.getDisplay();
		
		display.setCurrent(new __BlankCanvas__());
	}
	
	/**
	 * Blank canvas, needed because the display appears when a displayable is
	 * added.

Changes to modules/midp-lcdui/src/test/java/__Utils__.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34




35
36
37
38
39
40
41
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

import javax.microedition.lcdui.Display;
import net.multiphasicapps.tac.InvalidTestException;
import net.multiphasicapps.tac.UntestableException;

/**
 * Utilities for the LCDUI tests.
 *
 * @since 2019/03/04
 */
final class __Utils__
{
	/**
	 * Attempts to obtain the display, otherwise the test cannot be ran.
	 *
	 * @return The display to use.
	 * @throws InvalidTestException If the display could not be obtained.
	 * @since 2019/03/04
	 */
	public static final Display getDisplay()
		throws InvalidTestException
	{
		try
		{
			return Display.getDisplays(0)[0];




		}
		
		// No display possible?
		catch (Throwable e)
		{
			throw new UntestableException(e);
		}











<













|



|



|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

import javax.microedition.lcdui.Display;

import net.multiphasicapps.tac.UntestableException;

/**
 * Utilities for the LCDUI tests.
 *
 * @since 2019/03/04
 */
final class __Utils__
{
	/**
	 * Attempts to obtain the display, otherwise the test cannot be ran.
	 *
	 * @return The display to use.
	 * @throws UntestableException If the display could not be obtained.
	 * @since 2019/03/04
	 */
	public static final Display getDisplay()
		throws UntestableException
	{
		try
		{
			Display rv = Display.getDisplays(0)[0];
			
			rv.getCapabilities();
			
			return rv;
		}
		
		// No display possible?
		catch (Throwable e)
		{
			throw new UntestableException(e);
		}

Name change from modules/midp-lcdui/src/test/resources/display/TestDisplayInitialize.in to modules/midp-lcdui/src/test/resources/TestDisplayInitialize.in.

Changes to modules/tac/build.gradle.

20
21
22
23
24
25
26

27
28
29
30
31
32
33
	main
	{
		java
		{
			exclude "org/testng/internal/annotations/DisabledRetryAnalyzer.java"
			exclude "org/testng/annotations/CustomAttribute.java"
			exclude "org/testng/annotations/Test.java"

		}
	}
}

dependencies
{
	// We have some annotations we need the source for, but we do not want







>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
	main
	{
		java
		{
			exclude "org/testng/internal/annotations/DisabledRetryAnalyzer.java"
			exclude "org/testng/annotations/CustomAttribute.java"
			exclude "org/testng/annotations/Test.java"
			exclude "org/testng/SkipException.java"
		}
	}
}

dependencies
{
	// We have some annotations we need the source for, but we do not want
45
46
47
48
49
50
51

52
jar
{
	// These are excluded because they are not needed by the source and are
	// part of TestNG
	exclude("org/testng/internal/annotations/DisabledRetryAnalyzer.class")
	exclude("org/testng/annotations/CustomAttribute.class")
	exclude("org/testng/annotations/Test.class")

}







>

46
47
48
49
50
51
52
53
54
jar
{
	// These are excluded because they are not needed by the source and are
	// part of TestNG
	exclude("org/testng/internal/annotations/DisabledRetryAnalyzer.class")
	exclude("org/testng/annotations/CustomAttribute.class")
	exclude("org/testng/annotations/Test.class")
	exclude("org/testng/SkipException.class")
}

Changes to modules/tac/src/main/java/net/multiphasicapps/tac/MainSingleRunner.java.

70
71
72
73
74
75
76






77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
		
		// Run the class execution
		TestExecution execution = testInstance.runExecution();
		
		// Print the test execution results
		execution.print(System.err);
		






		// How do we exit?
		switch (execution.status)
		{
			case SUCCESS:
				System.exit(ExitValueConstants.SUCCESS);
				break;
				
			case FAILED:
			case TEST_EXCEPTION:
				System.exit(ExitValueConstants.FAILURE);
				break;
			
			case UNTESTABLE:

				System.exit(ExitValueConstants.SKIPPED);
				break;
		}
	}
}







>
>
>
>
>
>













>





70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
		
		// Run the class execution
		TestExecution execution = testInstance.runExecution();
		
		// Print the test execution results
		execution.print(System.err);
		
		// Print the tossed exception so that it is in the trace no matter
		// what (even on pass since it might be a false pass)
		Throwable tossed = execution.tossedAsThrowable();
		if (tossed != null)
			tossed.printStackTrace();
		
		// How do we exit?
		switch (execution.status)
		{
			case SUCCESS:
				System.exit(ExitValueConstants.SUCCESS);
				break;
				
			case FAILED:
			case TEST_EXCEPTION:
				System.exit(ExitValueConstants.FAILURE);
				break;
			
			case UNTESTABLE:
				
				System.exit(ExitValueConstants.SKIPPED);
				break;
		}
	}
}

Changes to modules/tac/src/main/java/net/multiphasicapps/tac/TestExecution.java.

125
126
127
128
129
130
131













132
			sb.append(tossed.toString());
		}
		
		sb.append("}");
		
		return sb.toString();
	}













}







>
>
>
>
>
>
>
>
>
>
>
>
>

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
			sb.append(tossed.toString());
		}
		
		sb.append("}");
		
		return sb.toString();
	}
	
	/**
	 * Returns the tossed exception as a {@link Throwable}.
	 *
	 * @return The tossed as a {@link Throwable} or {@code null} if it is not
	 * one.
	 * @since 2020/06/18
	 */
	public final Throwable tossedAsThrowable()
	{
		Object rv = this.tossed;
		return (rv instanceof Throwable ? (Throwable)rv : null);
	}
}

Changes to modules/tac/src/main/java/net/multiphasicapps/tac/TestResult.java.

102
103
104
105
106
107
108

















109
110
111
112
113
114
115
			return false;
		
		TestResult o = (TestResult)__o;
		return this.rvalue.equals(o.rvalue) &&
			this.tvalue.equals(o.tvalue) &&
			this._secondary.equals(o._secondary);
	}

















	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/08
	 */
	@Override
	public final int hashCode()







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
			return false;
		
		TestResult o = (TestResult)__o;
		return this.rvalue.equals(o.rvalue) &&
			this.tvalue.equals(o.tvalue) &&
			this._secondary.equals(o._secondary);
	}
	
	/**
	 * Gets the raw secondary value, if any.
	 *
	 * @param __key The key to get.
	 * @return The value of the key or {@code null} if it is not set.
	 * @throws NullPointerException On null arguments.
	 * @since 2020/06/16
	 */
	public final String getSecondaryRawValue(String __key)
		throws NullPointerException
	{
		if (__key == null)
			throw new NullPointerException("NARG");
		
		return this._secondary.get(__key);
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2019/05/08
	 */
	@Override
	public final int hashCode()
251
252
253
254
255
256
257


258
259
260
261
262
263

264
265
266
267
268
269
270
		man.write(__os);
	}
	
	/**
	 * Loads test results for the specified class.
	 *
	 * @param __cl The results to load.


	 * @return The results of the test.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/08
	 */
	@SuppressWarnings("FeatureEnvy")
	public static TestResult loadForClass(Class<?> __cl)

		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		// We are going to recursively go up the class chain and load values
		// from the manifest into our result







>
>





|
>







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
		man.write(__os);
	}
	
	/**
	 * Loads test results for the specified class.
	 *
	 * @param __cl The results to load.
	 * @param __otherKeys Other keys that were loaded and ignored, this is
	 * optional.
	 * @return The results of the test.
	 * @throws NullPointerException On null arguments.
	 * @since 2019/05/08
	 */
	@SuppressWarnings("FeatureEnvy")
	public static TestResult loadForClass(Class<?> __cl,
		Map<String, String> __otherKeys)
		throws NullPointerException
	{
		if (__cl == null)
			throw new NullPointerException("NARG");
		
		// We are going to recursively go up the class chain and load values
		// from the manifest into our result
322
323
324
325
326
327
328




329
330
331
332
333
334
335
						{
							String skey = DataDeserialization.decodeKey(
								ekey.substring(10));
							
							if (rv.getSecondary(skey) == null)
								rv.putSecondaryEncoded(skey, eval);
						}




						break;
				}
			}
		}
		
		// Done
		return rv.build();







>
>
>
>







342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
						{
							String skey = DataDeserialization.decodeKey(
								ekey.substring(10));
							
							if (rv.getSecondary(skey) == null)
								rv.putSecondaryEncoded(skey, eval);
						}
						
						// Another key, put into the ignored map
						else if (__otherKeys != null)
							__otherKeys.put(ekey, eval);
						break;
				}
			}
		}
		
		// Done
		return rv.build();

Changes to modules/tac/src/main/java/net/multiphasicapps/tac/TestResultBuilder.java.

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package net.multiphasicapps.tac;


import java.util.Map;
import net.multiphasicapps.collections.SortedTreeMap;

/**
 * This is used to build {@link TestResult} and is used by the code which
 * loads expected results and builds results.
 *











>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package net.multiphasicapps.tac;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.util.Map;
import net.multiphasicapps.collections.SortedTreeMap;

/**
 * This is used to build {@link TestResult} and is used by the code which
 * loads expected results and builds results.
 *
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
		Map<String, String> secondary = this._secondary;
		synchronized (this)
		{
			// Use formatted values
			secondary.put(__key.toLowerCase(), __val);
			
			// Debug
			todo.DEBUG.note("%s=%s", __key, __val);
		}
	}
	
	/**
	 * Adds a secondary test value which is a result of something, the value
	 * is always encoded to a string form.
	 *







|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
		Map<String, String> secondary = this._secondary;
		synchronized (this)
		{
			// Use formatted values
			secondary.put(__key.toLowerCase(), __val);
			
			// Debug
			Debugging.debugNote("SET %s=%s", __key, __val);
		}
	}
	
	/**
	 * Adds a secondary test value which is a result of something, the value
	 * is always encoded to a string form.
	 *

Changes to modules/tac/src/main/java/net/multiphasicapps/tac/TestStatus.java.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
	
	/** Failed due to test exception. */
	TEST_EXCEPTION,
	
	/** Test was not run yet. */
	NOT_RUN,
	
	/** Untestable. */
	UNTESTABLE,
	
	/* End. */
	;
}








|






25
26
27
28
29
30
31
32
33
34
35
36
37
38
	
	/** Failed due to test exception. */
	TEST_EXCEPTION,
	
	/** Test was not run yet. */
	NOT_RUN,
	
	/** Untestable, so this must be skipped. */
	UNTESTABLE,
	
	/* End. */
	;
}

Changes to modules/tac/src/main/java/net/multiphasicapps/tac/__CoreTest__.java.

1
2
3
4
5
6
7
8
9
10
11
12



13
14
15

16

17
18

19
20
21
22
23
24
25
26
27
28
29
30




31
32
33
34
35
36
37
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package net.multiphasicapps.tac;




import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import java.util.List;

import net.multiphasicapps.tool.manifest.JavaManifest;
import net.multiphasicapps.tool.manifest.JavaManifestAttributes;

import org.testng.annotations.Test;

/**
 * This is the core test framework which handles reading test information and
 * parameters, it forwards internally to other classes which handle
 * parameters and such.
 *
 * @since 2018/10/06
 */
abstract class __CoreTest__
	implements TestInterface
{




	/** Final result of the test, used during the test. */
	final TestResultBuilder _runResult =
		new TestResultBuilder();
	
	/**
	 * Runs the given test with the given arguments and resulting in the
	 * given result.












>
>
>



>

>


>












>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
//     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package net.multiphasicapps.tac;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.VMType;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.multiphasicapps.tool.manifest.JavaManifest;
import net.multiphasicapps.tool.manifest.JavaManifestAttributes;
import org.testng.SkipException;
import org.testng.annotations.Test;

/**
 * This is the core test framework which handles reading test information and
 * parameters, it forwards internally to other classes which handle
 * parameters and such.
 *
 * @since 2018/10/06
 */
abstract class __CoreTest__
	implements TestInterface
{
	/** Special value for any virtual machine. */
	private static final byte _ANYCOAT =
		-89;
	
	/** Final result of the test, used during the test. */
	final TestResultBuilder _runResult =
		new TestResultBuilder();
	
	/**
	 * Runs the given test with the given arguments and resulting in the
	 * given result.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
































125
126
127
128
129
130
131
132
133
134
135
136
137
		
		// Always print the result
		execution.print(System.err);
		
		// If the test did not pass, throw an exception
		if (execution.status != TestStatus.SUCCESS)
		{
			// If skippable, try throwing a TestNG skip exception if it exists
			if (execution.status == TestStatus.UNTESTABLE)
				try
				{
					Class<?> skippy = Class.forName(
						"org.testng.SkipException");
					
					// Create instance
					Object instance = skippy.newInstance();
					
					// If it is throwable, we throw it!
					if (instance instanceof RuntimeException)
					{
						RuntimeException re = (RuntimeException)instance;
						
						// So this way our information is not completely gone
						re.initCause(new ThrownTestExecution(
							execution, null));
						
						throw re;
					}
				}
				catch (ClassNotFoundException|InstantiationException|
					IllegalAccessException e)
				{
					// Ignore, treat as failure
				}
			
			Object tossed = execution.tossed;
			throw new ThrownTestExecution(execution,
				((tossed instanceof Throwable) ? (Throwable)tossed : null));
		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/02/23
	 */
	@SuppressWarnings("FeatureEnvy")
	@Override
	public final TestExecution runExecution(String... __mainargs)
	{
		// Use to name this test
		Class<?> self = this.getClass();
		
		// Decode the expected result

		TestResult expected = TestResult.loadForClass(self);
		
		// Read the inputs for the test
		Object[] args = this.__parseInput(self, __mainargs);
		
		// This is the result of the test
		TestResultBuilder runresult = this._runResult;
		
		// Our test result
		TestStatus status = null;
		
		// Run the test, catch any exception to report it
		Object thrown;
		try
		{
































			// Run the test
			runresult.setReturnValue(this.__runTest(args));
			runresult.setThrownValue((thrown = new __NoExceptionThrown__()));
		}
		
		// Cannot be tested
		catch (UntestableException e)
		{
			// Cannot be tested so it shall fail
			status = TestStatus.UNTESTABLE;
			thrown = e;
		}
		







<
<
<
<
<
<
|
<
|
|
|
<
|
<
|
<
<
<
|
|
|
<
<
<
<
<
<
|
<
|
<















>
|














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|







67
68
69
70
71
72
73






74

75
76
77

78

79



80
81
82






83

84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
		
		// Always print the result
		execution.print(System.err);
		
		// If the test did not pass, throw an exception
		if (execution.status != TestStatus.SUCCESS)
		{






			// Only use as a cause if this is even valid

			Object tossed = execution.tossed;
			Throwable tossedThrown = ((tossed instanceof Throwable) ?
				(Throwable)tossed : null);

			

			// If skippable, try throwing a TestNG skip exception if it exists



			if (execution.status == TestStatus.UNTESTABLE)
				throw new SkipException("SKIPPED", tossedThrown);
			






			// Fail otherwise

			throw new ThrownTestExecution(execution, tossedThrown);

		}
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2020/02/23
	 */
	@SuppressWarnings("FeatureEnvy")
	@Override
	public final TestExecution runExecution(String... __mainargs)
	{
		// Use to name this test
		Class<?> self = this.getClass();
		
		// Decode the expected result
		Map<String, String> otherKeys = new HashMap<>();
		TestResult expected = TestResult.loadForClass(self, otherKeys);
		
		// Read the inputs for the test
		Object[] args = this.__parseInput(self, __mainargs);
		
		// This is the result of the test
		TestResultBuilder runresult = this._runResult;
		
		// Our test result
		TestStatus status = null;
		
		// Run the test, catch any exception to report it
		Object thrown;
		try
		{
			// Determine the system that the test needs to be on, if one was
			// ever specified in the results
			int vmType = -1;
			String onlyIn = otherKeys.get("only-in");
			if (onlyIn != null)
				switch (onlyIn)
				{
					case "javase":		vmType = VMType.JAVA_SE; break;
					case "springcoat":	vmType = VMType.SPRINGCOAT; break;
					case "summercoat":	vmType = VMType.SUMMERCOAT; break;
					case "anycoat":		vmType = __CoreTest__._ANYCOAT; break;
				}
			
			// {@squirreljme.error BU0k Test is only valid on
			// AnyCoat (such as SpringCoat/SummerCoat).
			// (The requested VM type; The system VM type)}
			int systemVmType = RuntimeShelf.vmType();
			if (vmType == __CoreTest__._ANYCOAT &&
				systemVmType != VMType.SPRINGCOAT &&
				systemVmType != VMType.SUMMERCOAT)
				throw new UntestableException("BU0k " + vmType + " " +
					systemVmType);
			
			// {@squirreljme.error BU0j Test cannot run on a different VM.
			// (The requested VM type; The system VM type)}
			else if (vmType >= 0 && vmType != systemVmType)
				throw new UntestableException("BU0j " + vmType + " " +
					systemVmType);
			
			// Debug
			Debugging.debugNote("About to run test...");
			
			// Run the test
			runresult.setReturnValue(this.__runTest(args));
			runresult.setThrownValue((thrown = new __NoExceptionThrown__()));
		}
		
		// Cannot be tested at all, so must stop here
		catch (UntestableException e)
		{
			// Cannot be tested so it shall fail
			status = TestStatus.UNTESTABLE;
			thrown = e;
		}
		
154
155
156
157
158
159
160



161
162
163
164
165
166
167
			else
			{
				runresult.setReturnValue(new __ExceptionThrown__());
				runresult.setThrownValue((thrown = t));
			}
		}
		



		// If the status is not yet known, do a comparison with the results to
		// see if there is a match
		TestResult result = runresult.build();
		if (status == null)
			status = (expected.isSatisfiedBy(result) ? TestStatus.SUCCESS :
				TestStatus.FAILED);
		







>
>
>







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
			else
			{
				runresult.setReturnValue(new __ExceptionThrown__());
				runresult.setThrownValue((thrown = t));
			}
		}
		
		// Debug
		Debugging.debugNote("Finished test execution.");
		
		// If the status is not yet known, do a comparison with the results to
		// see if there is a match
		TestResult result = runresult.build();
		if (status == null)
			status = (expected.isSatisfiedBy(result) ? TestStatus.SUCCESS :
				TestStatus.FAILED);
		

Added modules/tac/src/main/java/org/testng/SkipException.java.

















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the GNU General Public License v3+, or later.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package org.testng;

/**
 * This is a virtual class for TestNG's {@code SkipException} and as such this
 * is ignored.
 *
 * @since 2020/06/16
 */
public class SkipException
	extends RuntimeException
{
	/**
	 * Initializes the exception.
	 *
	 * @param __m The message.
	 * @since 2020/06/15
	 */
	public SkipException(String __m)
	{
		super(__m);
	}
	
	/**
	 * Initializes the exception.
	 *
	 * @param __m The message.
	 * @param __c The cause.
	 * @since 2020/06/15
	 */
	public SkipException(String __m, Throwable __c)
	{
		super(__m, __c);
	}
	
	/**
	 * If this was skipped.
	 *
	 * @return Always {@code true}.
	 * @since 2020/06/16
	 */
	public boolean isSkip()
	{
		return true;
	}
	
	/**
	 * Not implemented.
	 *
	 * @since 2020/06/16
	 */
	protected void reduceStackTrace()
	{
	}
	
	/**
	 * Not implemented.
	 *
	 * @since 2020/06/16
	 */
	protected void restoreStackTrace()
	{
	}
}

Changes to modules/tool-classfile/src/main/java/net/multiphasicapps/classfile/BinaryName.java.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * This represents a binary name which consists of a class which is
 * separted internally by forwarded slashes.
 *
 * @since 2017/09/27
 */
public final class BinaryName
	implements Comparable<BinaryName>
{
	/** The identifiers in the name. */







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * This represents a binary name which consists of a class which is
 * separated internally by forwarded slashes.
 *
 * @since 2017/09/27
 */
public final class BinaryName
	implements Comparable<BinaryName>
{
	/** The identifiers in the name. */

Changes to modules/tool-classfile/src/main/java/net/multiphasicapps/classfile/ClassName.java.

300
301
302
303
304
305
306
















307
308
309
310
311
312
313
			case "long":		return PrimitiveType.LONG;
			case "float":		return PrimitiveType.FLOAT;
			case "double":		return PrimitiveType.DOUBLE;
			default:
				throw new RuntimeException("TODO");
		}
	}
















	
	/**
	 * {@inheritDoc}
	 * @since 2017/09/27
	 */
	@Override
	public String toString()







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
			case "long":		return PrimitiveType.LONG;
			case "float":		return PrimitiveType.FLOAT;
			case "double":		return PrimitiveType.DOUBLE;
			default:
				throw new RuntimeException("TODO");
		}
	}
	
	/**
	 * Returns rhe runtime string as if it were called for
	 * {@link Class#getName()}.
	 *
	 * @return The runtime string as if it were called for
	 * {@link Class#getName()}.
	 * @since 2020/06/14
	 */
	public String toRuntimeString()
	{
		BinaryName binary = this.binary;
		if (!this.isArray() && binary != null)
			return binary.toString().replace('/', '.');
		return this.toString().replace('/', '.');
	}
	
	/**
	 * {@inheritDoc}
	 * @since 2017/09/27
	 */
	@Override
	public String toString()

Changes to modules/tool-classfile/src/main/java/net/multiphasicapps/classfile/MethodNameAndType.java.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	/** The method type. */
	protected final MethodDescriptor type;
	
	/** String representation. */
	private Reference<String> _string;
	
	/**
	 * Initializes the method anme and type.
	 *
	 * @param __n The name of the method.
	 * @param __t The type of the method.
	 * @throws InvalidClassFormatException If the method name and type are not
	 * valid.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/03







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	/** The method type. */
	protected final MethodDescriptor type;
	
	/** String representation. */
	private Reference<String> _string;
	
	/**
	 * Initializes the method name and type.
	 *
	 * @param __n The name of the method.
	 * @param __t The type of the method.
	 * @throws InvalidClassFormatException If the method name and type are not
	 * valid.
	 * @throws NullPointerException On null arguments.
	 * @since 2018/09/03