В продолжении темы, поднятой мною тут: 906984
, таки решил озадачится, результатом озадачивания стало два скрипта.
-
gen-man2html.sh - пробегает по указанным секциям man-страниц (где они лежат и какие секции - внутри файла, лениво было опциями делать), и конвертирует их в HTML, заодно, по некоторым патернам создаёт ссылки (типа printf(3) или ссылкки в секцию 0, для <header.h>)
-
gen-html2assistant.sh - собственно уже пробегает по этим, сгенерированным, страницам, делает файл проекта справки Qt Assistan и, по завершении, вызывает *qhelpgenerator// для создания файла справки (на самом деле это SQLite база). После чего этот файл можно подключить в Qt Assistant:


Для того, что бы к работал поиск в “Указателе”, нужно указывать ключевые слова, в данный момент, в качестве оных, используется имя самой страницы. Полнотекстовый поиск будет доступен в соответствуем месте в Qt Assistant после окончания генерации индекса. В “Содержании” добавится новый пункт “Unix man pages”.
Вот так вот примерно это дело выглядит:

Сразу вопрос: подскажите инструмент для генерации ключевых слов для документа, интересует, на данный момент, только английский язык.
Бонусом нам это добавляет контекстную справку по всем функциям glibc и установленных библиотек (для которых есть man-page) в Qt Creator.
Сгенерированный мною файл справки можно взять тут:
http://hatred.homelinux.net/~hatred/unixman.qch.gz
UPD:
буквально сегодня в списке рассылки Qt Creator проскользнула статья:
Linux Man Pages integration with Qt Creator со схожим механизмом получения справочного файла. Отличие в том, что он брал готовые man-страницы в html с
http://www.kernel.org/doc/man-pages/online_pages.html
UPD2:
Там же в рассылке всплыла ссылка на галерею документации для Qt Creator:
https://wiki.qt.io/Qt_Creator_Documentation_Gallery (или поиском по “Qt_Creator_Documentation_Gallery”, так как они уже несколько раз домены тосовали).
В текущем состоянии не густо, но есть C++ Reference и убогенькая, сгенерированная doxygen документация по STL, а так же рекомендацию, как при помощи Doxygen генерировать документацию для Assistant.
Ещё когда топали на Ольховую, Ярослава кинула идею, что надо бы съездить на север Приморья, посетить водопад Чёрный Шаман (Большой Амгинский, высота около 30-35 метров - видимая часть и около 10-15 метров невидимая). Тогда дата была определена крайне расплывчато: а вот как нибудь в августе.
Узнал из
новости про очередной RC ядра Linux. А вот и пользовательская утилита:
http://pavlinux.ru/fanotify.tar.bz2, ну последней ссылкой, описание на LWN с небольшим примером на Си в конце:
http://lwn.net/Articles/339253/
Столкнулся с проблемой - никоим образом не получалось отредактировать контакт в ростере, хотя горячая клавиша была назначена. В конференции
psi-dev@conference.jabber.ru подсказали, посмотреть, а не залочен-ли ростер, оказалось - залочен, исправлять:
- Настройки -> Дополнительно
- далее находим опцию: options.ui.contactlist.lockdown-roster и ставим в true
Всё!
Тут уже писал про проблему пересылки/приёмки структурированных данных по сети.
На нашей целевой платформе нельзя применять сторонние библиотеки (типа libpack, как в предыдущей статье), и, так вышло (лучи ненависти), что #pragma pack() то работает, то не работает, да ещё стоит условие, что данные должны быть преобразованы к сетевому виду (ntohs(), ntohl(), htons(), htonl()), поэтому я сделал на макросах такой фит ушами:
/**************************************************************************************************/
/* Паковка и распаковка данных, для передачи по сети ---------------------------------------------*/
/**************************************************************************************************/
// Распаковка массива в структуры
/**
Начало блока распаковки массива данных, на которые указывает <br/>c ptr и размера <br/>c size
*/
#define unpack_begin(ptr, size) { <br/>
size_t __addr = 0; <br/>
size_t __size = (size_t)(size); <br/>
uint8_t *__ptr = (uint8_t*)(ptr); <br/>
union { <br/>
uint8_t cc[8]; <br/>
uint16_t ii[4]; <br/>
uint32_t ll[2]; <br/>
float ff[2]; <br/>
double dd; <br/>
} __swapd; (void)(__swapd)
/**
Распаковка очередной порции данных в <br/>c target
*/
#define unpack_next(target) <br/>
pack_printf("Unpack <br/>"%s<br/>"... Size: %d, current offset: %d, current size: %d<br/>n", #target, __size, __addr, sizeof(target)); <br/>
if ((__addr + (int)sizeof(target)) <= (__size)) <br/>
{ <br/>
memcpy(&(target), __ptr + __addr, sizeof(target)); <br/>
__addr += sizeof(target); <br/>
} (void)(0)
/**
Распаковка очередной порции данных в <br/>c target, с преобразованием из сетевого вида
Сетевое преобразование работает для простых типов размерос 2 (short), 4 (int, float)
и 8 (lint32_tlint32_t double) байтint16_t остальных данных
*/
#define unpack_net_next(target) <br/>
unpack_next(target); <br/>
switch(sizeof(target)) <br/>
{ <br/>
case 2: <br/>
memcpy(&__swapd.ii[0], &target, 2); <br/>
__swapd.ii[0] = ntohs(__swapd.ii[0]); <br/>
memcpy(&target, &__swapd.ii[0], 2); <br/>
break; <br/>
case 4: <br/>
memcpy(&__swapd.ll[0], &target, 4); <br/>
__swapd.ll[0] = ntohl(__swapd.ll[0]); <br/>
memcpy(&target, &__swapd.ll[0], 4); <br/>
break; <br/>
case 8: <br/>
memcpy(&__swapd.dd, &target, 8); <br/>
__swapd.ll[0] = ntohl(__swapd.ll[0]); <br/>
__swapd.ll[1] = ntohl(__swapd.ll[1]); <br/>
memcpy(&target, &__swapd.dd, 8); <br/>
break; <br/>
} (void)(0)
/**
Конец блока распаковки
*/
#define unpack_end() } (void)(0)
// Паковка данных из элементов струтуры в массив данных
/**
Начало блока паковки данных в <br/>c ptr размером <br/>c size
*/
#define pack_begin(ptr, size) unpack_begin(ptr, size)
// Внутренний вспомогательный макрос, как общая часть для pack_next()/pack_net_next()
#define _pack_next_intr(source, data) <br/>
printf("Pack <br/>"%s<br/>"... Size: %d, current offset: %d, current size: %d<br/>n", #source, __size, __addr, sizeof(source)); <br/>
if ((__addr + (int)sizeof(source)) <= (__size)) <br/>
{ <br/>
memcpy(__ptr + __addr, &(data), sizeof(source)); <br/>
__addr += sizeof(source); <br/>
} (void)(0)
/**
Пакует очередной элемент
*/
#define pack_next(source) <br/>
_pack_next_intr(source, source)
/**
Пакует очередной элемент, преобразовывая его в сетевой вид
*/
#define pack_net_next(source) <br/>
switch(sizeof(source)) <br/>
{ <br/>
case 2: <br/>
memcpy(&__swapd.ii[0], &source, 2); <br/>
__swapd.ii[0] = htons(__swapd.ii[0]); <br/>
_pack_next_intr(source, __swapd.ii[0]); <br/>
break; <br/>
case 4: <br/>
memcpy(&__swapd.ll[0], &source, 4); <br/>
__swapd.ll[0] = htonl(__swapd.ll[0]); <br/>
_pack_next_intr(source, __swapd.ll[0]); <br/>
break; <br/>
case 8: <br/>
memcpy(&__swapd.dd, &source, 8); <br/>
__swapd.ll[0] = htonl(__swapd.ll[0]); <br/>
__swapd.ll[1] = htonl(__swapd.ll[1]); <br/>
_pack_next_intr(source, __swapd.dd); <br/>
break; <br/>
default: <br/>
pack_next(source); <br/>
break; <br/>
} (void)(0)
/**
Конец блока паковки данных
*/
#define pack_end() unpack_end()
Можно ещё оптимизировать, тут оверхед с переменными вспомогательными, можно без них в большинстве случаев. Ну и, кажется, не совсем корректная работа с величинами больше 4 байт (double), но на серверной машине, по-моему, вообще залепа сделана, посмотрим как работать будет :)
Пример использования для отсылки данных:
struct Data {
short id;
float d;
long tm;
} data;
data.id = 0;
data.d = 73.3;
data.tm = 0xFEFD;
int n;
size_t data_size = 2 + 4 + 4; // sizeof(short) + sizeof(float) + sizeof(long) - поля структуры
char *data_ptr;
data_ptr = calloc(data_size, sizeof(char));
pack_begin(data_ptr, data_size);
pack_net_next(data.id);
pack_net_next(data.d);
pack_net_next(data.tm);
pack_end();
n = send(sock, data_ptr, data_size, 0);
Пример получения данных:
struct Data {
short id;
float d;
long tm;
} data;
int n;
size_t data_size = 2 + 4 + 4; // sizeof(short) + sizeof(float) + sizeof(long) - сколько данных получить нужно
char *data_ptr;
data_ptr = calloc(data_size, sizeof(char));
n = recv(sock, data_ptr, data_size, 0);
unpack_begin(data_ptr, data_size);
unpack_net_next(data.id);
unpack_net_next(data.d);
unpack_net_next(data.tm);
unpack_end();
// Тут структура заполнена распакованными данными
Если преобразование в сетевой вид не нужно, используйте pack/unpack_next()
На заметку,
отсюда и
отсюда, делается пустая директория /tmp:
$ mkdir tmp
$ touch tmp/.gitignore
$ git add tmp
$ echo '*' > tmp/.gitignore
$ git commit -m 'Empty directory' tmp
Основной нюанс: добавить .gitignore раньше, чем вписать туда игнорировать ВСЕ файлы
Очередной выпуск, в котором опубликована четвертая, заключительная статья из цикла “Схемотехника в Linux с помощью gEDA”: “Создание паттерна в PCB”, рассказывается как делать паттерны (футпринты) для компонентов, как обычно - в примерах.
Скачать выпуск:
http://osa.samag.ru/get/OpenSource067.zip
19 годков стукнуло.
Вышел 66 выпуск электронного приложения к журналу “Системный администратор”, а в нем и моя третья статья из цикла “Схемотехника в Linux с помощью gEDA”, в которой рассмотрено создание условного обозначения компонент для gschem. Так же сделано небольшое отступление и рассказано о интеграции gschem и pcb при помощи менеджера проектов xgschm2pcb. В общем качаем и читаем:
http://osa.samag.ru/get/OpenSource066.zip
Вспоминаем о выравнивании (не говорю о том, что числовые поля нужно привести в сетевой вид, дабы на удаленной стороне была уже произведена корректная распаковка данных: man 3 htons/ntohs, man 3 htonl/htohl, man 3 endian), чешем репу - а если приёмная сторона использует другое выравнивание, нежели у нас при сборке бинарника?((по рабоче-крестьянски: на типичной 32бит машине все переменные выравнены по 32битной длинне))
Вижу варианты:
- пихать все в char-буффер - некрасиво
- поэлементно отправлять - неудобно и некрасиво
- использовать #pragma pack() - удобно, красиво, но не супер переносимо
- использовать систему атрибутов GCC - не переносимо
Посмотрим на использование #pragma pack(), конкретно посмотреть подробности на официальной странице:
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
При объявлении структуры, которая будет гоняться по сети рекомендуется отключить выравнивание:
#pragma pack(push,1)
....
#pragma pack(pop)
Простой пример:
#include <stdio.h>
#pragma pack(push,1)
struct test_packed {
char ch;
long data;
};
#pragma pack(pop)
struct test_unpacked {
char ch;
long data;
};
int main()
{
printf("Packed size: %d, Unpacked size: %d<br/>n",
sizeof(struct test_packed),
sizeof(struct test_unpacked));
return 0;
}
Компилируем и выполняем:
$ gcc -o main main.c && ./main
Packed size: 5, Unpacked size: 8
Всё наглядно :)
Не рекомендуется использовать для обычной работы: в размерах выигрыша почти не получится, а в скорости доступа проиграете.
UPD: тут 864110|#864110
подкинули ещё ссылку:
http://www.leonerd.org.uk/code/libpack/
PS по слухам появилось в 2.95.2 или около того.