diff --git a/README.md b/README.md
index 4f10e69..d1b440a 100755
--- a/README.md
+++ b/README.md
@@ -2,11 +2,23 @@
# Portable Icon 9.5.2
+## Quick start (TL;DR)
+
+1. Create an Icon program, `world.icn`
+ - e.g., `copy examples\example_shebang.cmd world.icn`
+1. Translate and run in separate steps:
+ 1. Translate world.icn with
`path\to\icont world`
+ 1. Run the program with
`world`
+1. Translate and run the program in a single step with
`icon world.icn`
+1. Run an example script that contains a Icon program
`examples\example_shebang.cmd`
+
+## Introduction
+
The Icon programming language
[https://cs.arizona.edu/icon/](https://cs.arizona.edu/icon/) is
a high-level, general-purpose programming language that is in
the public domain. Icon programs translated by the Icon translator
-("icont") can be run by the Icon interpreter ("iconx").
+("icont") can be run by the Icon runtime interpreter ("iconx").
Frequently, Icon can be an expressive and enjoyable way to write software. You might find it helpful to copy the framework for writing and
running Icon programs to your home directory.
@@ -16,44 +28,95 @@ and library files for running Icon 9.5.2 on Microsoft Windows
in a manner similar to how Icon runs on Unix.
- This build has been tested on Windows 10.
-- This framework embeds "icode" (translated Icon programs) embedded `.bat`
+- This framework embeds "icode" (translated Icon programs) into `.bat`
files that provide for several ways of searching for the `iconx` runtime
system (which implements the Icon interpreter).
- This is very similar to how Icon 9.3.2 for Windows produces `.bat`
files when directed not to include a copy of the Icon interpreter when
translating Icon programs.
-
-This repository also provides rudimentary support for writing scripts
+- This repository also provides rudimentary support for writing scripts
in Icon.
-The icon translator and interpreter here were built in July 2021 using
+The icon translator and interpreter here were built in August 2021 using
Cygwin as described in
[the `README.md` file in the `src` directory](./src/README.md).
(These were compiled without support for the Icon graphical interface,
and they differ from
[the build of Icon for Windows (from 2015)](https://www2.cs.arizona.edu/icon/v95w.htm),
-for which source code is not presently available.)
+for which source code is not presently available.)
-(There is also an actively developed language extending Icon called Unicon
-that may be preferred for general software development because it provides
-multithreading and modern integration with networking, databases, messaging,
-file attributes, and the operating system. Please see
-[http://unicon.org/](http://unicon.org/) for further info.
-Unicon for Windows produces stand-alone binaries have a minimum size of about 5.5mb.)
+## Examples
-## Files in this repository
+Icon programs use the extension `.icn` (which need not be included
+for source files when invoking the translator using the `icont.cmd` script,
+but which is included in the examples below for clarity).
+The translator always produces a `.bat` file that includes the translation
+of the program into icode and [some code to search for the Icon runtime
+(`iconx`)](#searching-for-iconx-the-icon-runtime-interpreter).
+
+### `icont.cmd` outputs
+
+The output produced by `icont.cmd` can be adjusted several ways:
+
+- To create `world.bat` (a batch file that includes the icode as described immediately above):
+
`icont world.icn`
+ - To run this from within a batch file, you must use the `call` syntax:
+ `call world`
+ - To run it from the command line, `call` is not necessary
+ `world`
+- To create `world.exe` (an addtional 18 kb file that calls `world.bat` in the
+ same directory, so that batch files can use `world` rather than `call world`),
+ either give the output file a `.exe` extension or include the `--add-exe`
+ option:
+
`icont --add-exe world.icn`
+
`icont -o world.exe world.icn`
+ - Unless you have modified your `PATHEXT` environment variable, executing
+ `world`
+ will invoke `world.exe` in preference to `world.bat`.
+- To create a "standalone" set of files in the `portable` directory that
+ can be copied to and run on another machine without Icon installed,
+ include the `--standalone` option:
+
`icont -o portable\world.exe --standalone world.icn`
+
which populates `portable` with:
+ - `world.bat`
+ - `world.exe`
+ - `cygwin1.dll`
+ - `nticont.exe`
+- As with Icon on Unix, when the `-o` option is not specified, the result
+ is named after the first `.icn` file named; the following produces
+ `world.bat`:
+
`icont world.icn moon.icn`
+- To produce an icode-only file (*in addition to* the `.bat` file), provide
+ an extension for the output file different from `.bat` or `.exe`:
+
`icont -o world.icx world.icn`
+- To produce an icode-only file (without the `.bat` file),
+ - either use `icont_nosmudge`:
+
`icont_nosmudge -o world.icx world.icn`
+ - or define the `ICONT_NOSMUDGE` environment variable:
+
`set ICONT_NOSMUDGE=1`
+
`icont -o world.icx world.icn`
+ - If you were to want to create a `world.bat` file later from `world.icx`,
+ you would run this:
+
`bin\smudge world.icx`
-Note that invoking `icont.cmd` or `icont.exe` produces `.bat' program that
-needs no adjustments to the PATH to execute.
+### Searching for `iconx` (the Icon runtime interpreter)
-### Top-level files that you may find convenient to put onto your path
+The `.bat` file produced by `icont.cmd` includes code to search for the
+Icon runtime interpreter (`iconx`); the search order is:
+
+1. the value to which the `ICONX` environment variable is set, which, if it is set, should be the full path to a copy of `bin\nticonx.exe`;
+1. a file named `nticonx.exe` in the same directory as the `.bat` file;
+1. a file named `nticonx.exe` in the directory where the translator (`nticont.exe`) was located when it translated the program (assuming that it has not moved);
+1. a file named `nticonx.exe` on the `PATH`.
+
+## Files in this repository
+
+### Top-level files (which you may find convenient to put onto your path)
- `icont.cmd`
- This is a "convenience script" for invoking `bin\nticont.exe`:
- - Run `icont.cmd` without any arguments for a list of options.
- - This script passes all arguments through to `nticont.exe` *after* it:
- - ensures that the portable directory (which contains `bin\nticont.exe`
- and `bin\nticonx.exe`) is in PATH.
+ - Run `icont.cmd` without any arguments for a list of options.
+ - This script passes all arguments through to `bin\nticont.exe` (the actual translator) *after* it:
- ensures that the IPATH environmental variable points to the working
directory and `ipl/procs` unless IPATH is already set:
- Because spaces are the separator between directories specified in
@@ -68,9 +131,10 @@ needs no adjustments to the PATH to execute.
- ensures that the LPATH environmental variable points to the working
directory and `ipl/incl` unless LPATH is already set;
the same considerations for IPATH apply to LPATH.
- - converts the resulting icode into a `.bat` file.
+ - invokes `bin\smudge` to present the resulting icode files as described
+ in ["Examples"](#examples) above.
- The resulting `.bat` file can be executed anywhere on the machine
- so long as the path to the `bin` directory does not change.
+ so long as the path to the `bin` directory does not change, as described in ["Examples"](#examples) above.
- `icont.exe`
- This is a "convenience program" that calls `icont.cmd`, passing all of
its arguments through to `icont.cmd`.
@@ -83,6 +147,7 @@ needs no adjustments to the PATH to execute.
- This script invokes `icont` with a directive **not** to wrap the icode into
a `.bat` file. Rather, a non-executable `.exe` file containing the icode
is produced.
+ - `icont.cmd` performs this way when the `ICONT_NOSMUDGE` environment variable is set.
- See smoke test 7 in `examples\smoke_test.cmd`.
- `iconx.cmd`
- This is a "convenience script" for invoking `bin\nticonx.exe`:
@@ -100,15 +165,17 @@ needs no adjustments to the PATH to execute.
- usage: `icon [options for icont] [program.icn or -] [args]`
- Note that passing options of icont is an extension that is not allowed
on the Unix builds of Icon.
- - "Shebang - scripting with Icon" makes use of this script.
+ - ["Shebang - scripting with Icon"](#shebang---scripting-with-icon) makes use of this script.
+ - To support this, no matching `icon.exe` program is included.
- See smoke test 9 in `examples\smoke_test.cmd`.
- `#!icon.cmd`
- This script facilitates construction of scripts that are valid Icon
- source code and may be just-in-time translated and executed.
+ source code and may be just-in-time translated and executed.
- See `example\example_shebang.cmd` and `example\#!icon.cmd` to see how
to reference and use this script.
+ - See also ["Shebang - scripting with Icon"](#shebang---scripting-with-icon).
-### Examples of how to use the top-level files
+### More examples
- `examples\smoke_test.cmd`
- This demonstrates use of most of the files in the repository
@@ -131,7 +198,7 @@ needs no adjustments to the PATH to execute.
- See smoke test 3 in `examples\smoke_test.cmd`.
- See also "Shebang - scripting with Icon" for details.
-### Files that you do not need to interact with directly
+### Files with which you (ordinarily) do not need to interact directly
The following files are used by the top level programs; you shouldn't need
to interact with them directly.
@@ -150,11 +217,12 @@ to interact with them directly.
- `bin\nticonx.exe`
- This is the actual Icon interpreter, which executes "icode".
- See `iconx.*` for a convenient way to invoke this indirectly.
-- `bin\smudge.cmd` is a small utility that converts an "icode" file into
+- `bin\smudge.cmd` is a small utility invoked by `icont.cmd` (but not by
+ `icont_nosmudge.cmd`) that, in turn, converts an "icode" file into
a `.bat` file that locates and invokes the virtual machine; the search order
is:
1. The path set in the `ICONX` environment variable.
- 1. `nticonx.exe` if it exists in the same directory as the `.bat` file.
+ 1. `nticonx.exe` if it exists in the same directory as the `.bat` file.
- This is to mimic the behavior of the Unix build; it requires copies
of `bin\nticonx.exe` and `bin\cygwin1.dll` to be in the directory
as well.
@@ -192,17 +260,27 @@ For this to work:
must pass control to the `#!icon.cmd` script in the directory containing
`icon.cmd`.
- `examples\#!icon.cmd` does this.
-- In other words, I don't have to have this script on my PATH *per se*, as long
- as I have another (trivial) script on my path containing one line, e.g.:
-
`@"C:\Users\art\src\portableIcon\#!icon.cmd" %*`
+ - a minimally dependent example (not dependent on `examples\#!icon.cmd`) would be:
+ `mkdir elsewhere`
+ `copy examples\example_shebang.cmd elsewhere\`
+ `cmd /c "set PATH=.;c:\windows\system32& elsewhere\example_shebang.cmd foo bar"`
+- I don't have to have `C:\Users\eschen42\portableIcon\#!icon.cmd`
+ on my PATH *per se*, as long as I have another (trivial) script on my path
+ named `#!icon.cmd` that contains one line, e.g.:
+
`@"C:\Users\eschen42\portableIcon\#!icon.cmd" %*`
See test 8 in `smoke_test.cmd`.
## Bugs
-So far, I have not found a way to express an IPATH or LPATH that has
-directories that themselves include spaces, except by using
-["8.3" filenames](https://en.wikipedia.org/wiki/8.3_filename#Working_with_short_filenames_in_a_command_prompt).
+- I have not found a way to express an IPATH or LPATH that has
+ directories that themselves include spaces, except by using
+ ["8.3" filenames](https://en.wikipedia.org/wiki/8.3_filename#Working_with_short_filenames_in_a_command_prompt).
+- `bin\nticont.exe` and `bin\nticonx.exe` must be invoked with a relative or absolute path, i.e., the
+ `nticont.exe`
+ invocation fails from within the `bin` directory, but
+ `.\nticont.exe`
+ succeeds.
# Portable Icon 9.3.2
@@ -213,3 +291,13 @@ A portable version of Icon 9.3.2 is available on the `icon_v9.3.2` branch:
[https://github.com/eschen42/portableIcon/releases/tag/v9.3.2_rc1](https://github.com/eschen42/portableIcon/releases/tag/v9.3.2_rc1).
- For a description, see
[https://github.com/eschen42/portableIcon/tree/icon_v9.3.2](https://github.com/eschen42/portableIcon/tree/icon_v9.3.2)
+
+# Unicon
+
+There is an actively developed language extending Icon called Unicon
+that may be preferred for general software development because it provides
+multithreading and modern integration with networking, databases, messaging,
+file attributes, and the operating system. Please see
+[http://unicon.org/](http://unicon.org/) for further info.
+Unicon for Windows produces stand-alone binaries have a minimum size of about 5.5mb.
+
diff --git a/bin/smudge.cmd b/bin/smudge.cmd
index 6be0aa7..958d4cd 100755
--- a/bin/smudge.cmd
+++ b/bin/smudge.cmd
@@ -1,5 +1,15 @@
-@set ERRORLEVEL=&setlocal&set ECHO_ON=off
-@echo %ECHO_ON%
+ @set ERRORLEVEL=&set EXIT_CODE=1&setlocal&set ECHO_ON=off
+ @echo %ECHO_ON%
+
+ :: At least one argument is required
+ set ARG1=&set ARG1=%1&set ARG1s=%~dpns1
+ if not defined ARG1 goto usage
+ set EXIT_CODE=0
+ if /I ""%1"" == ""--help"" goto help
+ if ""%1"" == ""/?"" goto help
+ if /I ""%1"" == ""-H"" goto help
+
+set EXIT_CODE=1
set SMUDGE=smudge%RANDOM%
set ARG0=%~dpnxs0
set ARG0dir=%~dps0
@@ -10,11 +20,14 @@ set ARG1long=%~dps1%~n1
set ARG1x=%~xs1
set ARG2=%2
set ARG3=%3
-if defined ARG3 goto :usage
+set ARG4=%4
+if defined ARG4 goto :usage
if not defined ARG1 goto :usage
-if not exist "%ARG1%.exe" goto :usage
-if /I not "%ARG1x%" == ".exe" goto :usage
+if exist "%ARG1%.exe" set ARG1x=.exe
+if not exist "%ARG1%%ARG1x%" goto :usage
+
if not defined ICONX set ICONX=%ARG0dir%nticonx.exe
+fc /b "%ARG1%%ARG1x%" %ARG0dir%..\iconx.exe >NUL && goto :eof
:: Write the following inline text to file specified by the SMUDGE envar,
:: stopping at :HERE_END, using delayed-expansion syntax
pushd %~dps0
@@ -57,21 +70,33 @@ echo %ECHO_ON%
move /y %ARG1%%ARG1x% %ARG1%.%SMUDGE% >NUL
copy /y %ARG1dir%%SMUDGE% "%ARG1long%.bat" >NUL
type %ARG1%.%SMUDGE% >> "%ARG1long%.bat"
-del %ARG1dir%%SMUDGE% %ARG1%.%SMUDGE%
+if "%ARG1X%" == ".exe" (
+ del %ARG1DIR%%SMUDGE% %ARG1%.%SMUDGE%
+) else (
+ del %ARG1DIR%%SMUDGE%
+ move %ARG1%.%SMUDGE% %ARG1%%ARG1x% >NUL
+)
if not defined ARG2 exit/b 0
-if not "%ARG2%" == "--standalone" exit/b 0
-if not exist %ARG1dir%nticonx.exe copy %ARG0dir%nticonx.exe %ARG1dir%nticonx.exe >NUL
-if not exist %ARG1dir%cygwin1.dll copy %ARG0dir%cygwin1.dll %ARG1dir%cygwin1.dll >NUL
+
+set STANDALONE=0
+set ADD_EXE=0
+if "%ARG2%" == "--standalone" set STANDALONE=1
+if "%ARG2%" == "--add-exe" set ADD_EXE=1
+if "%ARG3%" == "--standalone" set STANDALONE=1
+if "%ARG3%" == "--add-exe" set ADD_EXE=1
+if 1 == %STANDALONE% (
+ if not exist %ARG1dir%nticonx.exe copy %ARG0dir%nticonx.exe %ARG1dir%nticonx.exe >NUL
+ if not exist %ARG1dir%cygwin1.dll copy %ARG0dir%cygwin1.dll %ARG1dir%cygwin1.dll >NUL
+)
+if 1 == %ADD_EXE% (
+ copy %ARG0dir%..\iconx.exe "%ARG1long%.exe" >NUL
+)
exit/b 0
:HERE_ERROR
echo %~nx0: Unable to write execution stub for icode
exit /b 1
-:usage
-
-echo "usage: %~nx0 "
-exit /b 1
::::::::::::::::::::::::::: :heredoc subroutine ::::::::::::::::::::::::::::
:: https://github.com/ildar-shaimordanov/cmd.scripts/blob/master/heredoc.bat
@@ -79,28 +104,48 @@ exit /b 1
:: ref: https://stackoverflow.com/a/15032476/3627676
::
:heredoc LABEL
-@echo off
-setlocal enabledelayedexpansion
-if not defined CMDCALLER set "CMDCALLER=%~f0"
-set go=
-for /f "delims=" %%A in ( '
- findstr /n "^" "%CMDCALLER%"
-' ) do (
- set "line=%%A"
- set "line=!line:*:=!"
+ @echo off
+ setlocal enabledelayedexpansion
+ if not defined CMDCALLER set "CMDCALLER=%~f0"
+ set go=
+ for /f "delims=" %%A in ( '
+ findstr /n "^" "%CMDCALLER%"
+ ' ) do (
+ set "line=%%A"
+ set "line=!line:*:=!"
- if defined go (
- if /i "!line!" == "!go!" goto :EOF
- echo:!line!
- ) else (
- rem delims are @ ( ) > & | TAB , ; = SPACE
- for /f "tokens=1-3 delims=@()>&| ,;= " %%i in ( "!line!" ) do (
- if /i "%%i %%j %%k" == "call :heredoc %1" set "go=%%k"
- if /i "%%i %%j %%k" == "call heredoc %1" set "go=%%k"
- if defined go if not "!go:~0,1!" == ":" set "go=:!go!"
- )
- )
-)
-set ECHO=%ECHO_ON%
-@goto :EOF
+ if defined go (
+ if /i "!line!" == "!go!" goto :EOF
+ echo:!line!
+ ) else (
+ rem delims are @ ( ) > & | TAB , ; = SPACE
+ for /f "tokens=1-3 delims=@()>&| ,;= " %%i in ( "!line!" ) do (
+ if /i "%%i %%j %%k" == "call :heredoc %1" set "go=%%k"
+ if /i "%%i %%j %%k" == "call heredoc %1" set "go=%%k"
+ if defined go if not "!go:~0,1!" == ":" set "go=:!go!"
+ )
+ )
+ )
+ set ECHO=%ECHO_ON%
+ @goto :EOF
::::::::::::::::::::::::: end :heredoc subroutine ::::::::::::::::::::::::::
+
+:usage
+ set EXIT_CODE=1
+ if defined ARG1 echo %~nxs0 %*
+ if not defined ARG1 (
+ echo.
+ echo.%~nxs0: at least one argument is required
+ )
+
+:help
+ echo.
+ echo.usage: %~nx0 icode [--standalone] [--add-exe]
+ echo. produces:
+ echo. icode.bat - (if icode has a file extension, it is omitted)
+ echo. icode.exe - (when --add-exe is specified)
+ echo. nticonx.exe - (when --standalone is specified)
+ echo. cygwin1.dll - (when --standalone is specified)
+ echo. where:
+ echo. icode is a file containing a translated Icon program
+ exit /b %EXIT_CODE%
diff --git a/examples/run_smoke_test.cmd b/examples/run_smoke_test.cmd
index 1c78eb1..963f138 100755
--- a/examples/run_smoke_test.cmd
+++ b/examples/run_smoke_test.cmd
@@ -1,11 +1,11 @@
-@set ERRORLEVEL=&setlocal&echo off
+@set ERRORLEVEL=&setlocal&set ECHO_ON=off
+@echo %ECHO_ON%
call %~dps0smoke_test.cmd > %~dps0smoke_test.output.actual.txt
if %ERRORLEVEL% neq 0 (
(echo smoke_test.cmd FAILED with error %ERRORLEVEL%)
endlocal
exit/b %ERRORLEVEL%
)
-if %ERRORLEVEL% neq 0 (echo smoke_test.cmd FAILED with error %ERRORLEVEL%)&endlocal&exit/b %ERRORLEVEL%
diff %~dps0smoke_test.output.expected.txt %~dps0smoke_test.output.actual.txt
if %ERRORLEVEL% neq 0 (
(echo smoke_test.cmd FAILED because results differed from what was expected)
diff --git a/examples/smoke_test.cmd b/examples/smoke_test.cmd
index 89b1cc5..15d1e2c 100755
--- a/examples/smoke_test.cmd
+++ b/examples/smoke_test.cmd
@@ -1,5 +1,5 @@
-@ set ERRORLEVEL=&setlocal&echo off
-@ set SENTINEL=findstr& set PROMPT=running -$G &set ECHO_ON=off
+@ set ERRORLEVEL=& setlocal& set SENTINEL=findstr& set PROMPT=running -$G& set ECHO_ON=off
+@ echo %ECHO_ON%
:: single-ampersand means execute second command regardless of EXITCODE from first command
set EXIT_CODE=0
@@ -27,8 +27,8 @@ if %ERRORLEVEL% neq 0 (
@echo ------- Test one - Translate with default options [1] 1>&2
@echo.
set PROMPT=running one -$G
-@echo %ECHO_ON%
(call "%~dp0..\icont.cmd" "%~dp0world.icn") >NUL 2>&1
+::@echo %ECHO_ON%
@ if %ERRORLEVEL% neq 0 (
set TEST_NAME=one translation
call :fail_msg icont.cmd world.icn failed
@@ -52,20 +52,20 @@ del "%~dp0world.bat"
@echo.
set PROMPT=running two -$G
@echo %ECHO_ON%
-call "%~dp0..\icont.cmd" -s -u -o "%~dp0mundo.exe" "%~dp0world.icn" 2>&1
+call "%~dp0..\icont.cmd" -s -u -o "%~dp0mundo.exe" --standalone "%~dp0world.icn" 2>&1
@ if %ERRORLEVEL% neq 0 (
set TEST_NAME=two translation
call :fail_msg icont.cmd -o mundo.exe world.icn failed
goto :farewell
)
-call "%~dp0..\bin\smudge.cmd" "%~dp0mundo.exe" --standalone
-@ if %ERRORLEVEL% neq 0 (
- set TEST_NAME=two smudge
- call :fail_msg bin\smudge.cmd mundo.exe failed
+@if not exist "%~dp0mundo.bat" (
+ set TEST_NAME=two no icode
+ call :fail_msg icont -o did not produce expected icode .bat file
goto :farewell
)
if not exist "%~dp0cygwin1.dll" echo cygwin1.dll required for standalone execution was not found
if not exist "%~dp0nticonx.exe" echo nticonx.exe required for standalone execution was not found
+if not exist "%~dp0mundo.exe" echo icode .exe file was not produced implicitly by -o .exe
@echo %ECHO_ON%
call "%~dp0mundo.bat" one two
@echo off
@@ -74,6 +74,14 @@ call "%~dp0mundo.bat" one two
call :fail_msg call mundo.bat failed
goto :farewell
)
+if exist "%~dp0world.exe" del "%~dp0world.exe"
+call "%~dp0..\icont.cmd" -s -u --add-exe "%~dp0world.icn" 2>&1 >NUL
+@if not exist "%~dp0world.exe" (
+ dir
+ set TEST_NAME=two no added exe
+ call :fail_msg icont --add-exe did not produce expected stub .exe file
+ goto :farewell
+)
:: prep for next test
if exist "%~dp0cygwin1.dll" del "%~dp0cygwin1.dll"
@@ -155,12 +163,14 @@ setlocal
call :fail_msg call icont.exe -o world.exe world.icn failed
goto :farewell
)
-call "%~dp0..\bin\smudge.cmd" "%~dp0world.exe"
-@ if %ERRORLEVEL% neq 0 (
- set TEST_NAME=five smudge
- call :fail_msg call bin\smudge.cmd world.exe failed
- goto :farewell
-)
+:: dir world.*
+:: call "%~dp0..\bin\smudge.cmd" "%~dp0world.exe"
+:: @ if %ERRORLEVEL% neq 0 (
+:: set TEST_NAME=five smudge
+:: call :fail_msg call bin\smudge.cmd world.exe failed
+:: goto :farewell
+:: )
+:: dir world.*
set PROMPT=running five -$G
set OLD_PATH=%PATH%
set PATH=%~dp0..;%PATH%
@@ -300,7 +310,8 @@ call %~dps0..\icont.cmd -v0 "%~dps0mio mundo.icn"&& call "%~dps0mio mundo.bat" n
)
if exist "%~dp0mio mundo.icn" del "%~dp0mio mundo.icn"
if exist "%~dp0mio mundo.bat" del "%~dp0mio mundo.bat"
-@echo off
+@ echo %ECHO_ON%
+set EXIT_CODE=0
goto farewell
@@ -309,15 +320,19 @@ goto farewell
set EXIT_CODE=%ERRORLEVEL%
echo %~n0 test %TEST_NAME% FAILED: %* 1>&2
+set EXIT_MSG=smoke test FAILED
+echo !!!!! %EXIT_MSG% !!!!!
+echo !!!!! %EXIT_MSG% !!!!! 1>&2
+
goto :eof
:farewell
+popd
+
@echo.
-@echo ------- "Where there's smoke, there's fire." -Anonymous ---------
-@echo ------- "Where there's smoke, there's fire." -Anonymous --------- 1>&2
+if %EXIT_CODE% equ 0 @echo ------- "Where there's smoke, there's fire." -Anonymous ---------
+if %EXIT_CODE% equ 0 @echo ------- "Where there's smoke, there's fire." -Anonymous --------- 1>&2
-popd
-if %EXIT_CODE% neq 0 echo %EXIT_MSG%
endlocal&exit /b %EXIT_CODE%
diff --git a/icon.cmd b/icon.cmd
index b64e0f8..337112c 100755
--- a/icon.cmd
+++ b/icon.cmd
@@ -38,7 +38,7 @@
if "%ICN_FILE%" == "-" goto have_pipe
:not_pipe
- set ICX=%ICNSRCdps%%ICNSRCns%.exe
+ set ICX=%ICNSRCdps%%ICNSRCns%.bat
if not exist "%ICNSRCdpnsx%" if not exist "%ICNSRCdpns%.icn" (
echo.icon.cmd: No .icn file find among args:
echo. %*
@@ -52,18 +52,31 @@
)
set ICNSRCdpnsx="%ICNSRCdpnsx%"
set ICX="%ICX%"
- ( type %ICNSRCdpnsx% | call %ARG0%icont.cmd -o %ICX% -u -v0 %ICONT_ARGS% -
- )&& if exist %ICX% ( %ARG0%bin\nticonx.exe %ICX% %ARGS% & del %ICX% ) else (echo %ARG0%: translation of %ICNSRCdpnsx% FAILED)
+ (
+ type %ICNSRCdpnsx% | call %ARG0%icont.cmd -o %ICX% -u -v0 %ICONT_ARGS% -
+ ) && if exist %ICX% (
+ call %ICX% %ARGS%
+ del %ICX%
+ if exist %ICX% echo icon.cmd: %ICX% still exists
+ ) else (echo %ARG0%: translation of %ICNSRCdpnsx% FAILED)
:: double-ampersand means execute second command only if first command returns zero EXITCODE
@echo off
goto post_pipe
:have_pipe
- set ICX=%ICNSRCdps%pipe%RANDOM%.exe
+ set ICX=%ICNSRCdps%pipe%RANDOM%.bat
set ICX="%ICX%"
- (call %ARG0%icont.cmd -o %ICX% -u -v0 %ICONT_ARGS% -
- )&& if exist %ICX% ( %ARG0%bin\nticonx.exe %ICX% %ARGS% & del %ICX% ) else (echo %ARG0%: translation of standard input FAILED)
+ (
+ call %ARG0%icont.cmd -o %ICX% -u -v0 %ICONT_ARGS% -
+ ) && if exist %ICX% (
+ :: echo running %ICX%
+ call %ICX% %ARGS%
+ del %ICX%
+ if exist %ICX% echo icon.cmd: %ICX% still exists
+ ) else (
+ echo %ARG0%: translation of standard input FAILED
+ )
:post_pipe
set EXIT_ERROR=%ERRORLEVEL%
diff --git a/icont.cmd b/icont.cmd
index 12bd88c..c25d471 100755
--- a/icont.cmd
+++ b/icont.cmd
@@ -1,11 +1,13 @@
- @set ERRORLEVEL=&setlocal&echo off
+ @set ERRORLEVEL=&set EXIT_CODE=1&setlocal&set ECHO_ON=off
+ @echo %ECHO_ON%
:: At least one argument is required
set ARG1=&set ARG1=%1&set ARG1s=%~dpns1
+ if not defined ARG1 goto usage
+ set EXIT_CODE=0
if /I ""%1"" == ""--help"" goto help
if ""%1"" == ""/?"" goto help
if /I ""%1"" == ""-H"" goto help
- if not defined ARG1 goto usage
:: set ARGS and STANDALONE
call :get_args %*
@@ -27,6 +29,8 @@
if not defined LPATH set LPATH=%~dps0ipl\incl
:: Return to working directory
popd
+
+ :: echo %MYNTICONT% %ARGS% 1>&2
:: Pass all arguments to the translator
%MYNTICONT% %ARGS%
set MY_RESULT=%ERRORLEVEL%
@@ -35,11 +39,20 @@
shift
if NOT .%1. == .. goto shift_loop
- if not defined ICODE set ICODE="%ISRC:~1,-1%"
- if ""%ISRC%"" == """-""" set ICODE="stdin"
- :: @if exist "%ICODE:~1,-1%.exe" echo "%ICODE:~1,-1%.exe" exists
- if not defined ICONT_NOSMUDGE if exist "%ICODE:~1,-1%.exe" (
- call "%BINDIR%\smudge.cmd" "%ICODE:~1,-1%.exe" %STANDALONE% >NUL
+ if ""%ISRC%"" == """-""" (
+ set ICODE="stdin"
+ set ICODEx=.exe
+ )
+ if not defined ICODE (
+ set ICODE="%ISRC:~1,-1%"
+ set ICODEx=.exe
+ )
+ :: smudge if icode.exe exists
+ :: echo "%%ICODE:~1,-1%%%%ICODEx%%" is %ICODE:~1,-1%%ICODEx%
+ if not defined ICONT_NOSMUDGE if not exist "%ICODE:~1,-1%%ICODEx%" echo Does the directory for "%ICODE:~1,-1%%ICODEx%" exist?
+ if not defined ICONT_NOSMUDGE if exist "%ICODE:~1,-1%%ICODEx%" (
+ :: echo call "%BINDIR%\smudge.cmd" "%ICODE:~1,-1%%ICODEx%" %STANDALONE% %ADD_EXE% 1>&2
+ call "%BINDIR%\smudge.cmd" "%ICODE:~1,-1%%ICODEx%" %STANDALONE% %ADD_EXE%
)
:: Produce result returned by translator
exit /b %MY_RESULT%
@@ -62,21 +75,49 @@ set ISRC=
:: shift till last arg is %0
set ARG=%0
if not defined ARG goto got_args
-:more_args
- if not ""%ARG%"" == """%ARG:~1,-1%""" if %ARG% == --standalone goto standalone
+ :more_args
+ if not ""%ARG%"" == """%ARG:~1,-1%""" (
+ if %ARG% == --standalone goto standalone
+ if %ARG% == --add-exe goto add_exe
+ )
set ARGS=%ARGS% %ARG%
+ set LAST_ARG=%0
+ if not defined ISRC if exist %~dpns0.icn set ISRC="%~n0"
+ goto shift_args
+ :add_exe
+ set ADD_EXE=--add-exe
goto shift_args
:standalone
set STANDALONE=--standalone
+ goto shift_args
:shift_args
- set LAST_ARG=%0
- set ISRC="%~n0"
- shift
- set ARG=%0
- if ""-o"" == ""%LAST_ARG%"" set ICODE=%~dpn0
- if not defined ARG goto got_args
- goto more_args
+ shift
+ set ARG=%0
+ set ARGx=%~xs0
+ if ""-o"" == ""%LAST_ARG%"" (
+ set ICODE="%~dpn0"
+ set ICODEx=%ARGx%
+ if "%ARGx%" == "" (
+ set ICODEx=.exe
+ set ADD_EXE=--add-exe
+ )
+ if /i "%ARGx%" == ".exe" set ADD_EXE=--add-exe
+ if /i "%ARGx%" == ".bat" set ARG=%~dpn0
+ )
+ if not defined ARG goto got_args
+ goto more_args
:got_args
+ :: Note this quirk: setting ICODEx to .exe does NOT result in
+ :: invocation of smudge with --add-exe, which is correct
+ :: but may be unexpected.
+ if /i "%ICODEx%" == ".bat" set ICODEx=.exe
+ echo %ECHO_ON%
+ :: echo ARGS=%ARGS% 1>&2
+ :: echo ISRC=%ISRC% 1>&2
+ :: echo ICODE=%ICODE% 1>&2
+ :: echo ICODEx=%ICODEx% 1>&2
+ :: echo STANDALONE=%STANDALONE% 1>&2
+ :: echo ADD_EXE=%ADD_EXE% 1>&2
goto :eof
::::::::::::::::::::::::::: :get_args subroutine ::::::::::::::::::::::::::::
@@ -112,25 +153,29 @@ goto :eof
@goto :EOF
::::::::::::::::::::::::: end :heredoc subroutine ::::::::::::::::::::::::::
-
:usage
-
+ set EXIT_CODE=1
if defined ARG1 echo %~nxs0 %*
+ if not defined ARG1 (
+ echo.
+ echo.%~nxs0: at least one argument is required
+ )
:help
set NX0=%~nx0
set DP0=%~dp0
set DPNX0=%~dpnx0
call :heredoc :post_usage & goto :post_usage
+-------------------------------------------------------------------------------
+# icont usage
-
-usage: !NX0! [-cpstuEV] [-fs] [-e efile] [-o ofile] file
+usage: !NX0! [-cpstuEV] [-fs] [-o ofile] [--add-exe] [--standalone] file[.icn]
-c Perform no linking, just produce `.u1` and `.u2` files.
- -e Redirect standard error [for execution] to efile.
-fs Prevent removal of all unreferenced declarations.
- This has the same effect as "invocable all" in the program.
- -o Name for output file. Without -o, !NX0! defaults creates
- file.bat
+ This has the same effect as `invocable all` in the program.
+ -o Name for output file:
+ - If `-o` is unspecified, `-o file.bat` is implied.
+ - If `ofile` has extension `.exe`, `--add-exe` is implied.
-p enable icode profiling
-s Suppress informative messages.
-t Turn on procedure tracing.
@@ -143,21 +188,27 @@ usage: !NX0! [-cpstuEV] [-fs] [-e efile] [-o ofile] file
n = 3 - also list discarded globals
-E Preprocess only. [This can be very helpful when debugging.]
-V print version information
-
--standalone
Copy nticonx.exe and cygwin1.dll to directory having .bat file.
-
-When !NX0! creates an .exe file:
- - It is likely that:
- + either, you will want to invoke the interpreter directly with
- !DP0!iconx.cmd file.exe
- + or you may want to run
- !DP0!bin\smudge.cmd file.exe
- to produce file.bat, but remember to
- call file.bat
- from batch files so that control will return to the calling
- script when file.bat exits.
+ --add-exe
+ (Implied when ofile name ends with `.exe`)
+ Create an `ofile.exe` file that invokes `ofile.bat`.
+ This passes all arguments through, but it works only when
+ `ofile.exe` and `ofile.bat` are in the same directory.
You can find !NX0! at !DPNX0!
+Environmental variables recognized by !NX0!
+
+Name Default Description
+-------- ------- -----------------------
+IPATH none search path for link directives
+LPATH none search path for $include directives
+
+Search paths are blank-separated lists of directories.
+The current directory is searched before a search path is used.
+-------------------------------------------------------------------------------
+
:post_usage
+
+exit /b %EXIT_CODE%
diff --git a/iconx.cmd b/iconx.cmd
index 8621f5a..e875fff 100755
--- a/iconx.cmd
+++ b/iconx.cmd
@@ -1 +1,84 @@
-@%~dps0bin\nticonx.exe %*
+ @set ERRORLEVEL=&set EXIT_CODE=1&setlocal&set ECHO_ON=off
+ @echo %ECHO_ON%
+
+ :: At least one argument is required
+ set ARG1=&set ARG1=%1&set ARG1s=%~dpns1
+ if not defined ARG1 goto usage
+ set EXIT_CODE=0
+ if /I ""%1"" == ""--help"" goto help
+ if ""%1"" == ""/?"" goto help
+ if /I ""%1"" == ""-H"" goto help
+
+
+ @%~dps0bin\nticonx.exe %*
+ @exit /b %ERRORLEVEL%
+
+
+::::::::::::::::::::::::::: :heredoc subroutine ::::::::::::::::::::::::::::
+:: https://github.com/ildar-shaimordanov/cmd.scripts/blob/master/heredoc.bat
+:: ref: https://stackoverflow.com/a/29329912
+:: ref: https://stackoverflow.com/a/15032476/3627676
+::
+:heredoc LABEL
+ @echo off
+ setlocal enabledelayedexpansion
+ if not defined CMDCALLER set "CMDCALLER=%~f0"
+ set go=
+ for /f "delims=" %%A in ( '
+ findstr /n "^" "%CMDCALLER%"
+ ' ) do (
+ set "line=%%A"
+ set "line=!line:*:=!"
+
+ if defined go (
+ if /i "!line!" == "!go!" goto :EOF
+ echo:!line!
+ ) else (
+ rem delims are @ ( ) > & | TAB , ; = SPACE
+ for /f "tokens=1-3 delims=@()>&| ,;= " %%i in ( "!line!" ) do (
+ if /i "%%i %%j %%k" == "call :heredoc %1" set "go=%%k"
+ if /i "%%i %%j %%k" == "call heredoc %1" set "go=%%k"
+ if defined go if not "!go:~0,1!" == ":" set "go=:!go!"
+ )
+ )
+ )
+ set ECHO=%ECHO_ON%
+ @goto :EOF
+::::::::::::::::::::::::: end :heredoc subroutine ::::::::::::::::::::::::::
+
+:usage
+ set EXIT_CODE=1
+ if defined ARG1 echo %~nxs0 %*
+ if not defined ARG1 (
+ echo.
+ echo.%~nxs0: at least one argument is required
+ )
+
+:help
+ set NX0=%~nx0
+ set DP0=%~dp0
+ set DPNX0=%~dpnx0
+ call :heredoc :post_usage & goto :post_usage
+-------------------------------------------------------------------------------
+# iconx usage
+
+usage: !NX0! icode-file-name [arguments for Icon program]
+
+You can find !NX0! at !DPNX0!
+
+Environmental variables recognized by !NX0!
+
+Name Default Description
+--------- ------- ----------------------------------------------------
+TRACE 0 Initial value for &trace.
+NOERRBUF undefined If set, &errout is not buffered.
+STRSIZE 500000 Initial size (bytes) of string region (strings).
+BLKSIZE 500000 Initial size (bytes) of block region (most objects).
+COEXPSIZE 2000 Size (long words) of co-expression blocks.
+MSTKSIZE 10000 Size (long words) of main interpreter stack.
+ICONPROFILE none Output file for execution profile.
+-------------------------------------------------------------------------------
+
+:post_usage
+
+exit /b %EXIT_CODE%
diff --git a/options_icont.md b/options_icont.md
index f75224a..48b3243 100755
--- a/options_icont.md
+++ b/options_icont.md
@@ -8,17 +8,16 @@ References:
- GNU tar could not:
- `tar (GNU tar) 1.12`
-## `bin\icont.exe` - Icon Translator
+## `bin\nticont.exe` - Icon Translator
```
-usage: icont [-cstuEIX] [-fs] [-e efile] [-o ofile] file ... [-x args]
+usage: icont [-cstuEIX] [-fs] [-o ofile] file ... [-x args]
```
From `sed -n -e '/case/ {s/.*-/ -/; s/[*][\/]//; p}' tunix.c`:
- `-c`: compile only (no linking)
- Perform no linking, just produce `.u1` and `.u2` files
-- `-e file`: [undoc] redirect stderr
- `-fs` or `-f s`: prevent removal of all unreferenced declarations
- - same as putting "invocable all" in your program
+ - same as putting `invocable all` in your program
- `-o file`: name output file
- `-p`: enable icode profiling
- `-s`: suppress informative messages (same as `-v 0`)
@@ -46,7 +45,7 @@ LPATH none search path for $include directives
```
Search paths are blank-separated lists of directories. The current directory is searched before a search path is used.
-## `bin\iconx.exe` - Icon Interpreter
+## `bin\nticonx.exe` - Icon Interpreter
```
usage: iconx icode-file-name [arguments for Icon program]
@@ -64,30 +63,3 @@ BLKSIZE 500000 Initial size (bytes) of block region (most objects).
COEXPSIZE 2000 Size (long words) of co-expression blocks.
MSTKSIZE 10000 Size (long words) of main interpreter stack.
```
-
-```
-icon9.32_src/src$ grep -n "case '.':" icont/tmain.c
-298: case '"': {
-607: case 'C': /* Ignore: compiler only */
-609: case 'E': /* -E: preprocess only */
-614: case 'L': /* -L: enable linker debugging */
-622: case 'S': /* -S */
-627: case 'X': /* -X */
-634: case 'I': /* -C */
-638: case 'A':
-644: case 'c': /* -c: compile only (no linking) */
-647: case 'e': /* -e file: redirect stderr */
-650: case 'f': /* -f features: enable features */
-656: case 'i': /* -i: Don't create .EXE file */
-661: case 'm': /* -m: preprocess using m4(1) [UNIX] */
-664: case 'n': /* Ignore: compiler only */
-666: case 'o': /* -o file: name output file */
-670: case 'p': /* -p path: iconx path [ATARI] */
-679: case 'q':
-683: case 'r': /* Ignore: compiler only */
-685: case 's': /* -s: suppress informative messages */
-689: case 't': /* -t: turn on procedure tracing */
-692: case 'u': /* -u: warn about undeclared ids */
-695: case 'v': /* -v n: set verbosity level */
-702: case 'x': /* -x illegal until after file list */
-```