15 | 12 | 2017

Приложение 5

1. ВОЗМОЖНОСТИ СИСТЕМЫ РАСШИРЕНИЯ.

Clipper дает возможности для написания функий на других языках
программирования и имеет средства,обеспечивающие для приема и
пересылки параметров в функции данного типа. Важно,что ваши функции
могут быть использованы так же как и стандартные функции Clipperа.
Имеется способность,например выводить на экран результат написанной
вами функции.

MyFunc() -
написанная вами функция (FUNC), возвращающая определенный результат.
variable = MyFunc()
? variable

Система расширения программирования предоставляет способность
использовать различные структуры построения программ, делает систему
открытой для включения дополнительных модулей на других языках
программирования.

Вы можете писать дополнительные функции и отдельные процедуры на
Си или Ассемблере и линковать их затем с клиппер-программами , написанными на
Clipperе. Функции написанные на Си и Ассемблере дадут возможности для
работы не поддерживаемые языком самого Clipperа. Это например работа
со структурой стандартного файла данных DBASE ,обеспечат доступ к
использованию прерываний и функций DOS.

При создании новой функии ей необходимо присвоить собственное
уникальное имя. Необходимо избежать конфликтов связанных с
использование имени уже определенных функций. Имя собственной функции
нужно писать полностью при вызове. Сокращение имени функции до первых
четырех символов аналогично собственно функция (FUNC)м Clipperа не
допускается.

Функции написанные на Си или Ассемблере могут вызываться из
Clipperа без их предварительного обьявления или же могут быть описаны
на этапе компиляции как EXTERNAL(внешние). Файл с описанием новых
функций и с их объявлением необходимо указать при линковке.

!!! Функции, использованные в качестве параметров в командах
Clipperа REPORT, LABEL FORMs и INDEX должны быть обязательно
объявлены как EXTERNAL.




- 310 -


2. СПИСОК СТАНДАРТНЫХ ФУНЦИЙ ОБЕСПЕЧИВАЮЩИХ ИНТЕРФЕЙС с Си и
АССЕМБЛЕРОМ.


Имена функций
Тип данных clipperа Тип данных в С для С для Ассемблера
-----------------------------------------------------------------------------
character char *_parc(int,[int]) _PARC
date char *_pards(int,[int]) _PARDS
logical int _parl(int,[int]) _PARL
numeric int _parni(int,[int]) _PARNI
numeric long _parnl(int,[int]) _PARNL
numeric double _parnd(int,[int]) _PARND


character void _retc(char*) _RETC
date void _retds(char*) _RETDS
logical void _retl(int) _RETL
numeric void _retni(int) _RETNI
numeric void _retnl(long) _RETNL
numeric void _retnd(double) _RETND
(no return value) void _ret() __RET

_parclen(int [,int]) _PARLEN
_parcsiz(int [,int]) _PARCSIZ
_retclen(int) _RETCLEN

-------------------------------------------------------------------------------



3. Интерфейс с языком программирования Си.

Clipper позволяет включать в состав выполняемого файла функции
написанные пользователем на языке Си . Для этой цели служит
специальная интерфейсная система содержащая специальные функции для
передачи и принятия параметров из Си в Clipper и наоборот.
Эти функции помещены в библиотеки Clipperа. При разработке
процедуры на С для программы на Clipperе необходимо включить ,
сделать include файл EXTEND.H . Этот файл содержит объявление
процедур и макроопределения необходимые для включения в состав
выполняемого файла функций написанных на Си.


Пересылка параметров в Си.

Концепция принятая для пересылки формальных параметров в Си
заключается в следующем. Все параметры принимаются через
использование функций типа _par(). Кроме того имеется способность
вызова функий без формальных параметров.


Принятие параметров из Си.

Функции типа _ret() используются для пересылки значений назад в

- 311 -
Clipper.Каждая функция (FUNC) по определению может вернуть только одно
значение. Выбор конкретного типа функций для возвращения зависит от
того какой тип данных вы желаете вернуть в Clipper.


Пример функций на Си.

Для того чтобы переслать вычисленную величину используйте
функцию типа _ret() Однако необходимо помнить что данная функия сама
не возвращает управления Clipperу.
Вот типичный пример использования в Clipperе функции написанной
на Си. Имя функции должно предваряться зарезервированным словом
CLIPPER.

CLIPPER <имя функции> ()

/* список формальных параметров для Си */

{ <объявление локальных переменных>

if (<есть пересланный параметр>)

{
<сегмент для выполнения с пересланным параметром>
}
else
{
<сегмент для выполнения без параметра>
}
return;
}

Вызов функции на Си из Clipperа

Declare arr[3]
arr[1] = "Devorah"
arr[2] = 456.56
arr[3] = ctod("09/01/88")
Arrfunc(arr)

Описание на Си вызываемой функции:

# include "extend.h" /* включение описания EXTEND SYSTEM */
# include "stdio.h" /* стандартная библиотека ввода вывода */
# include "math.h" /* стандартная математическая библиотека */

CLIPPER arrfunc() /* объявление функции используемой в Clipperе */

