跳轉到內容

Futurebasic/FBtoC

來自華夏公益教科書

什麼是 FBtoC?

[編輯 | 編輯原始碼]

FBtoC 是 FB 編譯器 (FB Compiler.app) 的替代品。將程式碼翻譯成 C 允許 Apple 的開發工具建立通用二進位制檔案。下面的圖表說明了這個過程

FB 編譯器FB 原始碼遺留應用程式(僅限 PPC,CFM 格式,資源分支...)
FBtoCFB 原始碼C 原始碼帶有 Carbon 通用二進位制檔案的 OS X 應用程式包,以 Mach-O 格式

FBtoC 翻譯外觀專案和獨立檔案,以及控制檯型別的純文字獨立檔案。PG 專案無法翻譯。使用 FBtoC 通常不需要詳細瞭解 C。

為什麼當我用 BASIC 程式設計時要翻譯成 C?

[編輯 | 編輯原始碼]
  • 編譯器 (gcc) 對速度的最佳化比 FB 編譯器更強大。
  • 原生 Intel 程式碼在 Rosetta 下的執行速度比 PPC 程式碼快 ≈3 倍(或更多)。
  • 框架訪問比 FB 中更容易(見後)。
  • FBtoC 可以自動將指定的資料夾複製到應用程式的資源中(見後)。
  • Apple 的現代開發工具適用於 FBtoC 生成的應用程式。工具包括 Xcode 偵錯程式和效能分析器 Shark。
  • 應用程式可以構建得儘可能小,只有 64 KB。
    • (視窗 1 : 列印 "Hello, world!" : 執行 處理事件 : 直到 gFBQuit)
  • 在 Intel Mac 上,崩潰報告是可以解釋的,不像遺留的 FB 應用程式那樣。
  • 與 FB 不同,區域性函式變數沒有 32k 的限制。
  • 還有令人垂涎的通用二進位制檔案狀態!

本節介紹 FutureBASIC 和 FBtoC 的安裝。在繼續之前,您需要獲取以下內容

系統要求

[編輯 | 編輯原始碼]

FBtoC 應該可以在 OS X 10.3.9 及更高版本上執行。大部分開發和測試是在 OS X 10.4 和 10.5 上完成的。在使用 FBtoC 之前,您應該已經安裝了 Apple 的免費開發工具(也稱為 Xcode 工具),這些工具來自您的 OS X 安裝 CD 或 DVD。

要建立通用二進位制檔案,您必須擁有 OS X 10.4 或更高版本、gcc 4.0 或更高版本,並安裝交叉開發 SDK。如果沒有 /Developer/SDKs/MacOSX10.4u.sdk,則只能構建 Mac 本機的體系結構。安裝後,Developer 資料夾的 Finder 檢視(下面)將顯示 SDK。交叉開發是 Xcode 工具安裝(來自 OS X DVD 或 CD)的可選部分。

另請參閱 Apple 的文件:Apple 開發工具文件

安裝 FBtoC

[編輯 | 編輯原始碼]

只需拖放。包含 FBtoC.app 的資料夾還必須包含三個特殊資料夾:build_goodiesHeadersUser Libraries

build-goodies 資料夾包含執行時的預翻譯部分。更改任何這些檔案可能會破壞 FBtoC。

Headers 資料夾包含標準 FB 標頭檔案的一部分。大多數檔案都需要修改才能在 FBtoC 中使用。一般來說,現有的 FB 標頭檔案如果簡單地複製到此資料夾中,將無法使用。

User Libraries 與 FB 中的功能相同,只是 FBtoC 會忽略鮮為人知的特殊檔案 UserFloatPrefs。

FutureBASIC 和 FBtoC 之間的差異

[編輯 | 編輯原始碼]

不太好的訊息

[編輯 | 編輯原始碼]

FBtoC 中必須以不同的方式完成的一些事情

