Difference between revisions of "Porting from Mac Pascal"

From Lazarus wiki
Jump to navigationJump to search
(→‎See also: Add another link)
 
(12 intermediate revisions by 5 users not shown)
Line 1: Line 1:
== Tips and tricks for porting from Mac Pascals to FPC ==
+
Although FPC today supports many [[Mac Pascal]] constructs, there are a few of issues one has to be aware of.
 
 
Although FPC today supports many Mac pascal constructs, there are a lot of issues one has to be aware of.
 
 
Tips to make the code work with GPC are also welcome.
 
Tips to make the code work with GPC are also welcome.
  
 
== Setting the compilation mode ==
 
== Setting the compilation mode ==
  
First of all, ensure that the compiler is in Mac Pascal mode. You can do this by either using the -Mmacpas command line switch, or by adding {$mode macpas} at the top of all of your source files.
+
First of all, ensure that the compiler is in [[Mode MacPas|Mac Pascal]] mode. You can do this by either using the -Mmacpas command line switch, or by adding {$mode macpas} at the top of all of your source files.
  
 
== Unit Names ==
 
== Unit Names ==
Line 15: Line 13:
 
Depending on the compiler you're moving from, you may have a simple or complex uses clause to include all of the toolbox calls.  Either way, it can all be replaced with:
 
Depending on the compiler you're moving from, you may have a simple or complex uses clause to include all of the toolbox calls.  Either way, it can all be replaced with:
  
 +
<syntaxhighlight lang="pascal">
 
   uses
 
   uses
 
     MacOSAll;
 
     MacOSAll;
 +
</syntaxhighlight>
  
== Bit Order ==
 
 
''(this paragraph is mainly relevant for users of FPC 2.0.4; as of FPC 2.1.2, the BTst, BSet and BClr routines are available in MacPas mode in FPC)''
 
 
The Macintosh Toolbox functions BitTst, BitSet and BitClr addresses bits form the highest bit in the byte pointed to by the parameter bytePtr. This is in opposition to what one traditionally count as first bit, namely the least significant bit. The reason of this reversed addressing was that these functions could address unlimited bitvectors on the 68K.
 
 
This will cause significant problems if you have used longints to store bit values in CodeWarrior, MPW or Think Pascal variants.  Because the order is backwards, you will have to code against the problem going forth.  The simplest solution is to wrap BitTst, BitSet and BitClr (not having BTst, BSet and BClr in FPC helps here) and flip the order in that function, ala:
 
 
  function BTst(theLong: longint; theBit: integer): boolean;
 
  begin
 
    BTst:= BitTst(theLong, (31 - theBit));
 
  end;  { BTst }
 
 
Subtracting the bit from 31 inverts the order automatically for you (0 becomes 31, 31 becomes 0, etc.)
 
  
 
== Ordinal sizes ==
 
== Ordinal sizes ==
Line 46: Line 32:
 
If you want to convert on the fly, in your structures, replace Style with Byte, then do a conversion in code.
 
If you want to convert on the fly, in your structures, replace Style with Byte, then do a conversion in code.
  
 +
<syntaxhighlight lang="pascal">
 
   function ByteToStyle(byteStyle: byte): Style;
 
   function ByteToStyle(byteStyle: byte): Style;
 
    
 
    
Line 59: Line 46:
 
     ByteToStyle:= returnValue;
 
     ByteToStyle:= returnValue;
 
   end;  { ByteToStyle }
 
   end;  { ByteToStyle }
 +