{ int i;

for ( i=1; i <= 3; ++x)

{
/* string variables */
if (_parinfa(1, x) == CHARACTER)
{
cprintf("%s\n", _parc(1, x));

- 312 -
}

/* integer or floating point */
if (_parinfa(1,X) == NUMERIC)
{
cprintf("%f\n", _parnd(1, x));
}
else
/* dates */
if (_parinfa(1, x) == DATE)
{
cprintf("%s\n", _pards(1, i));
}
}
_ret();
}

Функция cprintf() используется для вывода результатов обработки
на экран.


Компиляция и линковка программ на Си.

При включении в clipper функции на Си используйте компилятор
Микрософт Си версия 5.0.


Командная строка:

CL /c /AL /ZL /Oalt /FPa /Gs filename.c

где

CL - вызов команды компилятора
/c - компиляция без линковки
/AL - компиляция под Large модель С
/ZL - удалить установленный поиск в библиотеках из объектного файла
/Oalt - включить контроль по оптимизации
где
a=проверка областей
l=возможна петлевая оптимизация
t=увеличение скорости выполнения
/FPa - включение библиотек по операциям над числами с плавающей запятой
/Gs - перемещения процедур вызова в подпрограмму проверки стека.

Установленные Макроопределения.

Для упрощения синтаксиса и улучшения возможности чтения файла
Extend.h определяется несколько параметров для проверки передаваемых
в функции величин и их типов.
Далее приводится список имен которые используются для этой цели.

определены в Extend.h.

Tип Значение
-------------------------
не определено = UNDEF

- 313 -
стринговая = CHARACTER
числовая = NUMERIC
логическая = LOGICAL
дата = DATE
по адресу = MPTR/* определена по типу указателя */
мемо = MEMO
массив = ARRAY


Определены в интерфейсе Си

EXTEND.H Macro Определены как
-------------------------------
PCOUNT (_parinfo(0))
ISCHAR(order) (_parinfo(order) & CHARACTER)
ISNUM(order) (_parinfo(order) & NUMERIC)
ISLOG(order) (_parinfo(order) & LOGICAL)
ISDATE(order) (_parinfo(order) & DATE)
ISMEMO(order) (_parinfo(order) & MEMO)
ISBYREF(order) (_parinfo(order) & MPTR)
ISARRAY(order) (_parinfo(order) & ARRAY)
ALENGTH(order) (_parinfa(order, 0))

Для определения типа пересланных параметров и их количества вы
можете использовать макровеличину PCOUNT и любую из перечисленных
макровеличин с именем IS... . Эти величины помогут определить и
отконтролировать процесс пересылки параметров.Передаваемые параметры
могут также быть разных типов.

Reference - Extend System C Interface Functions
-----------------------------------------------

_exmback() освобождает занятую память

Написание:

#include <extend.h>

void *_exmback(pointer, bytes)

unsigned char *pointer; Указатель установленный _exmgrab()
unsigned int bytes; Размер определенный _exmgrab()

Описание:

_exmback() освобождает память занятую с помощью _exmgrab().
Поинтер и размер освобождаемой зоны задаются как параметр
функции _exmgrab.
Никакая величина не возвращается.

Пример:

size = 512
buff = _exmgrab(size) /* занятие памяти */
if (buff) /* если логический 0 */
check = TRUE;
.

- 314 -
.
.
if (check)
_exmback(buff, size); /* освобождение памяти */



_exmgrab() Занятие памяти

Написание:

#include <extend.h>

unsigned char *_exmgrab(bytes)

unsigned int bytes; Требуемый размер памяти для занятия

Описание :



_exmgrab() занимает память (размер определен в байта). Если
процесс завершен успешно, функция (FUNC) возвращает поинтер в указанную
область памяти; в противоположном случае, поинтер не изменяется.

Пример:

size = 512
buff = _exmgrab(size) /* Занять память */
if (buff) /* если не логический 0 */
check = TRUE;



_parc() Передает в Си из Clipperа стринговую величину.

Написание:

#include <extend.h>

char *_parc(order, index)

int order; Положение в списке передаваемых параметров
int index; Номер элемента массива

Описание:

_parc() используется для принятия текстовых переменных в Си из
Clipperа. Пересылается копия массива символов.




_parclen() Вычисляет длину переданного стринга

Написание:


- 315 -
#include <extend.h>

int _parclen(order, index)

int order; Номер в списке переданных параметров
int index; номер элемента массива

Описание:

_parclen() определяет длину пересланного стринга.
Вычисляет длину стринга со вставленными CHR(0) в нем

Дает длину стринга без подсчета нулевы окончаний.





_parcsiz() Определяет количество байт в стринге

Написание:



#include <extend.h>

int _parcsiz(order, index)

int order; Номер в списке переданных параметров
int index; Номер элемента массива

Описание:

_ parcsiz() возвращает число байт в памяти занимаемых данным
стрингом, включая завершающий символ.Важно что _parsize() возвращает
0 если работает не со стринговыми переменными а с постояннаями, т.е.
DO <процесс> WITH "ABC" возвратит 0.


_pards() Пересылает clipperную переменную типа дата

Написание:

#include <extend.h>

char *_pards(order, index)

int order; Номер в списке переданных параметров
int index; Номер элемента массива

Описание:

_pards() передает дату из Clipperа в Си в стринговом формате
YYYYMMDD YYYY-год, MM - месяц, DD-день. Важно что в стеке в каждый
момент времени можно передать только один параметр типа дата.



- 316 -