編譯長 if用 #if.... 替換
enterproc標籤必須與 enterproc 函式名匹配
autoXREFCurr&不同的語法;見後
DynamicRemoveItems不同的語法;見後
ControlButtonContentInfo用 '.u' 的不同語法;見後
HMHelpContent用 '.u' 的不同語法;見後
Hndl用 Handle 替換
proc不同的語法;此外,標籤 *必須* 在 proc 出現的行之前
100#, 100!FBII 格式;都重寫為 100.0

未實現的功能

[編輯 | 編輯原始碼]

由於 FBtoC 的操作限制和其他更明顯的限制(例如,Intel 不支援 PowerPC 彙編器 - 當然),一些遺留語法無法實現。但是,通常存在用於實現類似目標的現代等效項。將遺留原始碼更新為現代等效項可以利用更新的功能,並有助於保持原始碼的長期可用性。

1. 遺留語法和語言

[編輯 | 編輯原始碼]
beginassem ... endassemFB 彙編器與 gcc 不相容(即使在 PPC 上也不相容)
tbalias稍後討論
dim recordFBII 偽記錄;使用真實記錄
dim as int x;0, hi as byte, lo as byte別名變數會導致位元組序錯誤
myLong&[0]會導致位元組序錯誤

2. 目前未實現

[編輯 | 編輯原始碼]

appleeventmessage$
def SomeAreButSomeAreNotAvailable
DynamicInsertItems
event&
event%
flushevents // 相反,使用 Toolbox:呼叫 FlushEvents( _everyEvent, 0 )
folder
get field
on appleevent
on break
on edit
on expr
on finderinfo
on lprint
on overflows
on stop
覆蓋本地函式 SomeFunction,覆蓋執行時 SomeRuntimeThing(但支援覆蓋 _someConst = 1)
parentID
圖片欄位
syserror
計時器 [函式]

3. 不支援工具箱別名

[編輯 | 編輯原始碼]

FB 中的 TBalias 語句允許保留舊的工具箱名稱,並在 Apple 引入新函式時應用於新函式。這個想法應該是為了節省程式設計師更新函式名稱的一兩分鐘時間,否則每隔幾年就需要進行這項令人厭煩的任務。TBalias 功能現在被認為是有害的,FBtoC 將不支援它。您可能已經升級了您的專案,以便使用正確的(Apple 的官方)工具箱名稱。如果沒有,請做好準備,FBtoC 會顯示錯誤訊息,表明名稱有問題。

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

簡單、推薦的且唯一的解決方法是在程式碼中用 RemoveResource 替換每個出現的 RmveResource。

下面列出了一些在舊 FB 程式碼中經常被別名的工具箱函式。

FB、FBtoC 和 C僅限 FB 的別名
GetIntlResourceIUGetIntl
MemErrorMemErr
DisposeHandleDisposHandle
DisposePtrDisposPtr
AppendResMenuAddResMenu
GetMenuHandleGetMHandle
CountMenuItemsCountMItems
EnableMenuItemEnableItem
DisableMenuItemDisableItem
GetControlValueGetCtlValue
GetControlReferenceGetCRefcon
PBReadSyncPBRead
PBCatMoveSyncCatMove
PBHCreateSyncHCreate
PBFlushVolSyncFlushVol
AEPutParamDescAEPutKeyDesc
SecondsToDateSecs2Date
LongSecondsToDateLongSecs2Date
RemoveResourceRmveResource

4. 缺少標頭檔案

[編輯 | 編輯原始碼]
include "Util_Dialogtests.incl"

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

FBtoC 的 Headers 資料夾中還沒有此檔案。

5. 不完整的標頭檔案

[編輯 | 編輯原始碼]
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 存在於 FBtoC 的 Headers 資料夾中;錯誤出現是因為函式 usr FSFileExists 被某個小氣的官員給有條件地移除了,希望只是暫時性的。[稍後新增的說明:現在實現了 FSFileExists]

FBtoC 的示例翻譯

[編輯 | 編輯原始碼]

在 FBtoC 執行時中儲存的舊 FB 程式碼

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;
} 

FBtoC 的眾多內部函式之一

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;
} 
華夏公益教科書