lazarus/components/aggpas/find_compilers_mac.dpr
mattias 36a2b1ea07 added aggpas
git-svn-id: trunk@21942 -
2009-10-01 12:24:32 +00:00

662 lines
14 KiB
ObjectPascal

{target:mac}
{mac_console_app}
//
// AggPas 2.4 RM3 Helper utility application
// Milan Marusinec alias Milano (c) 2006 - 2008
//
program
find_compilers_mac ;
uses
SysUtils ,
agg_basics ,
file_utils_ ,
Carbon ;
{$I agg_mode.inc }
type
src_key = record
key ,
val : string[99 ];
end;
const
key_max = 99;
pool_max = 65536;
make_max = 99;
fpc_comp = '/usr/local/bin/ppcppc';
fpc_libs = '-Fu"src;src/ctrl;src/platform/mac;src/util;src/svg;upi;expat-wrap"';
fpc_incl = '-Fisrc';
fpc_outd = '-FU_debug';
fpc_frmw = '-k"-framework Carbon -framework QuickTime"';
fpc_conf = '-Mdelphi -Tdarwin -Sg -Se3 -XX -Xs -B -v0i';
fpc_capp = '-WC';
fpc_gapp = '-WG';
var
key_array : array[0..key_max - 1 ] of src_key;
key_count ,
key_lastx : unsigned;
key_scanx : shortstring;
pool_buff : pointer;
pool_aloc ,
pool_size : unsigned;
make_array : array[0..make_max - 1 ] of string[99 ];
make_count : unsigned;
{ WRPOOL }
procedure WrPool(str : shortstring; crlf : boolean = false );
begin
if crlf then
str:=str + #10;
if pool_size + length(str ) < pool_aloc then
begin
System.move(
str[1 ] ,
pointer(ptrcomp(pool_buff ) + pool_size )^ ,
length(str ) );
inc(pool_size ,length(str ) );
end;
end;
{ WRFILE }
function WrFile(destDir : FSRefPtr; name : shortstring ) : boolean;
var
i : unsigned;
ossState : OSStatus;
ossError : OSErr;
forkName ,
destName : HFSUniStr255;
dstFSRef : FSRef;
forkRef : SInt16;
written : ByteCount;
catInfo : FSCatalogInfo;
begin
result:=false;
// Fill in Unicode name
for i:=1 to length(name ) do
destName.unicode[i - 1 ]:=byte(name[i ] );
destName.length:=length(name );
// Write the script to file
ossError:=FSCreateFileUnicode(destDir^ ,destName.length ,destName.unicode[0 ] ,kFSCatInfoNone ,NIL ,@dstFSRef ,NIL );
if ossError = noErr then
begin
FSGetDataForkName(forkName );
ossError:=FSOpenFork(dstFSRef ,forkName.length ,forkName.unicode[0 ] ,fsWrPerm ,forkRef );
if ossError = noErr then
begin
ossError:=FSWriteFork(forkRef ,fsFromStart + noCacheBit ,0 ,pool_size ,pool_buff ,written );
FSCloseFork(forkRef );
if (ossError = noErr ) and
(pool_size = written ) then
else
exit;
end
else
begin write('[FSOpenFork:' ,ossError ,'] ' ); exit; end;
end
else
if ossError = dupFNErr then
else
begin write('[FSCreateFileUnicode:' ,ossError ,'] ' ); exit; end;
// Set The File permissions
CatInfo.permissions[0 ]:=0;
CatInfo.permissions[1 ]:=0;
CatInfo.permissions[2 ]:=0;
CatInfo.permissions[3 ]:=0;
FSPermissionInfoPtr(@CatInfo.permissions ).mode:=999;
ossError:=FSSetCatalogInfo(dstFSRef ,kFSCatInfoPermissions ,CatInfo );
// OK
result:=true;
end;
{ NEXTKEY }
function NextKey(var val : shortstring ) : boolean;
begin
result:=false;
while key_lastx < key_count do
begin
inc(key_lastx );
if cmp_str(key_array[key_lastx - 1 ].key ) = key_scanx then
begin
val :=key_array[key_lastx - 1 ].val;
result:=true;
break;
end;
end;
end;
{ FIRSTKEY }
function FirstKey(key : shortstring; var val : shortstring ) : boolean;
begin
key_lastx:=0;
key_scanx:=cmp_str(key );
result:=NextKey(val );
end;
{ LOADKEYS }
procedure LoadKeys(buff : char_ptr; size : SInt64 );
type
e_scan = (expect_lp ,load_key ,load_val ,next_ln ,expect_crlf );
var
scan : e_scan;
key ,
val : shortstring;
procedure add_key;
begin
if key_count < key_max then
begin
key_array[key_count ].key:=key;
key_array[key_count ].val:=val;
inc(key_count );
end;
key:='';
val:='';
end;
begin
key_count:=0;
scan:=expect_lp;
key :='';
val :='';
while size > 0 do
begin
case scan of
expect_lp :
case buff^ of
'{' :
scan:=load_key;
else
break;
end;
load_key :
case buff^ of
#13 ,#10 :
break;
':' :
scan:=load_val;
'}' :
begin
add_key;
scan:=next_ln;
end;
else
key:=key + buff^;
end;
load_val :
case buff^ of
#13 ,#10 :
break;
'}' :
begin
add_key;
scan:=next_ln;
end;
else
val:=val + buff^;
end;
next_ln :
case buff^ of
#13 ,#10 :
scan:=expect_crlf;
' ' :
else
break;
end;
expect_crlf :
case buff^ of
'{' :
scan:=load_key;
#13 ,#10 :
else
break;
end;
end;
dec(size );
inc(ptrcomp(buff ) );
end;
end;
{ WRITECOMPILESCRIPT }
function WriteCompileScript(destDir : FSRefPtr; name ,ext : shortstring ) : boolean;
var
cp ,fp ,fn ,fx : shortstring;
begin
result:=false;
// Create the script in memory
pool_size:=0;
WrPool(fpc_comp + ' ' );
WrPool(fpc_libs + ' ' );
WrPool(fpc_incl + ' ' );
WrPool(fpc_outd + ' ' );
WrPool(fpc_frmw + ' ' );
WrPool(fpc_conf + ' ' );
if FirstKey('mac_console_app' ,cp ) then
WrPool(fpc_capp + ' ' )
else
WrPool(fpc_gapp + ' ' );
WrPool(name + ext ,true );
if not FirstKey('mac_console_app' ,cp ) then
begin
WrPool('mkdir -p ' + name + '.app/Contents/MacOS' ,true );
WrPool('mv -f ' + name + ' ' + name + '.app/Contents/MacOS/' + name ,true );
end;
if FirstKey('mac_copy' ,cp ) then
repeat
spread_name(cp ,fp ,fn ,fx );
if cmp_str(fx ) = cmp_str('.bmp' ) then
WrPool('cp -f bmp/' + cp + ' ' + name + '.app/Contents/MacOS/' + cp ,true )
else
if cmp_str(fx ) = cmp_str('.svg' ) then
WrPool('cp -f svg/' + cp + ' ' + name + '.app/Contents/MacOS/' + cp ,true );
until not NextKey(cp );
// WriteFile
name:='compile-' + name;
if WrFile(destDir ,name ) then
begin
if make_count < make_max then
begin
make_array[make_count ]:=name;
inc(make_count );
end;
result:=true;
end;
end;
{ CREATECOMPILESCRIPT }
procedure CreateCompileScript(destDir : FSRefPtr; name ,ext : shortstring; inRef : FSRefPtr );
var
loaded : boolean;
ossError : OSStatus;
forkName : HFSUniStr255;
forkSize : SInt64;
forkRef : SInt16;
forkBuff : pointer;
forkLoad : ByteCount;
target ,value : shortstring;
begin
write(' ' ,name ,ext ,' ... ' );
// Open Source .DPR file
FSGetDataForkName(forkName );
ossError:=FSOpenFork(inRef^ ,forkName.length ,forkName.unicode[0 ] ,fsRdPerm ,forkRef );
if ossError = noErr then
begin
loaded:=false;
// Load DPR keys
FSGetForkSize(forkRef ,forkSize );
if (forkSize > 0 ) and
agg_getmem(forkBuff ,forkSize ) then
begin
ossError:=FSReadFork(forkRef ,fsAtMark + noCacheMask ,0 ,forkSize ,forkBuff ,forkLoad );
if (ossError = noErr ) and
(forkSize = forkLoad ) then
begin
loaded:=true;
LoadKeys(forkBuff ,forkSize );
end;
agg_freemem(forkBuff ,forkSize );
end;
// Close DPR
FSCloseFork(forkRef );
// Create compilation script
if loaded then
begin
if FirstKey('skip' ,value ) then
writeln('to be not included -> skipped' )
else
begin
target:='mac';
FirstKey('target' ,target );
if cmp_str(target ) = cmp_str('mac' ) then
if WriteCompileScript(destDir ,name ,ext ) then
writeln('OK' )
else
writeln('Failed to generate compile script !' )
else
writeln('different target (' ,target ,') -> skipped' );
end;
end
else
writeln('Failed to read the source file !' );
end
else
writeln('Failed to open !' );
end;
{ PROCESSOBJECT }
procedure ProcessObject(destDir : FSRefPtr; inCatInfo : FSCatalogInfoPtr; inRef : FSRefPtr; inSpec : FSSpecPtr );
var
file_path ,file_name ,file_ext : shortstring;
begin
if inCatInfo.nodeFlags and kFSNodeIsDirectoryMask = kFSNodeIsDirectoryMask then
else
begin
spread_name(inSpec.name ,file_path ,file_name ,file_ext );
if cmp_str(file_ext ) = cmp_str('.dpr' ) then
CreateCompileScript(destDir ,file_name ,file_ext ,inRef );
end;
end;
{ ITERATEFOLDER }
function IterateFolder(var inFolder : FSRef ) : OSStatus;
var
kRequestCountPerIteration : size_t;
outStatus : OSStatus;
kCatalogInfoBitmap : FSCatalogInfoBitmap;
iterator : FSIterator;
catalogInfoArray : FSCatalogInfoPtr;
FSRefArray : FSRefPtr;
FSSpecArray : FSSpecPtr;
actualCount : ItemCount;
index : UInt32;
changed : boolean;
begin
kRequestCountPerIteration:=((4096 * 4 ) div sizeof(FSCatalogInfo ) );
// Get permissions and node flags and Finder info
//
// For maximum performance, specify in the catalog
// bitmap only the information you need to know
kCatalogInfoBitmap:=kFSCatInfoNodeFlags or kFSCatInfoFinderInfo;
// On each iteration of the do-while loop, retrieve this
// number of catalog infos
//
// We use the number of FSCatalogInfos that will fit in
// exactly four VM pages (#113). This is a good balance
// between the iteration I/O overhead and the risk of
// incurring additional I/O from additional memory
// allocation
// Create an iterator
outStatus:=FSOpenIterator(inFolder ,kFSIterateFlat ,iterator );
if outStatus = noErr then
begin
// Allocate storage for the returned information
agg_getmem(pointer(catalogInfoArray ) ,sizeof(FSCatalogInfo ) * kRequestCountPerIteration );
agg_getmem(pointer(FSRefArray ) ,sizeof(FSRef ) * kRequestCountPerIteration );
agg_getmem(pointer(FSSpecArray ) ,sizeof(FSSpec ) * kRequestCountPerIteration );
if catalogInfoArray = NIL then
outStatus:=memFullErr
else
begin
// Request information about files in the given directory,
// until we get a status code back from the File Manager
repeat
changed:=false;
outStatus:=
FSGetCatalogInfoBulk(
iterator ,
kRequestCountPerIteration ,
actualCount ,
changed ,
kCatalogInfoBitmap ,
catalogInfoArray ,
FSRefArray ,
FSSpecArray ,
NIL );
// Process all items received
if (outStatus = noErr ) or
(outStatus = errFSNoMoreItems ) then
for index:=0 to actualCount - 1 do
ProcessObject(
@inFolder ,
FSCatalogInfoPtr(
ptrcomp(catalogInfoArray ) +
index * sizeof(FSCatalogInfo ) ) ,
FSRefPtr(
ptrcomp(FSRefarray ) +
index * sizeof(FSRef ) ) ,
FSSpecPtr(
ptrcomp(FSSpecArray ) +
index * sizeof(FSSpec ) ) );
until outStatus <> noErr;
// errFSNoMoreItems tells us we have successfully processed all
// items in the directory -- not really an error
if outStatus = errFSNoMoreItems then
outStatus:=noErr;
// Free the array memory
agg_freemem(pointer(catalogInfoArray ) ,sizeof(FSCatalogInfo ) * kRequestCountPerIteration );
agg_freemem(pointer(FSRefArray ) ,sizeof(FSRef ) * kRequestCountPerIteration );
agg_freemem(pointer(FSSpecArray ) ,sizeof(FSSpec ) * kRequestCountPerIteration );
end;
end;
FSCloseIterator(iterator );
result:=outStatus;
end;
{ CREATEMAKEFILE }
procedure CreateMakeFile(destDir : FSRefPtr );
var
i : unsigned;
begin
pool_size:=0;
i:=0;
while i < make_count do
begin
WrPool('./' + make_array[i ] ,true );
inc(i );
end;
WrFile(destDir ,'compile_make_all' );
end;
{ SCANDEMOS }
procedure ScanDemos;
var
outStatus : OSStatus;
folderRef : FSRef;
fileSpecs : FSSpec;
begin
outStatus:=FSMakeFSSpec(0 ,0 ,'' ,fileSpecs );
if outStatus = noErr then
begin
outStatus:=FSpMakeFSRef(fileSpecs ,folderRef );
if outStatus = noErr then
begin
outStatus:=IterateFolder(folderRef );
writeln;
if make_count > 0 then
begin
CreateMakeFile(@folderRef );
writeln('SUCCESS: FPC compilation script files were created' );
writeln(' for the AggPas demos listed above.' );
writeln;
writeln(' To compile the demos, run Terminal, change to the current' );
writeln(' directory and type "./compile_make_all"' );
writeln(' or "./compile-xxx", where "xxx" is the name of the demo.' );
end
else
writeln('MESSAGE: No AggPas demo files were found in current folder !' );
end
else
writeln('ERROR: Failed to create FSRef structure for the current folder !' );
end
else
writeln('ERROR: Failed to search for files in the current folder !' );
writeln;
end;
BEGIN
writeln;
writeln('*************************************************************' );
writeln('* Welcome to the AggPas 2.4 RM3 vector graphics library. *' );
writeln('*************************************************************' );
writeln('* *' );
writeln('* This helper utility will generate the compilation script *' );
writeln('* files with current paths and options needed to compile *' );
writeln('* properly all the AggPas demos on your Mac. *' );
writeln('* *' );
writeln('* Currently the Free Pascal compiler is supported. *' );
writeln('* (www.freepascal.org) *' );
writeln('* *' );
writeln('*************************************************************' );
writeln;
writeln('[Press ENTER key to continue ...]' );
writeln;
readln;
if agg_getmem(pool_buff ,pool_max ) then
begin
pool_aloc :=pool_max;
pool_size :=0;
make_count:=0;
ScanDemos;
agg_freemem(pool_buff ,pool_aloc );
end
else
writeln('ERROR: Not enough memory for the pool buffer !' );
END.