_parinfa() Проверка типов элементов массива

Написание:

#include <extend.h>

int _parinfa(order, index)

int order; Номер передаваемого элемента в списке
int index; Номер элемента массива

Описание:

_parinfa() возвращает тип элемента массива который передается в
Си. Вообще массивы Clipperа могут содержать смешанные элементы,
вследствие этого необходимо проверить тип элемента перед его
использованием. _parinfa(<n>, 0) возвращает число элементов массива.


Пример:

Следующий пример реализует задачу передачи массива из Clipperа в
Си и вывод их содержимого на экран в соответствии с типом элемента и
его размером.

В Clipperе:

DECLARE array[2]
array[1] = "Devorah"
array[2] = 456.56
ArrFunc(array)

В Си:

for (x = 1; x <= _parinfa(1, 0); ++x)

{ /* текстовая переменная */
if (_parinfa(1, x) == CHARACTER)
{
cprintf("%s\n", _parc(1, x));
}

/* целое число или число с плавающей запятой */
if (_parinfa(1, x) == NUMERIC)
{
cprintf("%f\n", _parnd(1, x));
}
}



_parinfo() Проверка типов пересланных параметров

Написание:

#include <extend.h>

- 317 -

int _parinfo(order)

int order; Номер элемента в списке


Описание:

_parinfo() использовать при проверке типа параметра.
_parinfo(0) возвратит число пересланных параметров и
_parinfo(<n>) возвратит тип параметра <n> где <n> есть позиция
параметра в списке. Возвращаются следующие типы элементов.
/* значения возвращаемые _parinfo определенные в extend.h*/
#define UNDEF 0
#define CHARACTER 1
#define NUMERIC 2
#define LOGICAL 4
#define DATE 8
#define ALIAS 16
#define MPTR 32
#define MEMO 65
#define WORD 128
#define ARRAY 512

Пример:

Следующая пользовательская функция (FUNC) на Си принимает 4 параметра
из clipperа ,тип текстовый , тип числовой, логический тип,тип дата
Параметры принимаются в преопределенные величины в Си.


CLIPPER cfunc() /* нет списка параметров*/
{
char *parm1;
double parm2;
int parm3; /* логический объявлен как целый */
char *parm4; /* дата объявлена как текст в формате (YYYYMMDD) */

if (PCOUNT == 4 && ISCHAR(1) && ISNUM(2) && ISLOG(3) && ISDATE(4))

{
<подклиппер-программа для выполнения если все верно>
}
else
{
<подклиппер-программа выполнения если есть ошибки>
}

}



_parl() Пересылка логической величины из Clipperа в Си и
преобразование ее в целое

Написание:
#include <extend.h>

- 318 -

int _parl(order, index)

int order; Номер в списке параметров
int index; Номер элемента массива

Описание:
_parl() передает логический параметр из clipperа и
преобразовывает его в целое число где (1 = .T. и 0 = .F.).

_parnd() Пересылка с преобразованием числового в число с двойной точностью

Написание:
#include <extend.h>
double _parnd(order, index)
int order; Номер в списке параметров
int index; Номер элемента массива

Описание:
_parnd() пересылает числовую величину и преобразовывает ее в
число с двойной точностью.


_parni() Пересылка числа с преобразованием в целое

Написание:
#include <extend.h>
int _parni(order, index)

int order; Место в списке формальных параметров
int index; Номер элемента массива

Описание:
_parni() принимает числовую величину из clipperа и
преобразовывает ее в целое.


_parnl() Пересылает числовую величину преобразовывая ее в длинное целое

Написание:
#include <extend.h>
long _parnl(order, index)

int order; Место в списке формальных параметров
int index; Номер элемента массива

Описание:
_parnl() принимает числовой параметр из clipperа преобразуя ее в
длинное целое.


_ret() Возвращает величину в Clipper

Написание:
#include <extend.h>
void _ret(void)


- 319 -
Описание:
_ret() не имеет возвращаемой величины. Дает способность
использовать для вызова функций на Си из clipperа через команду DO
как процедуру Clipperа

_retc() Возвращает стринг в Clipper

Написание:
#include <extend.h>
void _retc(string)
char *string; Указатель на возвращаемый стринг

Описание:
_retc() возвращает из Си символьную строку в Clipper для
дальнейшей обработки ее в clipperе.


_retclen() Пересылает вычисленную длину строки символов в Си


Написание:

#include <extend.h>
void _retclen(string, int)
char *string; Строка символов для передачи
int int; Начальная позиция в строке для подсчета

Описание:
_retclen() возвращает длину стринга включая внесенные в стринг
символы CHR(0)s.


_retds() Пересылает стринг в Clipper в формате даты

Написание:
#include <extend.h>
void _retds(string)
char *string; Стринг типа дата в формате (YYYYMMDD)

Описание:
_retds() пересылка стринговой сткоки с последующем
преобразованием в тип дата в формате YYYYMMDD.


_retl() Пересылка целого с преобразованием в логический тип

Написание:
#include <extend.h>
void _retl(flag)
int flag; Логическая величина

Описание:
_retl() пересылает целое из Си в clipper как логическую
величину, где 1 истина (.T.) и 0 ложь (.F.).

_retnd() Пересылка числа с двойной точностью с преобразованием в
числовой тип

- 320 -