</syntaxhighlight>
  
 
FPC 2.2.2 and later support packing sets to smaller sizes, by using the {$packset 1} directive. Note however that the set format is considered opaque (i.e., they're not guaranteed to have any particular internal layout), and that the internal format differs between little and big endian systems.
 
FPC 2.2.2 and later support packing sets to smaller sizes, by using the {$packset 1} directive. Note however that the set format is considered opaque (i.e., they're not guaranteed to have any particular internal layout), and that the internal format differs between little and big endian systems.
Line 66: Line 54:
 
CodeWarrior provided built in functions for stripping the Hi and Lo words from a longint.  Although most uses of this have been deprecated over the years (like menu commands,) you may still need the functions for old code.  Here are substitutions:
 
CodeWarrior provided built in functions for stripping the Hi and Lo words from a longint.  Although most uses of this have been deprecated over the years (like menu commands,) you may still need the functions for old code.  Here are substitutions:
  
 +
<syntaxhighlight lang="pascal">
 
   function HiWrd(aLong: cardinal): word;
 
   function HiWrd(aLong: cardinal): word;
 
    
 
    
Line 77: Line 66:
 
     LoWrd:= lo(aLong);
 
     LoWrd:= lo(aLong);
 
   end;  { LoWrd }
 
   end;  { LoWrd }
 +
</syntaxhighlight>
  
 
== UPP differences ==
 
== UPP differences ==
Line 83: Line 73:
  
 
Thus,  
 
Thus,  
 +
<syntaxhighlight lang="pascal">
 
   theRoutine:= NewAEEventHandlerUPP(@HandleODOC); // CW Apple Event Handler
 
   theRoutine:= NewAEEventHandlerUPP(@HandleODOC); // CW Apple Event Handler
 +
</syntaxhighlight>
 
becomes:
 
becomes:
 +
<syntaxhighlight lang="pascal">
 
   theRoutine:= NewAEEventHandlerUPP(HandleODOC);  // FPC Apple Event Handler
 
   theRoutine:= NewAEEventHandlerUPP(HandleODOC);  // FPC Apple Event Handler
 +
</syntaxhighlight>
  
 
== Four Character Codes (FCCs) ==
 
== Four Character Codes (FCCs) ==
Line 91: Line 85:
 
While FPC supports implicitly converting FCCs to integer constants to some extent, it does not do so in all cases. You can however always add an explicit typecast to OSType/Cardinal/LongWord around an FCC to ensure it is interpreted as an integer constant. This construct is endian-safe. For example: Cardinal('APPL').
 
While FPC supports implicitly converting FCCs to integer constants to some extent, it does not do so in all cases. You can however always add an explicit typecast to OSType/Cardinal/LongWord around an FCC to ensure it is interpreted as an integer constant. This construct is endian-safe. For example: Cardinal('APPL').
  
== Helpful Information ==
+
== ''Result'' function result alias ==
 +
 
 +
FPC adds an implicit alias for the function result called ''result''. This means that you cannot use local variables with the same name, as they will conflict with this identifier. The main reason is that using the function name itself is ambiguous in some situations (e.g., when passing it as a parameter to another routine it usually refers to the function result, but it can also mean the function itself as procedural variable).
 +
 
 +
== See also ==
 +
 
 +
* [[macOS_Programming_Tips#Converting_legacy_Pascal_code|Converting legacy Pascal code]].
 +
* [[Mode MacPas]]
  
Useful articles are available on [http://www.mac-how.net/  Mac-How.net]
+
[[Category:Mac OS Classic]]
 +
[[Category:Historical]]

Latest revision as of 02:38, 28 January 2022

Although FPC today supports many Mac Pascal constructs, there are a few of issues one has to be aware of. Tips to make the code work with GPC are also welcome.

Setting the compilation mode

First of all, ensure that the compiler is in Mac Pascal mode. You can do this by either using the -Mmacpas command line switch, or by adding {$mode macpas} at the top of all of your source files.

Unit Names

Unit names in FPC must match the source file name. Unit names must also differ from any object/class names you use. In Metrowerks Pascal it was possible to have the unit name and an object that was subsequently defined in that unit be the same name.

Uses clause

Depending on the compiler you're moving from, you may have a simple or complex uses clause to include all of the toolbox calls. Either way, it can all be replaced with:

  uses
    MacOSAll;


Ordinal sizes

In Traditional Mac Pascal, the types Byte and Char occupies 2 bytes, except in packed records and in arrays. If you need data to be sharable (e g through files), you need to be aware of this. One remedy is to make such records packed. If possible use SignedByte (which actually occupy only one byte) or Integer (or better SInt16 et. al.).

Set sizes (Style in particular)

Sets (eg: mySet = (opt1, opt2, opt3);) may be different sizes if you stored them to disk using CodeWarrior. This is evident with the MacOS type Style:

sizeof(Style) = 1 in CodeWarrior sizeof(Style) = 4 in FPC

If you want to convert on the fly, in your structures, replace Style with Byte, then do a conversion in code.

  function ByteToStyle(byteStyle: byte): Style;
  
  var
    returnValue: Style;
    count: StyleItem;
  
  begin
    returnValue:= [];
    for count:= bold to extend do
      if ((byteStyle shr Ord(count)) and 1) <> 0
        then returnValue:= returnValue + [count];
    ByteToStyle:= returnValue;
  end;  { ByteToStyle }

FPC 2.2.2 and later support packing sets to smaller sizes, by using the {$packset 1} directive. Note however that the set format is considered opaque (i.e., they're not guaranteed to have any particular internal layout), and that the internal format differs between little and big endian systems.

Missing CW Functions

CodeWarrior provided built in functions for stripping the Hi and Lo words from a longint. Although most uses of this have been deprecated over the years (like menu commands,) you may still need the functions for old code. Here are substitutions:

  function HiWrd(aLong: cardinal): word;
  
  begin
    HiWrd:= hi(aLong);
  end;  { HiWrd }

  function LoWrd(aLong: cardinal): word;
  
  begin
    LoWrd:= lo(aLong);
  end;  { LoWrd }

UPP differences

In Codewarrior Pascal, one declared a UPP generically with an "@functionName" parameter. With Carbon, Apple introduced specific UPP creator functions, and with the change to FPC, you simply pass the functionName without the "@" symbol.

Thus,

  theRoutine:= NewAEEventHandlerUPP(@HandleODOC); // CW Apple Event Handler

becomes:

  theRoutine:= NewAEEventHandlerUPP(HandleODOC);  // FPC Apple Event Handler

Four Character Codes (FCCs)

While FPC supports implicitly converting FCCs to integer constants to some extent, it does not do so in all cases. You can however always add an explicit typecast to OSType/Cardinal/LongWord around an FCC to ensure it is interpreted as an integer constant. This construct is endian-safe. For example: Cardinal('APPL').

Result function result alias

FPC adds an implicit alias for the function result called result. This means that you cannot use local variables with the same name, as they will conflict with this identifier. The main reason is that using the function name itself is ambiguous in some situations (e.g., when passing it as a parameter to another routine it usually refers to the function result, but it can also mean the function itself as procedural variable).

See also