                       СОЗДАНИЕ БИБЛИОТЕК


   Известны два способа создания библиотеки. Оба они будут описаны в следующих
параграфах. Первый из них, метод "а" - быстрый и легкий по исполнению, однако
к собираемым пользовательским программам прилинковываются в том числе и такие
функции, которые не обязательно будут использоваться.
  В отличие от первого, способ "b" реализуется сложнее и требует большего вре-
мени, но получаемые в соответствии с ним пользовательские программы будут со-
держать в себе только те функции, которые заведомо применяются в программе.
Стандартная библиотека компилятора "clib.irl" создается именно по способу "b".


               1. Простой способ создания библиотеки

Рассмотрим пример двух функций "power" и "log2":

int power(x,e)
int x,e;
{
     int y;
     for(y=1; e>0; e--)
           y *= x;
     return(y);
}

int log2(x)
int x;
{
     int y;
     for(y=0; x>1; x>>=1)
           y++;
     return(y);
}

   Если эти функции помещаются в файл с именем XLIB.C, последовательность
создания библиотеки выглядит следующим образом:

        cc1 xlib
        cc2 xlib
        as xlib

   При выполнении этой последовательности будет создана библиотека с именем
XLIB.REL. Ниже приведена команда сборки программы, которая вызывает функции
из этой библиотеки:

        ld prog,xlib,clib/l/gXMAIN

   В этом случае нет необходимости писать ключ /l после имени библиотеки XLIB,
т.к. даже если его написать, тем не менее все функции, входящие в библиотеку
XLIB, будут скомпонованы с программой "prog".

   Здесь будет описан способ включения в библиотеку программ, написанных на
Ассемблере. В качестве примеров взяты функции hex, ror и rol, помещенные в
файл ALIB.ASM:

        public hex_, ror_, rol_
        cseg
hex_:                     ; convert 0..F -> '0'..'F'
        and     0Fh
        add     a,90h
        daa
        adc     a,40h
        daa
        ret

ror_:                     ; ror(c,n) n bit rotate right char
        inc     e
rorl:   dec     e
        ret     z
        rrca
        jp      rorl

rol_:                     ; rol(c,n) n bit rotate left char
        inc     e
roll:   dec     e
        ret     z
        rlca
        jp      roll

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

        as alib.asm

Следующая команда вызывает линковку программы, как и в случае Си-программы:

        ld prog,alib,clib/l/gXMAIN

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


                  2. Создание полной библиотеки

              2.1. Включение Си-программ в библиотеку

   Здесь будет приведен тот же пример, что и выше - включение файла XLIB.C,
содержащего тексты функций POWER и LOG2 в библиотеку.
   Вначале нужно "разделить" файл XLIB.C на составляющие его функции, записав
их в отдельные файлы POWER.C и LOG2.C. Далее необходимо выполнить следующие
команды:

        cc1 power
	cc1 log2
	cc2 power
	cc2 log2
	as power
	as log2
	ol a xlib.irl power log2

При выполнении этой последовательности команд, происходит следующее:

   1. Си-тексты функций транслируются в ассемблерные листинги.
   2. В результате ассемблирования получаем модули с расширением ".rel".
   3. С помощью библиотекаря OL из двух модулей с расширением ".rel"
      создается библиотека XLIB.IRL.

После создания библиотеки XLIB.IRL, файлы POWER.REL и LOG2.REL уже не нужны
и их можно удалить.
Применение библиотеки XLIB.IRL определяется следующей командой:

        ld prog,xlib/l,clib/l/gXMAIN

   После имени библиотеки XLIB нужен ключ /l как указание линкеру подключить
к программе только необходимые ей функции.

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

   Правильный пример:

char islower(c)
char c;
{
   return('a'<=c && c<='z');
}

char toupper(c)
char c;
{
   return(islower(c) ? c-'a'-'A' : c);
}

   В данном примере в библиотеку включается файл X.C, состоящий из двух
функций. В этом случае функция "islower" расположена в файле X.REL перед
функцией "toupper". Поэтому при редактировании связей по ключу /l линкер
не выдаст диагностику об ошибке типа отсутствия определения.

  Но если написать вначале текст функции "toupper", возникает следующий
неправильный пример:

char toupper(c)
char c;
{
   char islower();
   return(islower(c) ? c-'a'-'A' : c);
}

char islower(c)
char c;
{
   return('a'<=c && c<='z');
}

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


            2.2. Создание библиотеки модулей на Ассемблере

   По сравнению с описанием включения в библиотеку, которое было дано в п.1,
здесь, файл ALIB.ASM следует предварительно разделить на следующие три файла
"hex.asm", "ror.asm" и "rol.asm":

HEX.ASM:
        cseg

hex_::  and     0Fh
        add     a,90h
        daa
        adc     a,40h
        daa
        ret


ROR.ASM:
        cseg

ror_::  inc     e
rorl:   dec     e
        ret     z
        rrca
        jp      rorl


ROL.ASM:
        cseg

rol_::  inc     e
roll:   dec     e
        ret     z
        rlca
        jp      roll

   После того, как каждый из них будет ассемблирован и получен файл с расши-
рением ".rel", вызывается библиотекарь OL для создания библиотеки:

        as hex
        as ror
        as rol
        ol a alib.irl hex ror rol

Применение библиотеки ALIB.IRL определяется следующей командой:

        ld prog,alib/l,clib/l/gXMAIN

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