FutureBasic Logo

<<    Index    >> FutureBasic

Appendix J - Command Line Tools   appendix

FutureBasic normally builds standard Mac applications. However, FutureBasic can also be used to build console applications and command-line tools. The choice between an FutureBasic console application or a command-line tool is made at the beginning of the program. A simple compiler conditional determines which file is to be included:

_buildAsCommandLineTool = _true // _true or _false
#if _buildAsCommandLineTool
include "CommandLineTool"
include "ConsoleWindow"

Most console apps can be built as tools with no other changes.

Retrieval of command-line arguments
The arguments that are passed on the command line can be inspected using:

tool_argc // the number of arguments
fn tool_arg( j ) // Str255 containing up to 255 characters of the jth argument
tool_argv // a pointer giving access to the C strings in "argv[]". This can be used to parse arguments longer than 255 characters.

A command-line tool always has at least one argument: the path to the command. More arguments may follow if the tool was run via a terminal or pipe.

#if def _FBUnixTool // tool_argc etc available only for tool, not console
dim as long j
print "Number of arguments = "tool_argc
for j = 0 to tool_argc - 1
 print fn tool_arg( j ) // fn tool_arg() returns a Str255

$ ./test.command 123 nine "a quoted string"
Number of arguments = 4
a quoted string

The constant _FBUnixTool is defined by the translator when building a tool, and is undefined otherwise. It is used in the code snippet above to 'conditionalise out' the argument inspection code when building a console app. Only tools receive useful arguments.

Environment variables
The command line tool can read any named environment variable from the host environment list as illustrated below:

#if def _FBUnixTool // tool only, not console
print fn tool_getenv( "HOME" ) // fn tool_getenv() returns a Str255

Standard input and output
In a tool, the input statement reads from stdin and the print statement writes to stdout.

dim as Str255 s
input s
print "The input was: " s

Note that only the first 255 characters will be read, or up to the newline character, whichever comes first.

File I/O:
A tool can perform any file-system operation except display a navigation dialog. Several functions in Util_FileDirectory.incl allow access to files in predictable locations. FD_PathGetFSRef() and FD_PathCreateCFURL() can be used to convert a path, passed as a tool argument, to a FSRef or CFURLRef.

64-bit executables
Command line tools (but not console apps) can be compiled in 64-bit mode. This is done by putting "-m64" into FBtoC's 'More compiler options'. That setting tells the compiler to produce a 64-bit executable instead of the older 32-bit kind.

#if def _LP64 // constant defined by the translator when building in 64-bit mode
print "Compiled in 64-bit mode"

def tab 10>
// these values are 8 when compiled in 64-bit mode
print "sizeof( long )", sizeof( long ) " bytes"
print "sizeof( pointer )", sizeof( pointer ) " bytes"

How to make an Xcode project from a FutureBasic command-line tool

[1] Put an Info.plist file in the same folder as the FutureBasic source. The xml content can be vacuous.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

[2] Set Optimization to None in build settings.

[3] Build and Run the FutureBasic source. You can either leave toolname.command running in Terminal.app or kill it.

[4] Choose Command > Make Xcode Project.

[5] In Xcode, Build and Run the translated C source. To see the output, ensure that Xcode's Debugger Console is shown, perhaps by choosing the command Run > Console.

[6] By appropriate manipulations in the Finder you can drag the executable from "build_temp/XcodeProject/build/Debug/toolname.app/Contents/MacOS/toolname" to a more sensible location.

[7] A later release of FutureBasic (version 5 onwards) may provide a special Xcode project template to make step #1 unnecessary and step #6 simpler.