make a directory, 'old' and move the existing sourcefile and executable to it. Also move,
if desired, any .BAK or .LOG files with the same names as the sourcefile (they will be overwritten
by PBCC at compile time). Delete BAPISDK.INI.
use the stub in the BAPI/CC documentation to create a template for your BAPI/CC program, or
copy a pre-existing BAPI/CC program (such as STUB.BAS) to your dev directory and rename
it to the name of the program you're porting. Try and select a template that works
the same way (eg. requires INI file, requires commandline parameter, loads extra
settings from INI modules, etc).
open the new source in PBCC and the old source in an editor or viewer.
get the program header information from the old source and type it into the new source
eg. p.name$, p.copy$ and the initial p. settings (p.needini% etc).
unless they will be useful, delete any existing GLOBAL declarations in the header,
and any existing code in readuserini, from the template. Also remove any program-
specific routines at the end (left behind from the previous program used as a template).
get the program-specific variablenames from readuserini (in the old source) and enter
them as GLOBAL variables at the top of the new source (as per point 8 of the QBASIC -> PBCC porting notes).
These variables are those used by the findsetting function (which
loads settings from the main section of the INI file, not from within modules).
Note: global variables come from:
DIMs and constants in readuserINI
findsetting calls in readuserINI
load module code
code in the main body of the program
get the program-specific arraynames from readuserini (in the old source) and enter
them as GLOBAL arrays at the top of the new source (as per point 7 of the QBASIC -> PBCC porting notes).
These arrays are those used by DIM statements.
This QBASIC code:
DIM rulesetlists$(d.max%), filters$(inielemax%)
GLOBAL rulesetlists$(), filters$()
copy the program-specific variable settings from readuserini (in the old source) and
paste them into readuserini in the new source. eg. mysetting%=10 or readim_e$="setting"
ensure the logic to read INI files and commandlines, and load and check rulesets, if
any, is identical (this usually involves reading each line of the main program loop
and the loadrule and checkrule subroutines, making changes where necessary). Copy-
and-paste any program-specific code from the main loop in the old source to the main
loop in the new source.
copy-and-paste the program-specific portions of "loadrule" (if any) to the new
source. These usually look like this: indextrue$ = inimod$(ourrulenum%, 20). If
extra data is loaded, copy-and-paste the program-specific portions of the extradata
loader into the new source. Get the variable and array names used and declare them
GLOBAL at the top of the new source (as per points 7 and 8 of the QBASIC -> PBCC porting notes).
Note: take care to allow for the fact that BAPI/CC, unlike previous versions, does NOT
strip the leading settingname= from extra settings as they are loaded. The settingname
is provided to the application as well as the setting value, in the same format as the
INI file (eg settingname=settingvalue). This is done so that more than one type of
extradata can be loaded (eg. so that the application can differentiate between them).
check whether loadrule has used any arrays. if so, ensure DIM statements are
placed at the top of the loadrule (or equivalent) routine. copy-and-paste the DIM
statement(s) from readuserini (in the old source) into loadrule in the new source.
loadrule usually uses arrays if "extra" data is being loaded from the INI file.
Otherwise it usually uses only the rulesetlists$() and inimod$() arrays (both of which
are pre-declared global by BAPI/CC).
copy-and-paste the data validation routine (usually "checkrule") from the old
source into the new source. Ensure the variable it uses to inform the rest of the
program that the data is good is GLOBAL. This is usually called ruleok%. The
variable ruleok% is declared global by BAPI/CC for this purpose.
copy-and-paste the main work routine (sometimes known as "munchrule") into the munchrule
section of the new source. copy-and-paste any program-specific subroutines at the
bottom of the new source. This is where the bulk of the program-specific code is
copy the program-specific DIM statements from readuserini (in the old source) and
paste them into each subroutine in the new source that uses them (as per point 7 of the
QBASIC -> PBCC porting notes). Keyword-search the
source for the name of the each array to find each call. PB/CC sometimes gives an 'array not dimensioned' error - sometimes
it doesn't, leaving the problem to be discovered as a GPF at runtime.
close the old source file, ensuring not to save any changes you made. Then, attempt
to build and execute the new source. Check the QBASIC -> PBCC porting notes to
deal with errors. You'll need to SUB the names of each subroutine, change each RETURN to
an END SUB, change each GOSUB to a CALL, type any untyped variables,
remove any fullstops from variablenames (replace with underscores), rename any variablenames
that are now reserved words, rewrite your errorhandlers, and possibly replace your SHELL commands,
and probably some other stuff as well. PBCC will point out each syntax error when you try
to compile. Search-and-replace can be very handy here. A 'duplicate name definition' error is sometimes
because of an incorrect type specifier on a variable - for example mystring$
as a global string, but accidentally referred to it in your code as mystring%.
'SUB expected' usually means a missing END IF, WEND or NEXT.
You'll also need to recode any calls to routines that have been removed or changed, such as
the findfiles subroutine (which no longer exists) - see the BAPI/CC changelog.
Once you get the program to compile, try BAPI/CC's new p_debug% toggle if you have logic issues.
Debug. GPFs at runtime are usually due to an attempt to access an undimensioned array.
A routine that returns no data is possibly suffering from a local variable that
should be declared GLOBAL. Two classes of variables pose what seem to be the trickiest
challenges when porting, as they are buried in the code, and cause all sorts of knock-on
effects when set wrongly.
The first, which might be called the "global variable scoped locally" class, are usually
control variables which are set by a subroutine for use elsewhere in the program.
The second, which might be called the "static variable
scoped locally" class, as it contains variables that are set by a subroutine, for later use
by the SAME subroutine. In QBASIC these variables remain set; in PBCC, they are destroyed
when the subroutine exits. There may be little indication in the code that the variable
is intended to be static.
Watch out for the few changes in the library, including the change to the abort routine
(all detailed in the BAPI/CC changelog).