Процесс портирования и создания средств разработки программ для KolibriOS продолжается. По наиболее активно используемым языкам программирования мы публикуем статьи. Сегодня мы начинаем рассказывать о языке С--, вокруг которого сложилось активное сообщество в 2000-е годы. Подробности под катом.
Кратко о языке с официального сайта:
C-- — это язык программирования, занимающий промежуточное положение между ассемблером и Cи. Идеально подходит для написания маленьких программ, резидентов (TSR), драйверов, обработчиков прерываний. Для работы с языком C-- необходимо знакомство с ассемблером и Cи. Сейчас С-- умеет генерировать 32-битный код под ДОС и Windows (прим. ред. а также под MenuetOS, KolibriOS).
Автором языка SPHINX C-- является Peter Cellik (CANADA). Последняя авторская версия SPHINX C-- v0.203 от 28.Oct.96. К сожалению автор отказался от дальнейшего развития языка. Сам язык вместе с исходные текстами был объявлен сиротой и отдан никому в никуда. Т.е. делайте что хотите. А почему бы и не сделать? На этой страничке Вы найдете самую последнюю (но уже не авторскую) версию самого языка, библиотеки, примеры программ, описание самого языка и библиотек в формате Notron Guide и много другой полезной информации по языку C--.
После Питера Селлика поддержкой занимался Михаил Шекер, но он прекратил разработку несколько лет назад. В прошлом году исходники были выложены на Github https://github.com/jossk/c--sphinx, но мы узнали об этом только в марте 2016 года.
Было решено рассказать о данном языке по двум причинам:
- На нём написаны несколько популярных программ KolibriOS, среди которых и Eolite — пожалуй, самый используемый файловый менеджер.
- Относительно недавно компилятор данного языка был портирован для KolibriOS (ответ на вопрос о лицензии можно найти тут).
Немного о процессе портирования от GerdtR:
Итак. Сначала я переделал код под gcc. Исходники просто были написаны для Watcom C, ну и пусть не значительная, но несовместимость была. Исправил пару названий переменных(extern в ваткоме можно, видимо), и обозначение 64битных чисел по другому. Потом уже Leency выявил, что gcc-версия совсем не ищет файлы в текущей папке, только в папке с самим экзешником. Когда и это исправил осталось самое сложное: порт для Колибри. Ну так как под С я в КОС не писал, то была стандартная проблема — с кем линковать, да и какие инклудники брать. Выбор не широкий, menuetlibc отпал сразу, как я, покопавшись в исходниках, увидел ещё старые функции обращения к файлам(ф56 вроде). Короче menuetlibc устарел сильно, остался newlib. Долго разбирался, как всё таки на выходе получить kex, а не PE, помог один Makefile, где писалась дополнительно обработка objcopy. Ну а дальше уже дописывание функций, которых нет в newlib(например stat не было, в port.c лежит его реализация). Ну и пара функций преобразования кодировок ANSI->ASCII, а точнее заглушек, потому как русских букв всё равно в строках компилятора нет. Ну и последней проблемой было, да и частично осталось вот это: из-за newlib(скорее всего, больше некому) текущий каталог устанавливается как путь до самого сmm(а обычно /rd/1), потому оказывается, что узнать, где лежит исходник компилятор не может, хоть откуда его запускай. Выход на данный момент — копировать компилятор в папку с исходниками, либо указывать абсолютный путь. Кстати, раньше символ '/' считался началом параметра и абсолютный путь указать было не возможно, сейчас можно. Но с абсолютным путём пока не уверен, что инклудники находить будет. Пока что-то не хочется с этим возиться, да и можно просто написать -IP="/hd1/1/my_source". В теории должно работать, на практике никто не спрашивал. Кстати… указать в форуме что ли, что параметры через '-' указывать теперь… И при запуске без параметров, в той таблице поправить, а то некоторая путаница получается. Ладно, потом как-нибудь. Ну вот в общем, вся история. Самое сложное было — это разобраться, откуда брать либы :) Сам код довольно несложный, не в супер порядке, но особо ковыряться в коде не пришлось
Руководство по языку находится по ссылке http://www.c--sphinx.narod.ru/c--doc.htm. Рассмотрим пример простого приложения для KolibriOS:
#define MEMSIZE 4096*10
#include "../lib/io.h"
#include "../lib/gui.h"
void main()
{
word id;
dword file;
io.dir.load(0,DIR_ONLYREAL);
loop() switch(WaitEvent())
{
case evButton:
id=GetButtonID();
if (id==1) ExitProcess();
break;
case evKey:
GetKeys();
if (key_scancode == SCAN_CODE_ESC ) ExitProcess();
break;
case evReDraw:
draw_window();
break;
}
}
void draw_window()
{
proc_info Form;
int i;
DefineAndDrawWindow(215,100,350,300,0x34,0xFFFFFF,"Window header");
GetProcessInfo(#Form, SelfInfo);
for (i=0; i<io.dir.count; i++)
{
WriteText(5,i*8+3,0x80,0xFF00FF,io.dir.position(i));
}
DrawCaptButton(100, 10, 100, 22, 22, 0xCCCccc, 0x000000, "Button");
WriteText(100,50,0x80,0,"Textline small");
WriteText(100,70,0x90,0,"Textline big");
DrawBar(100, 110, 100, 100, 0x66AF86);
}
Как видите, данный код почти не отличается от кода на Си, но при этом есть возможность писать спокойно в почти ассемблерном стиле, аналогично написанию оберток для системных функций. Например, функция создания окна:
void DefineAndDrawWindow(dword x, y, size_w, size_h, byte WindowType,dword WindowAreaColor, EDI, ESI)
{
EAX = 12;
EBX = 1;
$int 0x40
$xor EAX,EAX
EBX = x << 16 + size_w;
ECX = y << 16 + size_h;
EDX = WindowType << 24 | WindowAreaColor;
$int 0x40
EAX = 12;
EBX = 2;
$int 0x40
}
Чем же он привлекателен для разработчиков ПО для KolibriOS? Во-первых тем, что начать писать на нём очень легко. Это был единственный язык, не считая FASM, на котором можно было просто начать писать, не заморачиваясь с настройкой кросс-компиляции (сейчас в этом деле Си уже набирает обороты). Во-вторых, для C-- было написано множество библиотек и различных оберток над системными функциями. Среди них собственный набор элементов интерфейса и даже неплохие шрифты:
Вы наверняка зададитесь вопросом: если всё так прекрасно, то в чем же проблема? Почему он не применяется повсеместно, хотя бы в рамках проекта KolibriOS?
Ответ следующий. Несмотря на преимущество в простоте освоения, при его использовании всплывают и недостатки:
- плохая оптимизация результирующего кода;
- практически отсутствуют приоритеты операций (C-- всё считает слева направо, т.е. 2+2*2=8, а не 6);
- самое главное, хоть он и похож на Си, но это другой язык программирования со своей сферой применения. В рамках KolibriOS он наиболее подходит для создания программ с графическим интерфейсом и почти не применяется в системном программировании.