Написание:
#include <extend.h>
void _retnd(x);
double x; Числовое выражение

Описание:
_retnd() пересылает число с двойной точностью преобразуя его в
числовой тип.


_retni() Пересылка целого с преобразованием в числовой тип

Написание:
#include <extend.h>
void _retni(n)
int n; Числовое выражение

Описание:
_retni() пересылает целое в clipper преобразуя его в формат
числа clipperа.



_retnl() пересылает длинное челое в clipper

Написание:
#include <extend.h>
void _retnl(n)
long n; Длинное целое

Описание:
_retnl() пересылает длинное целое преобразуя его в числовой формат
clipperа.




Интерфейс с языком Ассемблера
-----------------------------

Так же, как и в случае с Си ,когда расширенная система дает
использовать возможности языка высокого уровня, имеется и способность
поддерживать функции написанные на языке Ассемблера. Как и в первом
случае имеется способность обеспечить доступ к списку параметров для
их передачи и возвращения их обратно между clipperом и ассемблером.
Однако в данном случае имеется различие в методе доступа к списку
параметров. Здесь при передаче параметров необходимо манипулировать
стеком куда clipper помещает свои параметры. Для облегчения и
рационализации процесса использованы две макроустановки включенные в
файлы с именами (EXTENDA.MAC и EXTENDA.INC). EXTENDA.MAC поддерживает
более ранние версии clipperа и обеспечивает для настоящей версии
способность использования ранее написанных ассемблерных программ
используемых в версии Осень '86. EXTENDA.INC новая разработка
созданная для использования с версией Лето '87 и Microsoft MASM
версия 5.0.


- 321 -
Пересылка параметров

Следующие функции служат для передачи параметров и
преобразования их из формата clipperа. Когда вы производите вызов
функции типа _PAR, необходимо выполнить следующие действия

поместить число параметров для обеспечения доступа
в регистр

задействовать регистр

вызвать соответствующюю _PAR функцию для типа данных
записанного параметра

если параметр принят из регистра ,очистите его записав
величину или используя поинтер

восстановите стек

Необходимо при этом помнить что clipper написан на Си и все
параметры пересылаются как типы данных в Си.


Простейшие процедуры на Ассемблере.

При использовании переслки данных из clipperа в Ассемблер ,
используя Extend Систему помните о соблюдении следующих правил.

Объявите вашу процедуру PUBLIC.

Объявите используемые функции в ассемблере EXTRN
и FAR или включите EXTENDA.INC который проведет
это объявление.

Если используется собственный сегмент данных - объедините
его вместе с сегментом clipperа используя DGROUP.Или же DS
должен указывать на DGROUP до вызова всяких функций.


Назовите ваши сегменты данных как DATA для версии осень'86 и
_DATA для версии лето'87.

Классифицируйте кодовый сегмент как PROG для версии 86 и
CODE для версии 87.

Если нет необходимости возвращать величину в clipper вызовите
__RET до вашей процедуре на ассемблере ENDS.


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

PUBLIC <имя функции>


;
EXTRN <имя фунции из extend систем>:FAR

- 322 -
;
DGROUP GROUP <сегмент данных>
<сегмент данных> SEGMENT PUBLIC '_DATA'
;
; <объявление данных>
;
<конец сегмента данных> ENDS
;
;
<кодовый сегмент> SEGMENT 'CODE'
ASSUME cs:<кодовый сегмент>, ds:DGROUP

<имя функции> PROC FAR
push bp ; сохранить регистры
mov bp,sp
push ds
push es
push si
push di

< ваш текст начинается отсюда >

pop di ; восстановление регистров
pop si
pop es
pop ds
pop bp
<имя функции> ENDP ; конец процедуры

<кодовый сегмент> ENDS ; конец кодового сегмента
END


Пример:
Следующая процедура на ассемблере выполняет функцию по очистке
части экрана

На clipperе :

Clearit(10, 10, 20, 60)

На ассемблере:

PUBLIC Clearit ; Объявлена публичной
;
EXTRN __PARNI:FAR ; Объявление функции
EXTRN __RET:FAR ; объявлена как внешняя
;
DGROUP GROUP DATASG ; Соединение вашего собственного сегмента
; с сегментом clipperа
DATASG SEGMENT '_DATA' ; Начало сегмента данных

top DB 0
left DB 0
bottom DB 0



- 323 -
right DB 0

DATASG ENDS ; конец сегмента данных
;
;
_PROG segment 'CODE' ; начало кодового сегмента
ASSUME cs:_PROG,ds:DGROUP
;
;
CLEARIT PROC FAR ; начало процесса.

push bp ; запомнить адрес возврата
mov bp,sp

push ds ; сохранить регистры
push es
push si
push di

mov ax,1 ; записать параметров
push ax ; поместиь в стек
call __PARNI ; везов clipperа
add sp,2 ; восстановить стек
mov top, al ; принять параметр в вершину стека

mov ax,2 ; Повторить процесс для следующего параметра
push ax
call __PARNI
add sp,2
mov left, al ; принять в левую часть

mov ax,3 ; повторить процесс для следующего параметра.
push ax
call __PARNI
add sp,2
mov BOTTOM,al ; Принять дно стека

mov ax,4 ; Повторить процесс для следующего параметра
push ax
call __PARNI
add sp,2
mov right,al ; записать в правую часть

