mirror of
https://github.com/AppleCommander/bastools.git
synced 2024-05-28 19:41:31 +00:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
5981f65db1 | ||
|
459394d1a9 | ||
|
3d936a435c | ||
|
797224c65a | ||
|
87336e7d97 | ||
|
c55b15b505 | ||
|
5e72a68c42 | ||
|
778c094b7b | ||
|
089356a3a2 | ||
|
02269e8abb | ||
|
ca87be4733 | ||
|
848468ed21 | ||
|
f61fdbac27 | ||
|
d84d4ca1e8 | ||
|
81e1fa0ce3 | ||
|
8e8bf72618 | ||
|
baabfead2c | ||
|
d59a033550 | ||
|
013790a610 | ||
|
9f657dc531 | ||
|
06eddc96c6 | ||
|
814f199782 | ||
|
9fbbcc5b81 | ||
|
bcfa634f7b | ||
|
71f28fccc0 |
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gradle" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
44
.github/workflows/gradle.yml
vendored
Normal file
44
.github/workflows/gradle.yml
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||
|
||||
name: Build bt and st
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'temurin'
|
||||
- name: Build with Gradle
|
||||
uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0
|
||||
with:
|
||||
arguments: build
|
||||
- name: Collect artifacts
|
||||
run: |
|
||||
mkdir artifacts
|
||||
cp $(find tools/ -name "bastools-*.jar" -not -name "bastools-*-plain.jar") artifacts/
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: build-artifacts
|
||||
path: artifacts/
|
||||
if-no-files-found: error
|
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"files.exclude": {
|
||||
"**/.classpath": true,
|
||||
"**/.project": true,
|
||||
"**/.settings": true,
|
||||
"**/.factorypath": true
|
||||
}
|
||||
}
|
|
@ -8,14 +8,6 @@ Generally, the usage pattern is:
|
|||
|
||||
## Code snippets
|
||||
|
||||
```java
|
||||
Configuration config = Configuration.builder()
|
||||
.sourceFile(this.sourceFile)
|
||||
.build();
|
||||
```
|
||||
|
||||
The `Configuration` class also allows the BASIC start address to be set (defaults to `0x801`), set the maximum line length (this is in bytes, and defaults to `255`, but feel free to experiment). Some of the classes report output via the debug stream, which defaults to a simple null stream (no output) - replace with `System.out` or another `PrintStream`.
|
||||
|
||||
```java
|
||||
Queue<Token> tokens = TokenReader.tokenize(config.sourceFile);
|
||||
```
|
||||
|
@ -29,12 +21,29 @@ Program program = parser.parse();
|
|||
|
||||
The `Program` is now the parsed version of the BASIC program. Various `Visitor`s may be used to report, gather information, or manipulate the tree in various ways.
|
||||
|
||||
```java
|
||||
Configuration config = Configuration.builder()
|
||||
.sourceFile(this.sourceFile)
|
||||
.build();
|
||||
```
|
||||
|
||||
The `Configuration` class also allows the BASIC start address to be set (defaults to `0x801`), set the maximum line length (this is in bytes, and defaults to `255`, but feel free to experiment). Some of the classes report output via the debug stream, which defaults to a simple null stream (no output) - replace with `System.out` or another `PrintStream`.
|
||||
|
||||
```java
|
||||
ByteVisitor byteVisitor = Visitors.byteVisitor(config);
|
||||
byte[] programData = byteVisitor.dump(program);
|
||||
```
|
||||
|
||||
Finally, the ByteVisitor will transform the program into the tokenized form.
|
||||
|
||||
## Directives
|
||||
|
||||
The framework allows embedding of directives.
|
||||
|
||||
### `$embed`
|
||||
|
||||
> NOTE: It appears that DOS 3.3 _rewrites_ the resulting application and messes up the linked list of lines. ProDOS does not.
|
||||
|
||||
`$embed` will allow a binary to be embedded within the resulting application and can move it to a destination in memory. Please note that once the application is loaded on the Apple II, the program cannot be altered as the computer will crash.
|
||||
|
||||
Options:
|
||||
|
@ -57,7 +66,7 @@ From the `circles-timing.bas` sample, this is the beginning of the program:
|
|||
```
|
||||
0801:9A 09 00 00 8C 32 30 36 32 3A AB 31 00 A9 2B 85
|
||||
\___/ \___/ \____________/ \___/ \_______...
|
||||
Ptr, Line 0, CALL 3062, :, GOTO 1, Assembly code...
|
||||
Ptr, Line 0, CALL 2062, :, GOTO 1, Assembly code...
|
||||
```
|
||||
|
||||
The move code is based on what Beagle Bros put into their [Peeks, Pokes, and Pointers](https://beagle.applearchives.com/Posters/Poster%202.pdf) poster. (See _Memory Move_ under the *Useful Calls*; the `CALL -468` entry.)
|
||||
|
|
122
api/build.gradle
122
api/build.gradle
|
@ -1,81 +1,95 @@
|
|||
repositories {
|
||||
jcenter()
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'signing'
|
||||
}
|
||||
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'signing'
|
||||
ext.isSnapshotVersion = version.endsWith("SNAPSHOT")
|
||||
ext.isReleaseVersion = !ext.isSnapshotVersion
|
||||
|
||||
sourceCompatibility = 11
|
||||
targetCompatibility = 11
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Implementation-Title': 'B/BAS Tools API',
|
||||
'Implementation-Version': "${version} (${new Date().format('yyyy-MM-dd HH:mm')})"
|
||||
'Implementation-Version': "${project.version} (${new Date().format('yyyy-MM-dd HH:mm')})"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
javadoc {
|
||||
title = "bastools ${version}"
|
||||
source = sourceSets.main.allJava
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar) {
|
||||
classifier = 'javadoc'
|
||||
archiveClassifier = 'javadoc'
|
||||
from javadoc
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
classifier = 'sources'
|
||||
archiveClassifier = 'sources'
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives javadocJar, sourcesJar
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
from components.java
|
||||
artifact sourcesJar
|
||||
artifact javadocJar
|
||||
pom {
|
||||
groupId = "net.sf.applecommander"
|
||||
artifactId = "bastools-api"
|
||||
name = "B/BAS Tools (bastools)"
|
||||
description = 'An Applesoft BASIC tools library.'
|
||||
url = 'https://applecommander.github.io/'
|
||||
licenses {
|
||||
license {
|
||||
name = 'The GNU General Public License (GPL) Version 3, 29 June 2007'
|
||||
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'robgreene'
|
||||
name = 'Rob Greene'
|
||||
email = 'robgreene@gmail.com'
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/AppleCommander/bastools.git'
|
||||
developerConnection = 'scm:git:git@github.com:AppleCommander/bastools.git'
|
||||
url = 'https://github.com/AppleCommander/bastools'
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
|
||||
def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
url = isSnapshotVersion ? snapshotsRepoUrl : releasesRepoUrl
|
||||
credentials {
|
||||
username = findProperty('ossrhUsername')
|
||||
password = findProperty('ossrhPassword')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
// Only sign if we're uploading...
|
||||
required { gradle.taskGraph.hasTask("uploadArchives") }
|
||||
sign configurations.archives
|
||||
sign publishing.publications.mavenJava
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
repositories {
|
||||
mavenDeployer {
|
||||
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
|
||||
|
||||
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
|
||||
authentication(userName: findProperty('ossrhUsername'), password: findProperty('ossrhPassword'))
|
||||
}
|
||||
|
||||
snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
|
||||
authentication(userName: findProperty('ossrhUsername'), password: findProperty('ossrhPassword'))
|
||||
}
|
||||
|
||||
pom.project {
|
||||
name archivesBaseName
|
||||
packaging 'jar'
|
||||
description 'An Applesoft BASIC tools library.'
|
||||
url 'https://applecommander.github.io/'
|
||||
|
||||
scm {
|
||||
url 'https://github.com/AppleCommander/bastools'
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name 'The GNU General Public License (GPL) Version 3, 29 June 2007'
|
||||
url 'https://www.gnu.org/licenses/gpl-3.0.html'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id 'robgreene'
|
||||
email 'robgreene@gmail.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,12 @@ import io.github.applecommander.bastools.api.model.Token;
|
|||
/**
|
||||
* The TokenReader, given a text file, generates a series of Tokens (in the compiler sense,
|
||||
* not AppleSoft) for the AppleSoft program.
|
||||
*
|
||||
* <p/>
|
||||
* Note that this relies on the Java StreamTokenizer. The goal is to provide a more modern
|
||||
* parsing of tokens (in which it succeeds), however, AppleSoft itself is dated and mixes with
|
||||
* what a modern syntax would consist of. Specifically, the '#' is out of place as part of a
|
||||
* token and not a syntax element. Hence there is some funny business embedded in the code.
|
||||
*
|
||||
* @author rob
|
||||
*/
|
||||
public class TokenReader {
|
||||
|
@ -57,16 +62,16 @@ public class TokenReader {
|
|||
return tokens;
|
||||
}
|
||||
|
||||
public TokenReader(Reader reader) {
|
||||
private TokenReader(Reader reader) {
|
||||
this.reader = reader;
|
||||
this.tokenizer = ApplesoftKeyword.tokenizer(reader);
|
||||
}
|
||||
|
||||
public boolean hasMore() {
|
||||
private boolean hasMore() {
|
||||
return hasMore;
|
||||
}
|
||||
|
||||
public Optional<Token> next(int depth) throws IOException {
|
||||
private Optional<Token> next(int depth) throws IOException {
|
||||
// A cheesy attempt to prevent too much looping...
|
||||
if (depth > 0) {
|
||||
if (this.needSyntheticEol) {
|
||||
|
|
|
@ -37,6 +37,7 @@ public class EmbeddedBinaryDirective extends Directive {
|
|||
byte[] bin = Files.readAllBytes(file.toPath());
|
||||
|
||||
CodeBuilder builder = new CodeBuilder();
|
||||
CodeMark moveStart = new CodeMark();
|
||||
CodeMark embeddedStart = new CodeMark();
|
||||
CodeMark embeddedEnd = new CodeMark();
|
||||
|
||||
|
@ -48,7 +49,7 @@ public class EmbeddedBinaryDirective extends Directive {
|
|||
|
||||
targetAddress.ifPresent(address -> {
|
||||
builder.basic()
|
||||
.CALL(embeddedStart)
|
||||
.CALL(moveStart)
|
||||
.endStatement();
|
||||
|
||||
Optional<Line> nextLine = line.nextLine();
|
||||
|
@ -64,8 +65,10 @@ public class EmbeddedBinaryDirective extends Directive {
|
|||
builder.basic()
|
||||
.endLine();
|
||||
|
||||
|
||||
targetAddress.ifPresent(address -> {
|
||||
builder.asm()
|
||||
builder.set(moveStart)
|
||||
.asm()
|
||||
.setAddress(embeddedStart, 0x3c)
|
||||
.setAddress(embeddedEnd, 0x3e)
|
||||
.setAddress(address, 0x42)
|
||||
|
|
|
@ -63,6 +63,7 @@ public class ByteVisitor implements Visitor {
|
|||
ByteArrayOutputStream os = stack.peek();
|
||||
os.write(0x00);
|
||||
os.write(0x00);
|
||||
this.address += 2;
|
||||
return program;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Universal bastools version number. Used for:
|
||||
# - Naming JAR file.
|
||||
# - The build will insert this into a file that is read at run time as well.
|
||||
version=0.3.1
|
||||
version=0.4.0
|
||||
|
||||
# Maven Central Repository G and A of GAV coordinate. :-)
|
||||
group=net.sf.applecommander
|
||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
286
gradlew
vendored
286
gradlew
vendored
|
@ -1,78 +1,129 @@
|
|||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
|
@ -89,84 +140,95 @@ location of your Java installation."
|
|||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
43
gradlew.bat
vendored
43
gradlew.bat
vendored
|
@ -1,3 +1,19 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
|
@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
@ -35,7 +54,7 @@ goto fail
|
|||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
|
@ -45,28 +64,14 @@ echo location of your Java installation.
|
|||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
## Usage
|
||||
|
||||
```shell
|
||||
$ bt
|
||||
Missing required parameter: <sourceFile>
|
||||
$ bt --help
|
||||
Usage: bt [-chOVx] [--addresses] [--applesingle] [--debug] [--list] [--pretty]
|
||||
[--stdout] [--tokens] [--variables]
|
||||
[--max-line-length=<maxLineLength>] [-a=<address>] [-o=<outputFile>]
|
||||
[--stdout] [--tokens] [--variables] [--wrapper] [-a=<address>]
|
||||
[--max-line-length=<maxLineLength>] [-o=<outputFile>]
|
||||
[-f=<optimizations>[,<optimizations>...]]... <sourceFile>
|
||||
|
||||
Transforms an AppleSoft program from text back to its tokenized state.
|
||||
<sourceFile> AppleSoft BASIC program to process.
|
||||
|
||||
Options:
|
||||
--addresses Dump line number addresses out.
|
||||
--applesingle Write output in AppleSingle format
|
||||
--debug Print debug output.
|
||||
--list List structure as bastools understands it.
|
||||
--max-line-length=<maxLineLength>
|
||||
Maximum line length for generated lines.
|
||||
Default: 255
|
||||
--pretty Pretty print structure as bastools understands it.
|
||||
--stdout Send binary output to stdout.
|
||||
--tokens Dump token list to stdout for debugging.
|
||||
--variables Generate a variable report
|
||||
-a, --address=<address> Base address for program
|
||||
Default: 2049
|
||||
-c, --copy Generate a copy/paste form of output for testing in an
|
||||
emulator.
|
||||
-f= <optimizations>[,<optimizations>...]
|
||||
--addresses Dump line number addresses out.
|
||||
--applesingle Write output in AppleSingle format
|
||||
-c, --copy Generate a copy/paste form of output for testing in
|
||||
an emulator.
|
||||
--debug Print debug output.
|
||||
-f=<optimizations>[,<optimizations>...]
|
||||
Enable specific optimizations.
|
||||
* remove-empty-statements - Strip out all '::'-like
|
||||
statements.
|
||||
* remove-rem-statements - Remove all REM statements.
|
||||
* shorten-variable-names - Ensure all variables are 1 or
|
||||
2 characters long.
|
||||
* extract-constant-values - Assign all constant values
|
||||
first.
|
||||
* shorten-variable-names - Ensure all variables are
|
||||
1 or 2 characters long.
|
||||
* extract-constant-values - Assign all constant
|
||||
values first.
|
||||
* merge-lines - Merge lines.
|
||||
* renumber - Renumber program.
|
||||
-h, --help Show this help message and exit.
|
||||
--list List structure as bastools understands it.
|
||||
--max-line-length=<maxLineLength>
|
||||
Maximum line length for generated lines.
|
||||
Default: 255
|
||||
-o, --output=<outputFile> Write binary output to file.
|
||||
-O, --optimize Apply all optimizations.
|
||||
--pretty Pretty print structure as bastools understands it.
|
||||
--stdout Send binary output to stdout.
|
||||
--tokens Dump token list to stdout for debugging.
|
||||
-V, --version Print version information and exit.
|
||||
--variables Generate a variable report
|
||||
--wrapper Wrap the Applesoft program (DOS 3.3).
|
||||
-x, --hex Generate a binary hex dump for debugging.
|
||||
```
|
||||
|
||||
|
@ -153,3 +153,13 @@ demo.dsk /DEMO/
|
|||
ProDOS format; 139,264 bytes free; 4,096 bytes used.
|
||||
|
||||
```
|
||||
|
||||
## Wrapping the application
|
||||
|
||||
DOS 3.3 (but not ProDOS) seems to rewrite the application linked list when an Applesoft program is loaded; this rewrites the pointers and impacts any embedded (via `$embed`) machine code. With the wrapper, the application is "wrapped" with a startup Applesoft program that prevents the rewrite. The wrapper is just a simple program:
|
||||
|
||||
```basic
|
||||
10 POKE 103,24:POKE 104,8:RUN
|
||||
```
|
||||
|
||||
This is a valid program that resets the Applesoft pointer to just after the current program and runs that other program.
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '2.0.2.RELEASE'
|
||||
id 'org.springframework.boot' version "2.7.17"
|
||||
id 'java'
|
||||
id 'application'
|
||||
}
|
||||
|
||||
sourceCompatibility = 11
|
||||
targetCompatibility = 11
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
apply plugin: 'application'
|
||||
|
||||
mainClassName = "io.github.applecommander.bastools.tools.bt.Main"
|
||||
|
||||
bootJar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Implementation-Title': 'BT CLI',
|
||||
'Implementation-Version': "${version} (${new Date().format('yyyy-MM-dd HH:mm')})"
|
||||
'Implementation-Version': "${project.version} (${new Date().format('yyyy-MM-dd HH:mm')})"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'info.picocli:picocli:3.0.2'
|
||||
compile 'net.sf.applecommander:applesingle-api:1.2.1'
|
||||
compile project(':bastools-api')
|
||||
implementation 'info.picocli:picocli:4.7.5'
|
||||
implementation 'net.sf.applecommander:applesingle-api:1.2.2'
|
||||
implementation project(':bastools-api')
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package io.github.applecommander.bastools.tools.bt;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -74,6 +70,9 @@ public class Main implements Callable<Void> {
|
|||
|
||||
@Option(names = "--max-line-length", description = "Maximum line length for generated lines.", showDefaultValue = Visibility.ALWAYS)
|
||||
private int maxLineLength = 255;
|
||||
|
||||
@Option(names = "--wrapper", description = "Wrap the Applesoft program (DOS 3.3).")
|
||||
private boolean wrapProgram;
|
||||
|
||||
@Option(names = "-f", converter = OptimizationTypeConverter.class, split = ",", description = {
|
||||
"Enable specific optimizations.",
|
||||
|
@ -103,7 +102,8 @@ public class Main implements Callable<Void> {
|
|||
|
||||
public static void main(String[] args) throws FileNotFoundException, IOException {
|
||||
try {
|
||||
CommandLine.call(new Main(), args);
|
||||
int exitCode = new CommandLine(new Main()).execute(args);
|
||||
System.exit(exitCode);
|
||||
} catch (Throwable t) {
|
||||
if (Main.debugFlag) {
|
||||
t.printStackTrace(System.err);
|
||||
|
@ -173,17 +173,34 @@ public class Main implements Callable<Void> {
|
|||
}
|
||||
|
||||
ByteVisitor byteVisitor = Visitors.byteVisitor(config);
|
||||
byte[] data = byteVisitor.dump(program);
|
||||
byte[] wrapperData = new byte[0];
|
||||
if (wrapProgram) {
|
||||
Queue<Token> wrapperTokens = TokenReader.tokenize(new ByteArrayInputStream(
|
||||
"10 POKE 103,24:POKE 104,8:RUN".getBytes()));
|
||||
Parser wrapperParser = new Parser(wrapperTokens);
|
||||
Program wrapperProgram = wrapperParser.parse();
|
||||
wrapperData = byteVisitor.dump(wrapperProgram);
|
||||
}
|
||||
|
||||
byte[] programData = byteVisitor.dump(program);
|
||||
if (showLineAddresses) {
|
||||
byteVisitor.getLineAddresses().forEach((l,a) -> System.out.printf("%5d ... $%04x\n", l, a));
|
||||
}
|
||||
|
||||
// Merge both programs together. Note that wrapperData may be a 0 byte array.
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
output.write(wrapperData);
|
||||
output.write(programData);
|
||||
output.flush();
|
||||
byte[] data = output.toByteArray();
|
||||
|
||||
if (hexFormat) {
|
||||
HexDumper.standard().dump(address, data);
|
||||
}
|
||||
if (copyFormat) {
|
||||
HexDumper.apple2().dump(address, data);
|
||||
}
|
||||
|
||||
|
||||
saveResults(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,27 +1,30 @@
|
|||
plugins {
|
||||
id 'org.springframework.boot' version '2.0.2.RELEASE'
|
||||
id 'org.springframework.boot' version "2.7.17"
|
||||
id 'java'
|
||||
id 'application'
|
||||
}
|
||||
|
||||
sourceCompatibility = 11
|
||||
targetCompatibility = 11
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
apply plugin: 'application'
|
||||
|
||||
mainClassName = "io.github.applecommander.bastools.tools.st.Main"
|
||||
|
||||
bootJar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Implementation-Title': 'Shape Tools CLI',
|
||||
'Implementation-Version': "${version} (${new Date().format('yyyy-MM-dd HH:mm')})"
|
||||
'Implementation-Version': "${project.version} (${new Date().format('yyyy-MM-dd HH:mm')})"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'info.picocli:picocli:3.0.2'
|
||||
compile 'net.sf.applecommander:applesingle-api:1.2.1'
|
||||
compile 'net.sf.applecommander:AppleCommander:1.4.0'
|
||||
compile project(':bastools-api')
|
||||
implementation 'info.picocli:picocli:4.7.5'
|
||||
implementation 'net.sf.applecommander:applesingle-api:1.2.2'
|
||||
implementation 'net.sf.applecommander:AppleCommander:1.9.0'
|
||||
implementation project(':bastools-api')
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@ public class Main implements Runnable {
|
|||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
CommandLine.run(new Main(), args);
|
||||
int exitCode = new CommandLine(new Main()).execute(args);
|
||||
System.exit(exitCode);
|
||||
} catch (Throwable t) {
|
||||
if (Main.debugFlag) {
|
||||
t.printStackTrace(System.err);
|
||||
|
|
Loading…
Reference in New Issue
Block a user