Распечатать страницу

Компиляция исходного текста в Visual FoxPro

« Назад

VFP исполняет объектные файлы, получаемые в результате компиляции исходного кода. Если при запуске программы обнаружится, что файл неоткомпилирован, то VFP выполнит его компиляцию и образует объектный файл с тем же именем, что и исходный, в той же директории, где записан исходный файл. Расширение объектного файла, что видно из табл. 5.3, зависит от вида исходного файла.

Таблица 5.3

Расширения исходных и объектных файлов

Расширение

Вид файла

исходного файла

объектного файла

PRG

FXP

Программа

SPR

SPX

Код формы

MPR

MPX

Код меню

QPR

QPX

Запрос

FMT

PRX

Формат

В процессе компиляции выявляются синтаксические ошибки в исходном файле.

Команда

SET LOGERRORS ON | OFF

определяет, будут ли ошибки компиляции записываться в текстовый файл.

Опции:

ON – (по умолчанию) ошибки компиляции будут записаны в LOG-файле, имеющем расширение ERR. Имя файла совпадает с именем программного файла. Если LOG-файл существует, то будет перезаписан. Если программа компилируется без ошибок, то существующий LOG-файл будет удален.

OFF – LOG-файл с ошибками компиляции создан не будет.

Команды

COMPILE [LABEL | REPORT] FileName | FileSkeleton |
? [ENCRYPT] [NODEBUG] [AS nCodePage]

или

COMPILE [DATABASE | FORM | CLASSLIB] FileName | FileSkeleton |? [ALL]

выполняют компиляцию исходного кода без запуска программы (формы, отчета…).

Опции и параметры:

DATABASE – указывает, что компилируются хранимые процедуры и функции базы данных (расширение DBC). Откомпилированный код сохраняется в дополнительном memo-поле.

FORM – указывает, что компилируемый файл является файлом формы (расширение SCX). Исходный код, имеющийся в среде формы, компилируется и сохраняется в дополнительном memo-поле.

CLASSLIB – указывает, что компилируемый файл является файлом библиотеки классов (расширение VCX). Исходный код библиотеки классов хранится в memo-поле таблицы библиотеки классов. COMPILE CLASSLIB компилирует это memo-поле и сохраняет объектный код в дополнительном memo-поле.

LABEL | REPORT – указывает, что компилируемый файл является файлом этикетки | отчета (расширение LBX | FRX). Исходный код, имеющийся в среде этикетки, компилируется и сохраняется в дополнительном memo-поле.

FileName | FileSkeleton – задает имя компилируемого файла или образец для отбора файлов, содержащий в общем случае символы * и ?. Так, для компиляции всех файлов с программами в текущей директории следует выполнить COMPILE *.PRG

ENCRYPT – задает режим шифрования объектного файла; опция не может быть использована с опциями CLASSLIB, LABEL и REPORT.

NODEBUG – уменьшает размер объектного файла на 2 * nLines байт, где nLines - число строк в исходном коде; опция не может быть использована с опциями CLASSLIB, LABEL и REPORT. При использовании NODEBUG нельзя наблюдать выполнение программы а окне трассировки и использовать MESSAGE(1), чтобы вернуть исходный код строки с ошибкой. На функционировании программы присутствие опции не отражается.

AS nCodePage – задает кодовую страницу, с использованием которой выполняется компиляция программы; опция не может быть использована с опциями CLASSLIB, LABEL и REPORT. Приоритет опции выше установки, заданной командой

SET CPCOMPILE TO [nCodePage]

определяющей кодовую страницу для компилируемых программ.

ALL – обеспечивает компиляцию всех записей всех платформ VFP в таблице формы. При отсутствии опции компилируются записи, отвечающие текущей платформе; употребляется с опцией FORM | CLASSLIB.

Команда

CLEAR PROGRAM

очищает буфер откомпилированных программ.

Во время компиляции могут быть использованы директивы #DEFINE, #UNDEF, #IF ... #ENDIF, #IFDEF | #IFNDEF, #INCLUDE и #INSERT.

Директива

#IF nExpression1 | lExpression1
                   Commands1
        
[#ELIF nExpression2 | lExpression2
                   Commands2
        
...

         #ELIF nExpressionN | lExpressionN
                   CommandsN]

         [#ELSE
                   Commands]
         #ENDIF

включает в компилируемый код первый набор команд, для которого числовое выражение nExpression отлично от нуля или логическое выражение lExpression вычисляется со значением .T. Если условия таковы, что ни один из наборов команд Commands1, Commands2, …, CommandsN не компилируется, и задана команда #ELSE, то следующие за ней команды Commands будут включены в компилируемый код.

Замечание. Нельзя задавать в качестве nExpression | lExpression системные переменные, поскольку они оцениваются на этапе исполнения и не оцениваются на этапе компиляции.

Директива #IF ... #ENDIF позволяет снизить объем компилируемого кода и, следовательно, повысить производительность.

Пример (приводится в справке VFP). В зависимости от значения идентификатора места выбирается вариант компилируемого и, следовательно, исполняемого кода. (Идентификатор места определяет язык, на котором объекты автоматизации обмениваются информацией.)

oleExcel = CreateObject('Excel.Application')

#if Sys(3004) = "1031"

? "Немецкий ID-места"

&& …

oleExcel.Beenden                && Закрываем 'Excel (немецкая команда)

&&

#elif Sys(3004) = "1033"

? "Английский ID-места"

&& …

oleExcel.Quit                      && Закрываем 'Excel (английская команда)

&&

#elif Sys(3004) = "1034"

? "Испанский ID-места"

&& …

&&

#elif Sys(3004) = "1036"