mov ch,top ; Поместиь координаты в CX:DX.
mov cl,left
mov dh,bottom
mov dl,right

mov ax,0600h ; Вызвать прокрутку экрана.
mov bh,07 ; Установить нормальные атрибуты.
int 10h ; Вызвать видео прерывание.
pop di
pop si
pop es ; Восстановить содержимое регистров
plt;кодовый сегментbr /op ds
pop bp


- 324 -


call __RET ; Возврат в clipper.

ret ; выход из процесса.
CLEARIT ENDP ; конец процесса.
_prog ENDS
END

Язык ассемблера обеспечивает доступ на самом низком уровне для
программного обесчение и аппаратной части. Все ассемблерные функции
требуют чтобы вы запоминали содержимое регистров до вызова функции.
После вызова любой ассемблерной функции необходимо восстановить
содержимое стека используя для этого процесса стек поинтер (SP).
Ошибка или неудача восстановления может вызвать прерывание в работе
системы.


Мароопределения для языка ассемблера
------------------------------------

Макро в ассемблере служат как имитаторы функций типа
макроподстановок в clipperе.
В clipperе вы можете использовать макроопределения для выражений
и литерных констант. В ассемблере эти понятия гораздо шире. Вы можете
использовать макроопределения для целых блоков программы. Когда
Ассемблер встречает ссылки на макро в процессе работы, он подставляет
тест указанный для макроподстановки или текст описания параметра с
определенной для параметра информацией.

Макроподстановки могут быть описаны используя включения
отдельных файлов. Эти файлы наиболее удобны для помещения в них
макроопределений так как это дает способность делить тексты программ.

EXTENDA.MAC

EXTENDA.MAC для настоящей версии способность работать с ранее
использованными ассемблерными процедурами для ранних версий clipperа
и использует прежний текст.

Внимание: EXTENDA.MAC макроопределение не производит
автоматического запоминания регистров. Однако имеется способность
запомнить содержание регистров до вызова.

Файл EXTENDA.MAC содержит следующие макроопределения.

Макро Функцияn
------------------------------------------
GET_PCOUNT Число пересланных параметров
GET_PTYPE Тип пересланного параметра
GET_CHAR Адрес для стринга в DX:AX
GET_INT Целое в AX
GET_LONG длинное целое в DX:AX
GET_DBL Двойное целое в AX:BX:CX:DX
GET_DATESTR Адрес для стринга данных в DX:AX
GET_LOGICAL Логическое в AX
RET_CHAR возвратить символ в

- 325 -
RET_INT Возвратить целое


RET_LONG Возвратить длинное целое
RET_DBL Возвратить цисло с двойной точностью
RET_DATESTR Возвратить стринг как дату
RET_LOGICAL Возвратить логическую величину



EXTENDA.INC

Новая система разработана для упрощения использования ассемблера
в clipperе и клиппер-программах clipperа.Эти макроопределения требуют
совместимости с Microsoft MASM 5.0. При использовании их поместите
следующие указания в заголовки исходных текстов на ассемблере.

INCLUDE EXTENDA.INC

В новой системе функции имеют следующий формат вызова

CLpublic list_of_UDFs

;*******
;
CLfunc тип функции имя функции [список парам.]
CLcode
.
. тело функции
.
CLret возвращаемая величина


;*******
;
; str = CRYPT(str, len)
; зашифровка/расшифровка символьной строки
;
CLfunc char CRYPT <char str, int len>

CLcode
PUSH ES

; проверка на допустимость параметров
CMP PCOUNT, 2
JB CRYPT_RET
TESTNUL str
JZ CRYPT_RET

; параметры доступны к использованию
LES SI, str
MOV BX, 0

CRYPT_LOOP:
CMP BX, len
JE CRYPT_RET
NOT BYTE PTR ES:[BX + SI]

- 326 -
INC BX
JMP CRYPT_LOOP



CRYPT_RET:
POP ES
CLret str

Скобки типа <> необходимы в MASM.

Основные 4 макроопределения - СLpublic, CLfunc, CLcode, CLret

В файле есть значительное количество других,но именно эти четыре
дают минимальное представление о начале работы с языком ассемблера и
дают ясное представление о концепции в целом.

CLpublic <CRYPT, MYFUNC, YOURFUNC, THISFUNC, THATFUNC>

Каждая функция (FUNC) использованная в clipperе должна быть объявлена
как публичная. Имена функций написаны заглавными буквами и разделены
запятыми.

CLfunc char CRYPT <char str, int len>

Это объявление функции. Этим макросистеме сообщается о
возвращаемой величине ,ее имя , тип и список параметров. Каждый
параметр объвлен как параметр обычного типа .Однако при отсутствии
параметров список можно опустить.

CLcode

Это описание выделено в отдельную главу т.к. некоторые
используемые макроопределения позволяют или требуют вызова между
описанием функции и началом самой функции. Текст для установки
функции помещается здесь. Все необходимое для обеспечения интерфейса
включая принятие параметров и одновременно проверка типов пересланных
параметров производится с помощью макро.Когда текст программы
запускается на выполнение записывается величина PCOUNT (Для clipperа
параметр COUNT). При передачи неверных типов данных параметры и
значения устанавливаются в нуль. Макрокоманда TESTNUL должна
применятся для выявления всех нулевых параметров и всегда должны
применятся для выявления нулевого поинтера.

