Futurebasic/FBtoC

From Wikibooks, open books for an open world
< Futurebasic
Jump to: navigation, search

Introduction[edit]

What is FBtoC?[edit]

FBtoC is a replacement for the FB Compiler (FB Compiler.app) . Translating the code to C allows Apple's developer tools to create a universal binary. The diagrams below illustrate the process:

FB Compiler: FB source codelegacy app (PPC-only, CFM format, resource fork...)
FBtoC: FB source codeC source codeOS X app package with Carbon universal binary in Mach-O format

FBtoC translates appearance projects and standalone files, and console-type text-only standalone files. PG projects cannot be translated. Using FBtoC normally requires no detailed knowledge of C.

Why translate to C when I code in BASIC?[edit]

  • The compiler (gcc) has more powerful optimizations for speed than the FB compiler.
  • Native Intel code runs ≈3 times faster (or more) than PPC code under Rosetta.
  • Framework access is much simpler than in FB (see later).
  • FBtoC can automatically copy specified files into the app's resources (see later).
  • Apple's modern development tools work on apps built by FBtoC. Tools include the Xcode debugger and the performance analyser Shark.
  • An app can be built as small as 64 KB.
    • (window 1 : print "Hello, world!" : do HandleEvents : until gFBQuit)
  • On an Intel Mac, crash reports are interpretable, unlike those of a legacy FB app.
  • Unlike FB, there is no 32k limit on local function variables.
  • And then there's the coveted Universal Binary status!

Installation[edit]

This section describes the installation of both FutureBASIC and FBtoC. Before continuing, you will need to obtain the following:

System Requirements[edit]

FBtoC should work on OS X 10.3.9 and later. Most development and testing has been done on OS X 10.4 and 10.5. Before using FBtoC you should have installed Apple's free Developer Tools (a.k.a. Xcode Tools), from your OS X install CDs or DVD.

To create universal binaries, you must have OS X 10.4 or higher, gcc 4.0 or higher, and install the Cross-development SDKs. Without /Developer/SDKs/MacOSX10.4u.sdk, only the native architecture of your Mac can be built. The Finder view (below) of the Developer folder shows the SDKs after installation. Cross-development is an optional part of the Xcode Tools install (from the OS X DVD or CDs).

See also Apple's documentation: Apple Developer Tools Documentation

Installing FBtoC[edit]

Just drag-and-drop. The folder containing FBtoC.app must also contain three special folders: build_goodies, Headers, and User Libraries.

The build-goodies folder contains pretranslated parts of the runtime. Changing any of these files is likely to break FBtoC.

The Headers folder contains a subset of the standard FB Headers files. Most of them needed modification to make them work with FBtoC. In general, an existing FB Headers file will not work if simply copied into this folder.

User Libraries has the same function as in FB, except that the little-known special file UserFloatPrefs is ignored by FBtoC.

Differences Between FutureBASIC and FBtoC[edit]

Mildly bad news[edit]

Some things that have to be done differently in FBtoC:

compile long if replace by #if....
enterproc label must match the enterproc fn name
autoXREFCurr& different syntax; see later
DynamicRemoveItems different syntax; see later
ControlButtonContentInfo different syntax with '.u'; see later
HMHelpContent different syntax with '.u'; see later
Hndl replace by Handle
proc different syntax; also, label *must* precede line in which proc appears
100#, 100! FBII format; rewrite both as 100.0

Features not implemented[edit]