? "Французский ID-места"

&& …

&&

#endif

Директива

#IFDEF ConstantName
                   Commands1
        
[#ELSE

                   Commands2]
         #ENDIF

включает в компилируемый код команды Commands1, если определена константа ConstantName, и не включает – в противном случае. Если константа не определена и задана команда #ELSE, то в компилируемый код включаются команды Commands2.

Директива

#IFNDEF ConstantName
                   Commands1
        
[#ELSE

                   Commands2]
         #ENDIF

включает в компилируемый код команды Commands1, если не определена константа ConstantName, и не включает – в противном случае. Если константа определена и задана команда #ELSE, то в компилируемый код включаются команды Commands2.

Константа ConstantName определяется директивой #DEFINE.

Директивы #IFDEF | #IFNDEF ... #ENDIF могут быть вложенными. Полезны, в частности, на этапе отладки программ.

Пример:

#define SOMEDEFCONST 1

&&

&& Директива #IFDEF ... #ENDIF

#ifdef SOMEDEFCONST

? "#IFDEF: команда компилируется, когда константа SOMEDEFCONST определена"

#else

? "#IFDEF: команда компилируется, когда константа SOMEDEFCONST не определена"

#endif

&&

&& Директива #IFNDEF ... #ENDIF

#ifndef SOMEDEFCONST

? "#IFNDEF: команда компилируется, когда константа SOMEDEFCONST не определена"

#else

? "#IFNDEF: команда компилируется, когда константа SOMEDEFCONST определена"

#endif

Директива

#INCLUDE FileName

предписывает компилятору VFP рассматривать содержимое текстового заголовочного файла FileName как часть программы. Имя файла FileName может содержать путь и должно включать расширение.

Содержимое файла FileName вставляется в программу в процессе компиляции начиная со строки с директивой #INCLUDE.

В заголовочном файле могут присутствовать только директивы #DEFINE, #UNDEF, #IF ... #ENDIF и #INCLUDE. Комментарий и команды VFP, обнаруженные в заголовочном файле, игнорируются.

Число директив #INCLUDE произвольно, и они могут появляться в любом месте программного кода.

Заголовочному файлу обычно дается расширение H, хотя это необязательно.

С VFP поставляется файл Foxpro.h, содержащий многочисленные константы. Вот его фрагмент:

*-- DrawStyle

#DEFINE DRAWSTYLE_SOLID         0 && 0 - Solid

#DEFINE DRAWSTYLE_DASH         1 && 1 - Dash

#DEFINE DRAWSTYLE_DOT  2       && 2 - Dot

#DEFINE DRAWSTYLE_DASH_DOT   3       && 3 - Dash-Dot

#DEFINE DRAWSTYLE_DASH_DOT_DOT  4       && 4 - Dash-Dot-Dot

#DEFINE DRAWSTYLE_INVISIBLE 5 && 5 - Invisible

#DEFINE DRAWSTYLE_INSIDE_SOLID       6       && 6 - Inside Solid

Пример. Создается файл d:\Const.h

&& Заголовочный файл d:\Const.h

#DEFINE ERROR_NODISK 1

#DEFINE ERROR_DISKFULL      2

который затем включается в файл d:\CheckError.prg:

&& Файл d:\CheckError.prg

&&

#include d:\Const.h

&&

procedure CheckError(errCode)

                                            do case

                                            case errCode = ERROR_NODISK

                                               ? "Неверное имя диска!"

                                            case errCode = ERROR_DISKFULL

                                               ? "Нет места на диске!"

                                            otherwise

                                               ? "Неизвестная ошибка!"

                                            endcase

endProc

Примеры обращения к программе d:\CheckError.prg:

do d:\CheckError with 1     && Напечатает: Неверное имя диска!

do d:\CheckError with 4     && Напечатает: Неизвестная ошибка!

Директива

#INSERT FileName

помещает содержимое текстового заголовочного файла FileName в генерируемый код файла меню. Имя файла FileName может содержать путь и должно включать расширение.

В частности, директива #INSERT может быть использована для размещения директив #DEFINE и #UNDEF в начале генерируемого кода меню.

Если файл FileName не может быть найден, то генератор меню проставляет комментарий перед соответствующей директивой; процесс генерации продолжается.

Директива может появляться в любой процедуре меню и в любом ее месте. Число директив #INSERT произвольно.

Пример. Создается короткое (ShortCut) меню ShowInsert.mnx с одноименным пунктом, запускающее приведенную на рис. 5.3 процедуру.

99.1.-Короткое-меню-ShowInsert-и-его-процедура

Рис. 5.3. Короткое меню ShowInsert и его процедура

Файл d:\ArrExtDef.h содержит директивы

#define MAXROWSNUMBER 10

#define MAXCOLSNUMBER 20

а файл d:\ArrExtUnDef.h – директивы

#undef MAXROWSNUMBER

#undef MAXCOLSNUMBER

Генератор меню, формирующий файл ShowInsert.mpr, включит в него в том числе и следующий код:

PROCEDURE _1gh0qvgky

                                            && Inserted from ArrExtDef.h

                                            #define MAXROWSNUMBER 10

                                            #define MAXCOLSNUMBER 20

                                            && End of inserted lines

                                            #ifdef MAXROWSNUMBER

? 'Defined', MAXROWSNUMBER, MAXCOLSNUMBER

                                            #else

                                            ? 'Not defined'

                                            #endif

                                            && Inserted from ArrExtUnDef.h

                                            #undef MAXROWSNUMBER

                                            #undef MAXCOLSNUMBER

                                            && End of inserted lines

Замечание. Меню генерируется в результате выполнения Menu – Generate.