CLret str

Эта макрокоманда содержит способность для возврата величины в
Clipper. Производит проверку типа возвращаемой величины основываясь
на ее объявлении записанном в макрокоманде CLfunc. Если функция (FUNC)
объявлена как тип "int," то возвращаемая величина может быть помещена
в любой 16 разрядный регистр (т.e. "CLret CX"), или в любую
переменную типа "int". Обычно функция (FUNC) объявленая как тип "char" будет
возвращать указатель на строку символов. В этом случае результат
помеается в любой из 2 16 разряд. регистров (т.e. "CLret BX DX"), или
в любую переменную типа "char". Все функции объявленные как "void" не
возвращают значение ,макрокоманда CLret может быть вызвана но
значение возвращено не будет.

- 327 -

Все исходные тексты ассемблерных макрокоманд помещены в пакете с
подробным описанием. Файл EXAMPLEA.ASM содержит именно текст
программ.



Ссылки файл - EXTENDA.INC
-----------------------

CLpublic <FUNC1, FUNC2, ...>

Объявление одной или нескольких функций публичными.Все функции
вызываемые из clipperа должны быть объявлены как публичные. Имена
функций должны быть написаны заглавными буквами.


CLfunc ftype NAME <ptype p1, ptype p2, ...>

Объявление функции. Имя заглавными буквами. Тип функции
определяет какого типа величину возвражщать в clipper при вызове
макрокоманды CLret. Возможный тип функций :char, int, long, double,
log, date, и void. Тип void указан для функций не возвращающих
величины в clipper. Типы параметров аналогичны за исключением типа
void.


CLcode

Эта макрокоманда должна быть вызвана перед телом функции. Во
время выполнения, в PCOUNT записывается число принятых параметров.
Нераспознанные величины и ошибочный тип параметра принимаются как 0.

CLret r

Проверка типа параметра в соответствии с его объявлением в
описании функции(CLfunc). Дает вожможность возвращать любые типы
переменных корректного типа в один или br /два шестнадцатиразрядных
регистра в зависимости от типа параметра в описании функции. Не
используется если выбран тип void.

PCOUNT

Устанавливает с помощью CLcode количество принятых параметров.
Величина занесенная в PCOUNT может быть доступна из любого места
функции.

TESTNUL переменная

Устанавливает код ошибки если переменная передана неверно.
Используется для сравнения типов пересланных и принятых переменных.

CODESEG имя сегмента

Есть первый сегмент с программой имя_файла_TEXT,где имя файла
прямое имя файла с текстом. В этой макрокоманде изменение текущего
имени происходит по умолчанию,причем кодовый сегмент должен быть

- 328 -
объявлен взамен в виде имя сегмента_TEXT. Эту макрокоманду можно
использовать в любом месте после того как объявлен начальный сегмент
программы (с использованием CLfunc или WORKFUNCS).

DATASEG имя сегмента

После вызова сегмента с программой (СODESEG) ожидает объявления


сегмента с данными. Начальный кодовый сегмент имеет имя _DATA. В
отличиеот кодового сегмента сегмент с данными не изменяется
автоматически. Вызывать макро можно и после объявления статических
данных, но в любом случае опция DATASEG должна быть вызвана до вызова
макро CLstatic. Параметр имя сегмента не обязателен.


CLstatic <stype v1 i1, stype v2 i2, ...>

Объявление статических данных где v-переменная а i-велечина для
строки ее в v. Возможны следующие типы статических данных byte, len,
int, log, long, double, cptr, и string. Некоторые из этих типов и их
назначение будут понятны позднее.

Len используется для определение длины сегмента данных между
текущим адресом и i, где i ранее определенная метка. Для примера:

CLstatic <byte msg1 "Это текст...">
CLstatic <len msglen1 msg1>
CLstatic <byte msg2 "Это только текст.">
CLstatic <len msglen2 msg2, len msglen3 msg1>

Этим определены следующие величины:

msglen1 = размер msg1
msglen2 = размер msg2
msglen3 = msglen1 + msglen2.

Сptr служит для однозначного обозначения символов v_OFF и v_SEG
Эти символы обеспечивают доступ к нескольким сегментам или к
некоторой части адреса указателя. Статический поинтер может быть
инициализирован во время ассемблирования как указатель на постоянные
данные.

Тип string аналочичен типу byte и к конец его добавляется
нулевой байт.


CLlocal <ltype l1, ltype l2, ...>

Объявляется как автоматическая (относительно стека) данные. Эта
макро подстановка может применятся только между CLfunc и CLcode.
Данные объявленные в списке могут быть типа char, int, long, double,
log, и date.


CLextern <xtype x1, xtype x2, ...>


- 329 -
Объявляет внешние сегменты программ и данные.Вожможные внешние
типы (xtype) byte, int, log, long, double, cptr, и far. Far это тип
данных используемый для функций объявленных внешними. Cptr использует
для доступа к ним внешние указатели в форме segment:offset.


CLlabel <ltype l1, ltype l2, ...>

Используется для создания метки для обращения к памяти по