Due to FBtoC operational constraints and other more obvious constraints (e.g. Intel doesn't support PowerPC assembler -duh), some legacy syntax cannot be implemented. However, a modern equivalent to achieve a similar goal often exists. Updating legacy source code to a modern equivalent benefits from newer features and helps preserve the longevity of the source code.

1. Legacy syntax and language[edit]

beginassem ... endassem FB assembler is incompatible with gcc (even on PPC)
tbalias discussed later
dim record FBII pseudo-record; use true record instead
dim as int x;0, hi as byte, lo as byte aliased vars would lead to endian bugs
myLong&[0] would lead to endian bug

2. Not currently implemented[edit]

appleeventmessage$
def SomeAreButSomeAreNotAvailable
DynamicInsertItems
event&
event%
flushevents // instead use the Toolbox: call FlushEvents( _everyEvent, 0 )
folder
get field
on appleevent
on break
on edit
on expr
on finderinfo
on lprint
on overflows
on stop
override local fn SomeFunction, override runtime SomeRuntimeThing (but override _someConst = 1 IS supported)
parentID
picture field
syserror
timer [function]

3. Toolbox aliases not supported[edit]

The TBalias statement in FB allows old Toolbox names to be kept and applied to new functions when introduced by Apple. The idea must have been to save programmers a minute or two updating function names, a task otherwise tiresomely required every few years. The TBalias feature is now Considered Harmful and will not be supported by FBtoC. You may have already upgraded your project to use the correct (Apple's official) Toolbox names. If not, be prepared for FBtoC error messages indicating dodgy names:

•• Unknown statement in line 6 of untitled
  6:  RmveResource( resH )
                 ^

The simple, recommended, and only, workaround is to replace each occurrence in your code of the fossil RmveResource by RemoveResource.

Some Toolbox functions that were commonly aliased in old FB code are listed below:

FB, FBtoC and C FB-only alias
GetIntlResource IUGetIntl
MemError MemErr
DisposeHandle DisposHandle
DisposePtr DisposPtr
AppendResMenu AddResMenu
GetMenuHandle GetMHandle
CountMenuItems CountMItems
EnableMenuItem EnableItem
DisableMenuItem DisableItem
GetControlValue GetCtlValue
GetControlReference GetCRefcon
PBReadSync PBRead
PBCatMoveSync CatMove
PBHCreateSync HCreate
PBFlushVolSync FlushVol
AEPutParamDesc AEPutKeyDesc
SecondsToDate Secs2Date
LongSecondsToDate LongSecs2Date
RemoveResource RmveResource

4. Missing Headers files[edit]

include "Util_Dialogtests.incl"

•• Include file not found in line 1 of OopsMissingFunction.main
  1:  include "Util_Dialogtests.incl"
                                    ^

FBtoC's Headers folder doesn't have this file yet.


5. Incomplete Headers files[edit]

include "Util_Files.incl"
dim as FSSpec   fs
dim as Boolean  found
found = usr FSFileExists( fs )

•• Unknown function in line 4 of OopsMissingFunction.main: FSFileExists
  4:  found = usr FSFileExists( fs )
                               ^

Util_Files.incl is present in FBtoC's Headers folder; the error arises because the function usr FSFileExists has been conditionalised out by some petty official, one hopes temporarily. [Note added later: FSFileExists is now implemented]


Sample translations by FBtoC[edit]

Elderly FB code preserved in the FBtoC runtime:

CLEAR LOCAL
dim pBlk.128
LOCAL FN FBGetFolderName(DirID&,WDRefNum%,@StrPtr&)
 StrPtr&.Nil$ = ""
 pBlk.ioDirID&    = DirID&
 pBlk.ioVRefNum%  = WDRefNum%
 pBlk.ioNamePtr&  = StrPtr&
 pBlk.ioFDirIndex%= -1
 long if FN PBGetCatInfoSync(@pBlk)
  StrPtr&.Nil$ = "Error"
 end if
END FN
long FBGetFolderName( long  DirID, short  WDRefNum, long  StrPtr )
{
  char              pBlk[128] = {};
  PLstrcpy( ((StringPtr)StrPtr), "\p" );
  *(long*)(pBlk + 48) = DirID;
  *(short*)(pBlk + 22) = WDRefNum;
  *(long*)(pBlk + 18) = StrPtr;
  *(short*)(pBlk + 28) = -1;
  if ( PBGetCatInfoSync( (void*)&pBlk ) )
  {
  PLstrcpy( ((StringPtr)StrPtr), "\pError" );
  } // 'end if'
  return 0;
} 

One of FBtoC's many internal functions:

local fn DefinePointRecord
 dim as VarInfo  varInfo
 BlockZero( varInfo, sizeof( varInfo ) )
 varInfo.varType = _shortVarType // for fields
 fn SuppressTypedefs
 fn StartRecordDefinition( "Point" )
 fn AddFieldToRecordDefinition( "v", "", varInfo )
 fn AddFieldToRecordDefinition( "h", "", varInfo )
 fn FinishRecordDefinition
 fn DontSuppressTypedefs
end fn
long DefinePointRecord()
{
  VarInfo           varInfo;
  BlockZero( &varInfo, sizeof( varInfo ) );
  varInfo.varType =  3;
  SuppressTypedefs();
  StartRecordDefinition( PLstrcpy( gFBStrStk[++gFBStk], "\pPoint" ) );
  AddFieldToRecordDefinition( PLstrcpy( gFBStrStk[++gFBStk], "\pv" ), PLstrcpy( gFBStrStk[++gFBStk], "\p" ), &varInfo );
  AddFieldToRecordDefinition( PLstrcpy( gFBStrStk[++gFBStk], "\ph" ), PLstrcpy( gFBStrStk[++gFBStk], "\p" ), &varInfo );
  FinishRecordDefinition();
  DontSuppressTypedefs();
  return 0;
}