# Settings
#
-IMPLS = ada awk bash c d chuck clojure coffee clisp cpp crystal cs erlang elisp \
+IMPLS = ada awk bash basic c d chuck clojure coffee clisp cpp crystal cs erlang elisp \
elixir es6 factor forth fsharp go groovy guile haskell haxe \
io java julia js kotlin logo lua make mal ocaml matlab miniMAL \
nim objc objpascal perl perl6 php plpgsql plsql powershell ps \
ada_STEP_TO_PROG = ada/$($(1))
awk_STEP_TO_PROG = awk/$($(1)).awk
bash_STEP_TO_PROG = bash/$($(1)).sh
+basic_STEP_TO_PROG = basic/$($(1)).bas
c_STEP_TO_PROG = c/$($(1))
d_STEP_TO_PROG = d/$($(1))
chuck_STEP_TO_PROG = chuck/$($(1)).ck
--- /dev/null
+
+step%.bas: step%.in.bas readline.in.bas
+ ./qb2cbm.sh $< > $@
--- /dev/null
+#!/bin/bash
+
+set -e
+
+DEBUG=${DEBUG:-}
+
+infile=$1
+
+die () {
+ echo >&2 "$*"
+ exit 1
+}
+
+[ "${infile}" ] || die "Usage: <infile>"
+
+input=$(cat ${infile})
+
+[ "${DEBUG}" ] && echo >&2 "Processing includes"
+
+full="${input}"
+declare -A included
+
+while [[ ${input} =~ REM\ \$INCLUDE:\ \'.*\' ]]; do
+ full=""
+ while read -r line; do
+ if [[ ${line} =~ REM\ \$INCLUDE:\ \'.*\' ]]; then
+ include=${line#REM \$INCLUDE: \'}
+ include=${include%\'}
+ # Only include it once
+ if [ "${included[${include}]}" ];then
+ [ "${DEBUG}" ] && echo >&2 "already included: ${include}"
+ continue
+ fi
+ [ "${DEBUG}" ] && echo >&2 "including: ${include}"
+ included[${include}]="done"
+ full="${full}\nREM vvv BEGIN '${include}' vvv\n$(cat ${include})\nREM vvv END '${include}' vvv\n"
+ else
+ full="${full}${line}\n"
+ fi
+ done < <(echo -e "${input}")
+ input="${full}"
+done
+
+
+[ "${DEBUG}" ] && echo >&2 "Renumbering"
+
+data=""
+declare -A labels
+
+lnum=10
+while read -r line; do
+ if [[ ${line} =~ ^\ *$ ]]; then
+ [ "${DEBUG}" ] && echo >&2 "found blank line after $lnum"
+ data="${data}\n"
+ continue
+ elif [[ ${line} =~ ^[A-Za-z_]*:$ ]]; then
+ label=${line%:}
+ [ "${DEBUG}" ] && echo >&2 "found label ${label} at $lnum"
+ labels[${label}]=$lnum
+ data="${data}${lnum} REM ${label}:\n"
+ else
+ data="${data}${lnum} ${line}\n"
+ fi
+ lnum=$(( lnum + 10 ))
+done < <(echo -e "${input}")
+
+for label in "${!labels[@]}"; do
+ [ "${DEBUG}" ] && echo >&2 "Updating label: ${label}"
+ lnum=${labels[${label}]}
+ data=$(echo "${data}" | sed "s/\(THEN\|GOTO\|GOSUB\) ${label}\>/\1 ${lnum}: REM \1 ${label}/g")
+done
+
+echo -en "${data}"
--- /dev/null
+EOF=0
+
+REM READLINE(A$) -> R$
+READLINE:
+ EOF=0
+ PROMPT$=A$
+ PRINT PROMPT$;
+ CH$="": LINE$="": CH=0
+ READCH:
+ GET CH$: IF CH$="" THEN READCH
+ CH=ASC(CH$)
+ IF (CH=4 OR CH=0) THEN EOF=1: GOTO RL_DONE: REM EOF
+ IF (CH=127) THEN GOSUB RL_BACKSPACE
+ IF (CH=127) THEN GOTO READCH
+ IF (CH<32 OR CH>127) AND CH<>13 THEN READCH
+ IF LEN(LINE$)<255 AND CH$<>CHR$(13) THEN LINE$=LINE$+CH$
+ IF LEN(LINE$)<255 AND CH$<>CHR$(13) THEN GOTO READCH
+ RL_DONE:
+ R$=LINE$
+ RETURN
+
+ REM Assumes LINE$ has input buffer
+ RL_BACKSPACE:
+ IF LEN(LINE$)=0 THEN RL_BACKSPACE_ONCE:
+ PRINT CHR$(157) + CHR$(157) + " " + CHR$(157) + CHR$(157);
+ LINE$=LEFT$(LINE$, LEN(LINE$)-1)
+ RETURN
+ RL_BACKSPACE_ONCE:
+ PRINT CHR$(157) + " " + CHR$(157);
+ RETURN
--- /dev/null
+#!/bin/bash
+exec cbmbasic $(dirname $0)/${STEP:-stepA_mal}.bas "${@}"
--- /dev/null
+GOTO MAIN
+
+REM $INCLUDE: 'readline.in.bas'
+
+REM /* READ(A$) -> R$ */
+MAL_READ:
+ R$=A$
+ RETURN
+
+REM /* EVAL(A$, E%) -> R$ */
+EVAL:
+ GOSUB MAL_READ: REM /* call READ */
+ RETURN
+
+REM /* PRINT(A$) -> R$ */
+MAL_PRINT:
+ GOSUB EVAL: REM /* call EVAL */
+ RETURN
+
+REM /* REP(A$) -> R$ */
+REP:
+ GOSUB MAL_PRINT: REM /* call PRINT */
+ PRINT R$
+ RETURN
+
+REM /* main program loop */
+MAIN:
+ A$="user> "
+ GOSUB READLINE: REM /* call input parser */
+ IF EOF=1 THEN END
+ A$=R$
+ GOSUB REP: REM /* call REP */
+ GOTO MAIN
+