адресу. Возможные типы меток (ltype) byte, int, log, long,
double,cptr, и string. Использование Сptr типа предусматривает что
символы l_OFF и l_SEG будут определены. Эти символы обеспечат доступ
к некоторым сегментам памяти или к нескольким смещениям относительно
базового адреса для указателя.

Cglobal <v1, v2, ...>

Используется для объявления статических данных доступными из
других модулей. Данные объявленные глобальными не могут быть доступны
из программ на clipperе, но имеется способность использовать их из С
и программ на Ассемблере.

Ccall cfunc <param1, param2, ...>

Вызов функции на Си. Макрокоманда содержит все параметры и
управление стеком обеспечивая интерфейс с языком Си. Идентификатор
Param может быть регистром определенной изменяемой или же константой
(заданной величиной). Для примера cfunc объявлена внешней по отношению к
clipperу с помощью CLextern:

Ccall cfunc <str, AX, i, 5>


WORKFUNCS

Начало внутренней процедуры. Эта макрокоманда содержит только
объявления. Внутри блока WORKFUNCS сохраняется стандартный стиль
написания объявлений для ассемблере.Процедура должна быть объявлена
как исключительная и заканчиваться ЕNDP командой.


ENDWORK

Конец внутренней программы. Эта макрокоманда вызывается для
завершения блока WORKFUNCS. Если WORKFUNCS следует после CLfunc,
ENDWORK вызывается автоматически.Однако, если WORKFUNCS является
концом файла программы, ENDWORK должна быть вызвана явно.


SES 16-ый регистр

Соответствует команде LES..,записывает из памяти ES и указанный
регистер из двойного слова,первая половина DWORD в ES,вторая в
указанный регистер. Для примера:
SES DI, pointer_variable

- 330 -

SDS 16-ый регистр

Соответствует команде LDS..,записывает из памяти DS и указанный
регистр из двойного слова,первая половина DWORD в ES,вторая в
указанный регистер. Для примера:

SDS SI, pointer_variable


DOSREQ номер



Вызов DOS прерывания 21H с указанием соответствующего номера
функции DOS. Все необходимые установки,например загрузка регистров
должны быть сделаны предварительно.

$определение постоянные

Аналогично определению величин в Cи #define а также ассемблерной
команде "символ EQU значение".


OFFPART p

Взять первую часть DWORD (segment:offset)(база)


SEGPART p

Взять вторую часть DWORD (segment:offset)(смещение)


LSW n

Взять первое слово DWORD (32 разрядное число)


MSW n

Взять второе слово DWORD (32 разрядное число)



Примеры - EXTEND SYSTEM ASSEMBLY LANGUAGE функции
-----------------------------------------------------

__PARC

Написание:

mov x,<word>
push ax
call __PARC
add p,2


- 331 -
Аргументы:

<word> номер параметра в списке.

Описание:
Записывает стринг из clipperа по адресу DX:AX где:

DX = база
AX = смещение


__PARDS



Написание:
mov x,<word>
push ax
call __PARDS
add p,2

Аргументы:
<word> номер параметра в списке

Описание:
Запись стринга в формате дата из clipperа YYYYMMDD в DX:AX где:

DX = база
AX = смещение


__PARINFO

Написание:
mov x,<word>
push ax
call __PARINFO
add sp,2

Аргументы:
<word> номер параметра в списке.

Описание:

Если параметр <word> =0, __PARINFO запишет число переданных
параметров в AX. Если величина <word> > 0, _PARINFO запишет в AX по
следующей таблице

Тип Значение в AX
----------------------------------
Неопределено 0
Текст 1
Число 2
Логическое 4
Дата 8
По ссылке 32
Мемо 65

- 332 -

Регистры SP, BP, DS, SS, CS и IP должны быть сохранены.


__PARL

Написание:

mov ax,<order>
push ax
call __PARL
add sp,2

; Принятие параметров из массива.
mov ax,<order>


mov bx,<index>
push bx
push ax
call __PARL
add sp,4

Аргументы:
Tип: word <ORDER> номер элемента в списке
Tип: word <INDEX> номер величины в массиве

Описание:

Принимает логическую величину из Clipperа в AX где 1 истина
(.T.) и 0 ложь (.F.).

__PARND

Написание:
mov ax,<order>
push ax
call __PARND
add sp,2

; Принимает числовое как число с двойной точностью
mov ax,<ORDER>
mov bx,<INDEX>
push bx
push ax
call __PARND
add sp,4

Аргументы:
Tип: word <order> номер в списке параметров
Tип: word <index> номер элемента массива

Описание:
Принимает число из clipperа и помещает его как число с двойной
точностью по адресу в DX:AX где:

DX = база

- 333 -
AX = смещение

Для помещения двух чисел в AX:DX:CX:BX следующая реализация

mov ax,<order>
push ax
call __PARND
add sp,2
mov es,dx
mov si,ax
mov ax,es:[si]
mov bx,es:[si + 2]
mov cx,es:[si + 4]
mov dx,es:[si + 6]


__PARNI


Написание:
mov ax,<order>
push ax
call __PARNI
add sp,2
; Принимат число как целое из clipperа
mov ax,<order>
mov bx,<index>
push bx
push ax
call __PARNI
add sp,4
Аргументы:
Тип: word <order> номер параметра в списке.
Тип: word <index> номер элемента массива

Описание:
Принимает число из clipperа и помещает его в AX.


__PARNL

