Привет!
Сразу же хочу сказать, что я свои выводы я сделал на основании просмотра одной open-source программы под названием PuTTY. Это виндовый клиент для SSH, Telnet и rlogin. Знаю, что он достаточно популярен.
Просматривая код я ловил себя на мысли, что это гавно лучше переписать чем попытаться понять, как оно работает.
Приведу несколько примеров:
1. Файл ssh.c
В начале файла есть несколько дефайнов:
/* Coroutine mechanics for the sillier bits of the code */
#define crBegin1 static int crLine = 0;
#define crBegin2 switch(crLine) { case 0:;
#define crBegin crBegin1; crBegin2;
#define crFinish(z) } crLine = 0; return (z)
#define crFinishV } crLine = 0; return
#define crReturn(z) \
do {\
crLine=__LINE__; return (z); case __LINE__:;\
} while (0)
#define crReturnV \
do {\
crLine=__LINE__; return; case __LINE__:;\
} while (0)
#define crStop(z) do{ crLine = 0; return (z); }while(0)
#define crStopV do{ crLine = 0; return; }while(0)
#define crWaitUntil(c) do { crReturn(0); } while (!(c))
#define crWaitUntilV(c) do { crReturnV; } while (!(c))
Потом эти дефайны используются в коде следующим образом:
static int ssh1_rdpkt(unsigned char **data, int *datalen)
{
struct rdpkt1_state_tag *st = &rdpkt1_state;
crBegin;
next_packet:
pktin.type = 0;
pktin.length = 0;
for (st->i = st->len = 0; st->i < 4; st->i++) {
while ((*datalen) == 0)
crReturn(4 - st->i);
st->len = (st->len << 8) + **data;
(*data)++, (*datalen)--;
}
...
Т.е., пришли в функцию, что-то сделали, и вышли, сохранив номер строки из которой мы вышли. В следующий раз мы продолжим выполнение с этого же места. Этот код не компилируется в студии если установлен режим сохранения отладочной информации Edit and continue. Выводится ошибка "case label not a constant" или типа того. Меняем эту настройу на что-нибудь другое, и все работает.
Как это поддерживать? Какой смысл в открытости кода, если поддерживать его могут только авторы?
2. В файле window.c приведена функция TranslateKey длиной в 800 строк! Это же убиться можно.
3. Мой любимый пример. Функция term_out из файла terminal.c. Она занимает 1830 строк. Там реализован какой-то офигенный конечный автомат. С какими-то вложенными состояниями и метками case вида:
case 40:
compatibility_level &= TM_VTXXX;
break;
case 41:
compatibility_level = TM_PUTTY;
break;
case 42:
compatibility_level = TM_SCOANSI;
break;
или
case 14:
get_window_pixels(&x, &y);
len = sprintf(buf, "\033[4;%d;%dt", x, y);
ldisc_send(buf, len, 0);
break;
case 18:
len = sprintf(buf, "\033[8;%d;%dt",
rows, cols);
ldisc_send(buf, len, 0);
4. Также советую посмотреть на то, какое количество статических и глобальных переменных используется в этом коде.
Мне интересно, весь open-source написан так же или это мне так повезло?
Как при таком качестве кода они умудряются что-то разумное делать?