Окей, it's fflush() tiem!
Досмотрел сегодня Initial D Fourth Stage, ну естественно первый сезон был самым лучшим, что ни говори. Это похоже на Thief: The Dark Project VS Thief II: The Metal Age. Техническое совершенство, миссии ориентированные в первую очередь на геймплей, а не на создание атмосферы, prodiving'а экспириенса... Кстати пословица "первый блин комом" -- мне нифига лично не нравится, ящетаю что перый блин как раз самый вкусный.
Под конец как-то начали появлятся такие странные шутки, походу даже не специально получившиеся. Ну короче все равно, Initial D рулит, буду смотреть дальше~
Какое-то время назад я писал о проге KeyHoleTV которая позволяет смотреть некоторые, японские теле/радио каналы, а также любительские станции (которые с помощью того же KHTV можно создавать).
У нее есть версия и под линукс, а в OpenBSD есть поддержка бинарной эмуляции линукса, ну то бишь можно линуксовые экзешники запускать. И как я опять же уже говорил, иногда эта эмуляция работает отлично, иногда нет.
Вобщем я решил попробовать запустить KeyHoleTV у себя на лаптопе. Долго мучался, скачивал всякие rpm'ы с библиотеками, устанавливал, они тянули за собой другие библиотеки и т.д.
В конце концов дело остановилось на том что при попытке запуска, ld стал жаловатся что типа у libSDL -- executable stack o_O Вобщем я проделал for key in stack sections elf; do find memory/ -iname '*'$key'*'; done (иными словами попытался вспомнить все что знаю если что-то знаю по теме) и решил попробовать пойграть с флагами секций в elf файле программы.
ELF -- в принципе стандартный формат выполняемый файлов на юниксен на сегодняшний день.
А потом я не смог дверь сломать мне не удалось найти никакого редактора ELF файлов, поэтому я решил при помощи libelf быстренько на левой пятке задней ноги нижней части туловища написать малюсенькую прогу которая только и делала бы что меняла RWX флаги на секциях. Написал, игрался там, менял флаги у бинарника -- но нифига не вышло. Он походу как-то динамически наверное менял аксесс мод на память, вроде с помощью mprotect. На след. день я тупо на работе скомпилил SDL, каким-то раком, не помню каким, отключив эту фишку (а, помоему я configure скрипт испоганил так, чтобы он не находил mprotect =), принес домой, затаив дыхание набрал ./lkeyholetv, нажал Enter ииииИИ... Segmentation fault!! FUUUUUUUUUUUUUUUU- ><
Но вообще я не об этом хотел рассказать =)
Когда я лазил по интернетам в поисках доков к libelf, то в конце концов остановился на странице братцев-ФриБСДшников:
http://people.freebsd.org/~jkoshy/download/libelf/article.html.
Пока я читал этот туториал, ( хотя я только где-то половину прочитал, на больше у меня не хватило мужества D: ) я офигел с того как чел мастерски владеет Си Препроцессором!! =о Словно препроцессор -- это продолжение его руки, он рассекает им нудные повторяющиеся куски кода как горячий нож масло! =о
Вобщем я сильно вдохновился, и начал тоже весьма активно юзать препроцессор.
Фишка/и/аи:
1. Заменяем какой-то нудный/некрасивый/обфускированный_мама_не_горюй/просто_длинный кусок кода, каким-то коротким, емким названием которое отражает суть этого кода
2. Зачем { name, "name" ... }, если можно MACRO(name)
3. Не факт, но скорее всего, когда понадобятся изменения, можно будет просто поправить один этот макрос
На работе вот неплохо удалось поюзать уже это дело, типа (1)
было
if (var1 == что-то && var2 == .... и так до фига
стало
#define IS_ТАКОЙ-ТО_MSG() var1 == что-то && var2 == ....
#define ...
if (IS_ТАКОЙ-ТО_MSG()) { ...
и (2)
#define NELEMS(a) (sizeof(a)/sizeof(a[0]))
#define END_OF(a) (a + NELEMS(a))
...
struct PointerPair {
SomeType *begin, *end
} pointer_pairs[] = {
# define POINTER_PAIR(a) { a, END_OF(a) }
POINTER_PAIR(array1),
POINTER_PAIR(array2)
...
}, p_pair;
...
p_pair = pointer_pairs[some_index];
for_each(p_pair.begin, p_pair.end, someFunc);
...
А сегодня вот шкодил одну штуку (на старом добром Си) и понадобился мне стэк, я подумал почему бы не сделать что-то вроде С++ного тэмплейта :D А ч0, C++ ведь начинался как расширения к препроцессору Си.
Вот такой получился макрос
#define DEFINE_STACK(NAME, TYPE) \
struct NAME##stack { \
TYPE *v; \
size_t n; \
size_t el_size; \
}; \
typedef struct NAME##stack NAME##stack_t; \
\
static void \
NAME##stack_init(struct NAME##stack *st) { \
bzero(st, sizeof(struct NAME##stack)); \
st->el_size = sizeof(TYPE); \
} \
\
static void \
NAME##stack_cleanup(struct NAME##stack *st) { \
free(st->v); \
NAME##stack_init(st); \
} \
\
static void \
NAME##stack_push(struct NAME##stack *st, TYPE val) { \
st->v = realloc(st->v, ++st->n * st->el_size); \
st->v[st->n - 1] = val; \
} \
\
static TYPE \
NAME##stack_pop(struct NAME##stack *st) { \
TYPE val; \
\
if (st->n == 0) \
return (TYPE) 0; \
\
val = st->v[st->n - 1]; \
st->v = realloc(st->v, --st->n * st->el_size); \
\
return val; \
} \
\
static TYPE \
NAME##stack_peek(struct NAME##stack *st) { \
if (st->n == 0) \
return (TYPE) 0; \
return st->v[st->n - 1]; \
}
Beauuuutiful...
Ну я такой, простенький сделал.. Чтобы заюзать его, надо просто в .с файле DEFINE_STACK(name, type), где name -- приставка которая будет у имени структуры и тайпдэфа и у всех функций, а type -- тип который будет в стэке хранится. (Я в курсе что надо проверять что realloc возвращает, это просто набросок пишу)
На самом деле я 100% когда-то в прошлом видел где-то подобные макросы, но где точно -- не могу вспомнить. Ну возможно что в той же /usr/include, ибо когда "портировал" cwm на линукс, увидел что он юзает например очереди, которые типа тоже как макрос приведенный выше.. Где-то они там в /usr/include живут.. Короче find /usr/include | fgrep -o TAILQ а я пополз спать ~.~