Написание:
mov ax,<ORDER>
push ax
call __PARNL
add sp,2

; Принимает число и преобразует в длинное целое
mov ax,<order>
mov bx,<index>
push bx
push ax
call __PARNL
add sp,4
Аргументы:
Тип: word <ORDER> номер параметра в списке
Тип: word <INDEX> номер элемента массива

- 334 -

Описание:
Принимает число из clipperа преобразовывает его в длинное целое
и помещает значение в DX:AX.


__RET
Написание:
call __RET

Описание:
Вызов процедуры возврата без передачи значения


__RETC
Написание:

mov <регистр1>,<числовое выражение 1>
mov <регистр2>,<числовое выражение 2>


push <регистр1>
push <регистр2>
call __RETC
add sp,4

Аргументы:
<числовое выражение 1> базовый адрес для стринга.
<числовое выражение 2> смещение для стринга.

Описание:
__RETC пересылает назад в clipper текстовую строку через
<регистр 1> и <регистр 2>.


__RETDS
Написание:
mov <регистр1>,<числовое выражение 1>
mov <регистр2>,<числовое выражение 2>
push <регистр1>
push <регистр2>
call __RETDS
add sp,4

Аргументы:
<числовое выражение 1> базовый адрес для стринга в формате дата .
<числовое выражение 2> смещение для стринга в формате дата.

Описание:
__RETDS возвращает в clipper дату в виде текстовой строки в
формате YYYYMMDD.


__RETL
Написание:
mov <регистр1>,<числовое выражение>
push <регистр1>

- 335 -
call __RETNL
add sp,2

Аргумент:
<числовое выражение> возвращаемая числовая величина в clipper
где 0 ложь (.F.) и истина 1 (.T.).

Описание:
Пересылка в clipper слова как логической изменяемой clipperа.


__RETND
Написание:
mov <регистр1>,<числовое выражение 1>
mov <регистр2>,< ? >
mov <регистр3>,< ? >
mov <регистр4>,< ? >
push <регистр1>
push <регистр2>
push <регистр3>
push <регистр4>


call __RETND
add sp,8

Аргумент:
<числовое выражение 1> величина возвращаемая в clipper.

Описание:
__RETND возвращает в clipper число двойной точности
преобразовывая его число формата clipperа.


__RETNI
Написание:
mov <Регистер1>,<числовое выражение 1>
push <регистр1>
call __RETNI
add sp,2

Аргументы:
<числовое выражение 1> целое возвращенное в clipper как числовое.

Описание:
__RETNI возвращает целое из <регистра1> в clipper как числовое.


__RETN
Написание:
mov <регистр1>,<числовое выражение1>
mov <регистр2>,< ? >
push <регистр1>
push <регистр2>
call __RETNL
add sp,4


- 336 -
Аргументы:
<числовое выражение 1> длинное целое возвращаемое в clipper.

Описание:
__RETNL возвращает в clipper длинное целое в clipper как число в
формате clipperа . Длинное целое размещено в <регистре1>:<регистре2>.


ОБЩИЕ ИЗМЕНЕНИЯ ПО СРАВНЕНИЮ С ВЕРСИЕЙ ОСЕНЬ'86
-----------------------------------------------

Эта глава содержит общие изменения и отличие между версией
Осень'86 Clipperа и версией лето'87 для обеих интерфейсных систем как
к Cи так и к языку Ассемблера.

Интерфейс к Cи.

1. Функции на Си используемые в clipperе могут теперь
определяться используя макроподстановку CLIPPER или описанием типа
функции "void pascal." Для примера:

Осень'86:
c_routine() {



}

Лето'87:
CLIPPER c_routine() {

}

2. Функции расширенной системы должны предваряться знаком
подчеркивания (_)- символом. Для примера:

Осень '86:
parni(1)
parinfa(2, 1)
ret()


Лето'87:
_parni(1)
_parinfa(2, 1)
_ret()


Интерфейс к Ассемблеру

1. Ссылки на функции расширенной системы должны предваряться
двойным знаком подчеркивания (__)- символами. Для примера:

Осень'86: call _PARNI
call _PARC
call _RETNI
call _RET

- 337 -

Лето'87: call __PARNI
call __PARC
call __RETNI
call __RET

2. Для некоторых принимающих из clipperа параметры функций типа
__PAR изменены регистры принимающие значения параметров.

__PARC
Осень'86: Принятие параметра в AX:BX (база:смещение) по адресу.
Лето '87: Принятие параметра в DX:AX (база:смещение) по адресу.

__PARNL
Осень'86: Принятие параметра в AX:BX как величину.
Лето '87: Принятие параметра в DX:AX как величину.

__PARND
Осень'86: Принятие параметра в AX:BX:CX:DX как последовательность
величин.
Лето '87: Принятие параметра в DX:AX (база:смещение) как последо-
вательность ссылок на адреса.

__PARDS
Осень'86: Принятие параметра в AX:BX (база:смещение) как послед
овательность ссылок по адресу.
Лето '87: Принятие параметра в DX:AX (база:смещение) как
последовательность ссылок по адресу.


Замечание: Некоторые типы макрокоманд в файле EXTENDA.MAC также
изменены. Если вы делаете INCLUDE этот файл (включаете файл),
пожалуйста проверьте сделанные изменения.