Problems in user code can be due to one function being declared in
two slightly different ways, so that it looks like two different
functions to Digital Mars C++. For example:
to .RC files.
Problem: Redefinition of default arguments
Borland C++ allows redefinition of default arguments (in violation of
ARM 8.2.6). For example:
int f(int i = 0);
int f(int i = 0); // SC++ gives error
Remove the second default definition. For example:
int f (int i = 0);
int f (int i);
Problem: Automatic enum conversions
Borland C++ provides an option to "treat enums as ints." Digital Mars
C++ does not allow implicit conversions of ints to enums, or implicit
conversion of enums to other enums in C++ compilations. For
example:
enum color (black, red, green, blue);
enum color current_color = NULL; // SC++ error
There are two recommended solutions:
- Change the code to use equivalent values from the enum
in question. For example:
enum color (black, red, green, blue);
enum color current_color = red;
- Cast int values to the enum. For example:
enum colorcurrent_color = (enum color) NULL;
Problem: Undefined escape cequences
Borland C++ ignores undefined escape sequences in strings. For
example, it interprets \U as U. Digital Mars C++ generates an error in
this case.
To avoid the error, remove unnecessary escape characters (\) from
strings.
Problem: Return types for constructors/destructors
Borland C++ allows a return type for constructors and destructors (in
violation of ARM 12.1 and ARM 12.4). Digital Mars C++ does not allow
this. For example:
void A::A() {...} // SC++ generates "illegal constructor
// declaration" error
Remove the return type from the declaration. For example:
A::A() {...}
Problem: Differentiating functions by addressing or calling conventions
Borland C++ differentiates between two functions with the same
name in a class if they have different addressing or calling
conventions. Digital Mars C++ does not. For example:
class x
{
void func();
void __far__ pascal func (); // SC++ generates "function is already
// defined" error
};
The problematic declaration is most likely a mistake; remove the
additional declaration.
Problem: No implicit function declarations for derived classes
Borland C++ allows functions to be defined for a derived class that
were only declared for the base class, not the derived class. For
example:
class A
{ public:
virtual void f() = 0;
};
class B: public A {};
void B::f() // SC++ generates " is
// not a member of " error
{...}
Put explicit declarations for all of a class's functions in
the class declaration. For example:
class B: public A
{
public:
void f();
};
Problem: findfirst() and findnext()
The Borland versions of the functions findfirst() and
findnext() take different parameters from their Digital Mars
counterparts.
Rewrite your code to use the Digital Mars versions of findfirst()
and findnext(), or use _dos_findfirst() and
_dos_findnext(). For information see the Digital Mars C++ Run-
time Library Reference.
Problem: _control87() parameters
Borland C defines various constants for use as parameters to the
_control87() function (MCW_EM, EM_INVALID, EM_DENORMAL,
and so on), whose names differ from their Digital Mars equivalents.
You can form the equivalent Digital Mars C constants by adding an
underscore (_) to the Borland version; for example: _MCW_EM or
_EM_INVALID.
Problem: __DLL__ macro defined for DLL compilations
Borland C defines the macro __DLL__ for DLL compilations;
Digital Mars C does not.
Here are two recommended solutions:
- If you are using the SC command line compiler, add -D
__DLL__ to the command line for all DLL compilations.
- From the IDDE, add __DLL__ to your project's Defines
list box in the IDDE (choose Project-Settings, click the
Build tab, and choose Compiler).
Problem: undefined type dosdate_t
The type dosdate_t declared in Borland C's dos.h file is not
defined in Digital Mars C.
Change all instances of dosdate_t to _dosdate_t.
Problem: no values.h file
Borland C provides a file values.h, which defines various
implementation defined limits (for instance, MAXINT, which
represents the largest int). Digital Mars C does not provide an
equivalent file.
You can use the ANSI standard file limits.h instead. To do this,
you will need to change the names of most of the defined identifiers
(MAXINT is called INT_MAX, for instance).
Problem: Typos in long identifiers
Borland C uses the first 32 characters in identifiers; Digital Mars C uses
the first 254. This can expose typing errors at the ends of long
identifiers. For example:
#define I_am_not_very_happy_monday_morning 1
i = I_am_not_very_happy_monday_mornings;
// BC does not generate an error; SC does
Fix any typing errors as needed.
Problem: _argc and _argv not declared
Borland C declares the variables _argc and _argv in dos.h.
Digital Mars C++ does not.
Add the following declarations as needed:
extern int __cdecl _argc;
extern char ** __cdecl _argv;
Note that these names are not part of the published Digital Mars C/C++
run-time library interface, and are subject to change.
Problem: Invalid bitmap syntax
The resource compiler run from the Borland IDE accepts an alternate
syntax for BITMAPs, where the actual bitmap is specified in the code
rather than in a file. For example:
Example BITMAP
BEGIN
'42 4D 5E 00 ...
Digital Mars's RCC and Microsoft's RC do not accept this syntax. Use
Borland's Resource Workshop to convert the text to a .BMP file and
change the code to:
Example BITMAP .BMP
Problem: Invalid pointer conversions
Borland C allows conversion of different pointer types with only a
warning. Digital Mars C++ does not. For example:
void f()
{ int *p;
char **q;
q = p; // SC generates error "cannot implicitly convert"
Examine your code for correctness, and add explicit casts where
appropriate.
Problem: Names declared in different header files
Some names that are defined in both Digital Mars C++ and Borland
C++ are declared in different header files. An example is the run-time
library function coreleft(), which is declared in stdlib.h
in Digital Mars C++ and alloc.h in Borland C++.
To fix this problem, change the header files that your code includes
as appropriate.
Problem: Automatic definitions
Borland C allows an extern variable to be declared without ever
being explicitly defined. In Digital Mars C++, this results in the error
"symbol undefined:< symbol>" at link time. For example, where the
following is a complete program:
extern int a;
void main() {a = 1;}
Add explicit definitions to your code as required.
Problem: Names referenced in .ASM files
Borland C++ mangles only function names. Digital Mars C++ mangles
both function and variable names. This can cause link errors on
names referenced in .ASM files. For example: extrn _a: word
produces a link error in SC++ because the correct name is ?a@@ 3HA.
There are two recommended solutions:
Problem: Inconsistencies in declarations at link time
Borland C++ only mangles the names of variables slightly. For
example, for function pointers it does not encode the parameters of
the function; Digital Mars C++ does. This can expose inconsistencies
in declarations at link time.
Make declarations consistent where needed.
Problem: Inconsistencies in _pascal declarations at link time
Borland C++ does not encode the _pascal calling convention
modifier into mangled names (except by making the mangling all
lowercase); Digital Mars C++ does. This can expose inconsistencies in
declarations at link time for case-insensitive links.
Make declarations consistent where needed.
Problem: opendir, closedir, etc. not available
The Borland library functions opendir, closedir, readdir, and
rewinddir functions are not available in Digital Mars C++.
Rewrite your code to use _dos_findfirst, _dos_findnext, or
findfirst/ findnext(). For information, see the Digital Mars C++
Run-time Library Reference.
Problem: Linker cannot export names
If the Digital Mars linker cannot find names listed in the project .DEF
file's EXPORT list, one of these issues is the cause:
- Digital Mars C++ and Borland C++ mangle C++ names
differently (see the information on name mangling
above). If this is the problem, you need to disassemble
the object module(s) to see what the names should be in
Digital Mars C++.
- Borland C++ does not mangle variable names (see
"Problem: Inconsistencies in declarations at link time"
above). If this is the problem, add extern "C" to the
appropriate declarations as described above.
- The Borland linker does not complain about nonexistent
names. If this is the problem, delete the nonexistent
names.
Problem: Undefined Borland identifiers in .RC files
Some Borland predefined identifiers, like IDHELP, are undefined
when you compile resources with Digital Mars's RCC.
Borland's resource compiler automatically includes bwcc.h, so you
need to explicitly include bwcc.h in the .RC file.
Problem: BC program does not load after conversion to SC
If this is your problem, you might find that one or more DLLs do not
load, or "undefined dynalink" errors occur.
Make sure that all Digital Mars compiler options match their Borland
equivalents. For example, exports can be uppercase, by ordinal,
export all far, and so on.
Problem: BC program does not run after conversion to SC
If a Borland program compiles but does not run, check that all
Digital Mars compiler options match their Borland equivalents. For
example, Borland's default struct alignment is on byte boundaries,
Digital Mars's is on word boundaries.
Problem: _new_handler is not declared
Borland C++ declares pvf _new_handler in the file new.h.
Digital Mars C++ does not.
Simply add the declaration _PNH _new_handler as needed.
Problem: _new_handler behavior is different
Borland's _new_handler function takes no arguments, and exits
on failure. Digital Mars's _new_handler takes one argument (the
number of bytes to make available) and returns zero on failure.
Simply recode calls to _new_handler as needed.
Problem: "class huge" syntax not supported
Borland C++ allows the keyword huge after class in a class
declaration. Digital Mars C++ does not. For example:
class huge A;
Rewrite any class declarations that use the huge keyword.
Problem: Non-Pascal names not found at DLL load time
Windows cannot find exported names in a DLL if they are lowercase.
Borland's IMPLIB solves this problem by always exporting names in
DLLs by ordinal. Digital Mars's linker does not automatically do this;
therefore, some non _pascal names might not be found when a
DLL is loaded.
Link with these Digital Mars linker options: /XUPPER (Export,
uppercase) and /BYORDINAL (Export by ordinal).
Problem: Can't convert between unsigned char and char
The Borland C++ option -K makes unsigned char and char the
same type.
Try one of these two possible solutions:
- Compile with the Digital Mars C++ compiler option -Ju,
which is similar to Borland's -K option. Note, however,
that -Ju is incompatible with Digital Mars's iostreams
library (as described under "Problem: iostreams library
incompatible with -Ju" above. Do not use -Ju to
compile code that includes iostreams headers.
- Search for and replace all unsigned char and BYTE types
with char, and compile with Digital Mars's -J compiler
option. (This solution is more compatible with Microsoft
C++.)
Tips on porting from previous Digital Mars releases
This section provides tips
on how to solve problems that might
occur when porting code from previous releases of Digital Mars C++ or
Zortech C++. For related information, see Chapter 22, "Switching to
Digital Mars C++."
Problem: asm() function does not compile
Zortech C++ allowed instructions to be assembled from integers
using the asm() pseudo-function. For example:
asm (0x8C, 0x96, 0xCC, 0xFE);
Digital Mars C++ does not provide this function. Therefore, you need
to replace asm() calls with calls to __emit__. For more
information, see. "Chapter 5, "Using Assembly Language Functions."
Problem: ios class not declared in iomanip.h
Previous versions of the iostreams library declared the ios class in
iomanip.h. The current version of iostreams does not.
You need to explicitly include iostream.h.
Problem: Zortech library names are different
Zortech C++ library names specified in makefiles are different from
the corresponding Digital Mars C++ names (ZWL corresponds to SWL,
for example).
Change your makefiles to use the Digital Mars C++ library names. Note
that, since the names of libraries are specified in object files, it may
not be necessary to explicitly specify them in the makefile.
Problem: Compiler control program has a different name
The Zortech C++ compiler control program was ZTC.EXE. The
Digital Mars C++ equivalent is SC.EXE.
Change makefiles, batch files, and so forth to run SC instead of ZTC.
Problem: Missing #endifs generate errors
Zortech C++ allowed #endif directives at the end of files to be
omitted; it interpreted End of File as any number of #endifs.
Digital Mars C++ does not.
Add #endif directives to the ends of files as appropriate.
Problem: __pascal names mangled in C++ files
Zortech C++ did not perform C++ name mangling on __pascal
names. In Digital Mars C++, the __pascal modifier changes the
calling sequence, but does not affect name mangling.
Add the modifier extern "C" to declarations that should not be
mangled. For more information, see Chapter 4, "Mixing Languages."
Problem: Jumps around variable initializations disallowed
Zortech C++ allowed jumps around variable initializations, in
violation of ARM 6.4.2. Digital Mars C++ does not allow this. For
example:
switch (i)
{
int v1 = 2; // error
case 1:
int v2 = 3;
case 2:
if (v2 == 7) // error
...
There are two recommended solutions for this problem:
- Move the variable initialization out of the case statement.
- Add braces around the declaration to restrict the
variable's scope to be within the area that the flow of
control can jump around.
Problem: Differences in mangled names
Zortech C++ code might not link with Digital Mars C++ because .ASM
files reference mangled names. The Digital Mars C++ name mangling
scheme differs from Zortech C++ name mangling.
Use the OBJ2ASM utility to obtain the new mangled names, and
manually edit the assembly language files to use these names. For
information on Digital Mars C++ name mangling, see Chapter 4,
"Mixing Languages." For information on OBJ2ASM, see Chapter 14,
"Using Digital Mars C++ Utilities."
Problem: WEP in user code causes a link error
Digital Mars C++ Version 6 allowed users to specify a WEP function in a
DLL. Digital Mars C++ Version 7 provides a WEP function in the library,
which handles static destructors and other cleanup functions on exit
from the DLL. Thus, WEP functions should not be used if these
function are required.
If a DLL requires special termination procedures, put them in a
function called _WEP. Digital Mars's WEP automatically calls _WEP. An
_WEP function is not required, however.
Problem: Access to protected members not allowed
Zortech C++ allowed access to protected member functions, in
violation of ARM page 253. (Base class members can only be
accessed through a derived class.) For example, the following is an
error in Digital Mars C++:
class A {protected: int x };
class B: public A
{
void f() { x = 10; }
void f1() {A *p = new A; p-> x = 10; } // error
friend void f2(A*);
friend void f3(B*);
};
void f2(A* a) { a->x = 10; } // error
void f3(B* b) { b->x = 10; }
To solve this problem, recode invalid constructs as necessary.
Problem: Mismatches in C++ const functions not allowed
Zortech C++ allowed mismatches in function declarations involving
const-ness. For example, the following constructs, which were valid
in Zortech C++, are invalid in Digital Mars C++:
class A
{ public:
int operator== (A&);
};
class B
{ A a;
int operator==(B& b) const
{
return (a == b.a); // error in DMC++ 7
}
};
In the above example, since B::operator== is const, B::a is
const, but there is no matching function in A. To fix the error, you
need to add the required matching function. To fix the example
code above:
class A
{ public:
int operator==(A&);
int operator==(A&) const;
};
Tips on porting Win16 Code to Win32
This section provides tips on how to solve problems that might
occur when porting 16-bit Windows 3.1 code to a 32-bit Windows
environment. See Chapter 16, "Win32 Programming Guidelines," for
general information on porting 16-bit code to Win32.
Problem: Files not found when porting to Windows NT
Symptoms of this problem include .MAK or .BAT files generating
errors, or programs not finding files.
Windows NT does not run the autoexec.bat file, so your PATH
environment variable (and other environment variables) may not be
set. You need to manually add these values to the Windows NT
Registry.
Problem: 32-bit SmartHeap does not work
In this case, SmartHeap symbols are not found when linking with 32-bit
SmartHeap libraries (specifically SHDW3SMD.LIB).
The version of SHDW3SMD.LIB shipped with SmartHeap is not
usable. To create a usable one, perform this step to create a new
library directly from the SmartHeap DLL:
implib /system shdw3smd.lib sh22w3sd.dll
Problem: Windows 3.1 functions undefined at link time
Some Windows 3.1 routines, such as GetCurrentTask(), are
obsolete for Win32.
You need to reengineer these routines. For information, see
Microsoft Win32 API Programmer's Reference (available as the
online Help file ..\sc\help\vc20bks4.hlp in Digital Mars C++).
Problem: ToolHelp functions undefined at link time
The Windows 3.1 ToolHelp library, which includes functions like
ModuleFindHandle() and StackTraceNext(), is not
available in Win32.
You need to reengineer these routines. For information, see
Microsoft Win32 API Programmer's Reference (available as the
online Help file ..\sc\help\vc20bks4.hlp in Digital Mars C++).
Problem: Exported names not found
If this is a problem, the linker indicates that it cannot export any of
the names in the .DEF file's export list, although the export list
worked for Windows 3.1.
Win32 defines PASCAL, WINAPI, and related functions as
__stdcall; in Windows 3.1 they were defined as __pascal. This
means that all PASCAL/ WINAPI functions now begin with an
underscore (_) and are case-sensitive. Add underscores and change
case in the export list as needed.
Problem: Names in .ASM files not found
If this is a problem, the linker indicates that it cannot fnd PASCAL
names that are declared in .ASM files, although it could for
Windows 3.1.
Win32 defines PASCAL as __stdcall; in Windows 3.1 it was
defined as __pascal. __stdcall functions begin with an
underscore (_) and are case-sensitive. Add underscores and change
case in the assembly language definitions of the affected functions.
Problem: DOS functions undefined in NT compilations
An example would be int86x and its parameter, union REGS,
being undefined in a Windows NT compilation.
Some DOS routines may need to be re-engineered using their
Windows NT equivalents. For information, see Microsoft Win32 API
Programmer's Reference (available as the online Help file
..\sc\help\vc20bks4.hlp in Digital Mars C++).
Problem: "FIXUPP" errors in 32-bit links
In this case, the linker generates an error for every reference to an
external name in the build.
You may be using outdated linker options. The Digital Mars C++ IDDE
uses: /DO/DE/NT/Entry:__DllMainCRTStartup.
Problem: Assembler files don't link in Win32
In this case, assembly language code with .286 or 16-bit segments
may not link.
Recode affected files to remove 16-bit specific features. Note also
that the use of segment registers is different for Win32 compilations.
Problem: 32-bit link errors
In this case, you might need to convert your .DEF file to 32-bit. The
Digital Mars C++ IDDE uses EXETYPE NT, no STUB, CODE SHARED
EXECUTE DATA WRITE, and HEAPSIZE 100000,4096.
Problem: Undefined resource symbols in Win32 links
To solve this problem, compile 32-bit resources for 32-bit links with
the command RCC -32.