13 мар. 2013 г.

/bin/sh: no: command not found

Ошибка

$ ./configure
...
/bin/sh: line 1: no: command not found


Возможное решение

# apt-get install gettext

10 мар. 2013 г.

Пьесы Шекспира в две колонки с переводом

Если Вы хотите почитать Шекспира на английском, но ничего не понимаете, можно отформатировать оригинал и перевод на русский в две колонки: слева реплика на английском, справа ее перевод.

Удобные для парсинга английские варианты есть на shakespeare.mit.edu. В HTML текст уже разделен на акты, сцены и пронумерованные реплики. Русские переводы есть на lib.ru/SHAKESPEARE. HTML для парсинга неудобен, но plain text можно разбить на реплики регулярными выражениями.

Здесь находятся 3 скрипта, которые делают следующее:
  1. mit2xml: преобразует пьесу с mit.edu в XML.
  2. libru2xml: преобразует пьесу с lib.ru в XML.
  3. concat-en-ru: склеивает два XML по репликам и генерирует один HTML-файл.
Скрипты проверялись только на пьесе "Буря" (The Tempest): en, ru (и на других её переводах с lib.ru). URL исходных HTML  прописываются в Makefile. Собрать выходной HTML с двумя колонками для "Бури" можно так:

$ make tempest

Необходимые перловые модули можно установить с помощью пакетного менеджера или так:

$ sudo make cpan

Результат можно посмотреть здесь.

Для форматирования других пьес потребуется создать файл с переводом имен героев, по аналогии с tempest_names.cfg. Он используется для нахождения соответствия между английскими и русскими репликами, которые не всегда идут один-в-один.

Список имен героев можно получить так:

$ perl mit2xml ... | grep '<actor>'
$ perl libru2xml ... | grep '<actor>'

Кроме этого, возможно, придется поколдовать в регулярными выражениями в libru2xml, они могут не подходить для других пьес.

16 февр. 2013 г.

Gentoo: Сборка GCC 3.2 в современном окружении

В Gentoo есть ebuild-ы для GCC старых версий, однако GCC 3.2 не собирается последними версиями GCC, в том числе текущим стабильным 4.6. Возможное решение следующее: с помощью GCC 4.6 собрать GCC 3.4, а с помощью GCC 3.4 уже собрать GCC 3.2.

Шаг 1: версия bison


GCC 3.2 не собирается текущим стабильным bison 2.x. Для bison слотов нет, так что для сборки GCC можно просто замаскировать новые версии. У меня работает bison-1.875d.

/etc/portage/package.mask

>=sys-devel/bison-2.0

# emerge -u sys-devel/bison

Шаг 2: настройка окружения


См. /etc/portage/env.
  1. Во-первых, GCC версии 3.x могут не поддерживать ваши CFLAGS (в частности -march=native), поэтому отключим их для этих пакетов.
  2. Во-вторых, мы должны указать, что для сборки GCC 3.2 будет использоваться GCC 3.4.
/etc/portage/package.env

# Отключаем CFLAGS для GCC 3.x
=sys-devel/gcc-3* use-simple-cflags.conf

# Включаем использование GCC 3.4 для GCC 3.2
=sys-devel/gcc-3.2* use-gcc-3.4.conf

 /etc/portage/env/use-simple-cflags.conf 

CFLAGS="-O2"
CXXFLAGS="-O2"

/etc/portage/env/use-gcc-3.4.conf 

CC="gcc-3.4.6"


Шаг 3: сборка GCC 3.4


# emerge sys-devel/gcc:3.4


Шаг 4: сборка GCC 3.2


# emerge sys-devel/gcc:3.2
# /usr/i686-pc-linux-gnu/gcc-bin/3.2/gcc --version

13 февр. 2013 г.

Emacs, tramp: File ... is read-only on disk. Change buffer mode?


Это сообщение может появиться, если соединение разорвалось и tramp не может установить повторное соединение самостоятельно.

Решение:

M-x tramp-cleanup-all-connections

Затем можно обновить буфер в dired или повторно сохранить файл.

2 февр. 2013 г.

Emacs: тормоза, плавная прокрутка


Ссылки

  1. Возможные причины медленной работы
  2. Плавная прокрутка

Возможные симптомы и их причины


1. Задержки при наборе текста


Это возможно при использовании модуля tabbar, старый баг. AFAIK, его мало кто использует.

2. Задержки при прокрутке и построчном перемещении курсора

Возможные причины:
  1. Самое главное, из-за linum-mode (нумерация строк).
  2. Из-за font-lock-mode (применение цветов и шрифтов к тексту), когда в буфере слишком много разноцветных жирных шрифтов.
  3. Из-за hl-line-mode (подсветка текущей строки).

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

Настройки прокрутки

;; При прокрутке применять font-lock не сразу, а после небольшой задежки.
(setq jit-lock-defer-time 0.01)

;; Эту опцию часто советуют выставлять в t, но я не заметил разницы с nil.
;(setq redisplay-dont-pause t)

;; Опционально: медленная плавная прокрутка колесиком.
(setq mouse-wheel-scroll-amount '(2 ((shift) . 2)))   ; Прокручивать по 2 строки.
(setq mouse-wheel-progressive-speed nil)
(setq mouse-wheel-follow-mouse 't)

;; Опционально: никогда не прокручивать более, чем на 1 строку при перемещении курсора за
;; нижнюю или верхнюю границу экрана.
(setq scroll-conservatively 10000)

;; Опционально: отступ от верха и низа экрана в 1 строку, при попадании курсора за отступ
;; происходит прокрутка.
(setq scroll-margin 1)

См. также Bug #12936.

Настройки нумерации строк

Дело в том, что linum-mode перерисовывает номера строк во время прокрутки, из-за чего она и тормозит. Мне известны 2 альтенативы:

  1. nlinum-mode: успешно решает в точности описанную проблему. Доступен на github.
  2. setnu-mode: предшественник linum-mode, работает почти без задержек, но есть баги, в том числе при использовании совместно с модулем auto-complete.
Стандартный linum позволяет установить hook на генерацию формата номеров строк и face для них, причем они могут быть свои для каждой строки. В nlinum это на данный момент не поддерживается, но такую возможность легко добавить, см. nlinum--region.

Справедливости ради замечу, что на 8-ядерном компьютере прокрутка у меня все же немного плавнее, чем на 2-х ядерном.

23 дек. 2012 г.

C++11: std::enable_shared_from_this, исключение std::bad_weak_ptr


Ссылки


Если при вызове shared_from_this() генерируется исключение  std::bad_weak_ptr, это означает, что еще не существует ни одного std::shared_ptr, ссылающегося на объект. См. Notes.

Неправильно:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <memory>

struct Class : std::enable_shared_from_this<Class>
{};

int main()
{
    Class *c = new Class;
    
    c->shared_from_this();
    
    return 0;
}

terminate called after throwing an instance of 'std::bad_weak_ptr'
  what():  std::bad_weak_ptr

Правильно:

#include <memory>

struct Class : std::enable_shared_from_this<Class>
{};

int main()
{
    Class *c = new Class;
    
    std::shared_ptr<Class> sc(c);
    
    c->shared_from_this();
    
    return 0;
}

16 дек. 2012 г.

Unix domain sockets: гарантированное освобождение и повторное использование сокета

Ссылки

Для связи процессов на одном компьютере можно использовать доменные сокеты (IPC-сокеты).

Отличия от интернет-сокетов:
  • Более высокая производительность.
  • Доставка SIGPIPE сразу после обрыва соединения с другого конца.
  • Стандартные права доступа unix у файлов сокетов.
См. также здесь.

Производительность можно измерить с помощью netperf:

$ netperf -t TCP_STREAM      # TCP
$ netperf -t STREAM_STREAM   # unix domain (компилировать netperf с опцией --enable-unixdomain)

Проблема

Файл сокета создается при вызове bind(2). Если файл уже существует, возвращается ошибка EADDRINUSE.

Единственный способ повторного использования файла сокета - вызов unlink(2) перед bind.

Есть две схемы:
  • Вызывать unlink перед завершением сервера. Тогда нет гарантии, что при крахе сервера не останется висячего файла, который пользователю придется удалять вручную.
  • Вызывать unlink при запуске сервера. Тогда нет гарантии, что не будет удален файл другого запущенного экземпляра сервера.

Решение

Именованные доменные сокеты бывают двух типов: filesystem sockets и abstract namespace sockets, см. unix(7).

Filesystem sockets

Простое решение - использовать дополнительный lock-файл для каждого сокета.

Этот файл может быть заблокирован тогда и только тогда, когда в данный момент запущен другой экземпляр сервера. Если блокировку удалось захватить, можно безопасно вызывать unlink() для файла сокета.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const char *socket_path = "/tmp/server-socket";

int server = socket(PF_LOCAL, SOCK_STREAM, 0);
assert(server != -1);

struct sockaddr_un server_addr;
bzero(&server_addr, sizeof(server_addr));

server_addr.sun_family = AF_LOCAL;
strcpy(server_addr.sun_path, socket_path);

char lock_path[256];
sprintf(lock_path, "%s.lock", socket_path);

//
// Open lock file
//
int lock_fd = open(lock_path, O_RDONLY | O_CREAT, 0600);
if (lock_fd == -1) {
    printf("can't open lock file\n");
    exit(1);
}

//
// Acquire lock
//
int ret = flock(lock_fd, LOCK_EX | LOCK_NB);
if (ret != 0) {
    printf("address already in use!\n");
    exit(1);
}

//
// Remove socket file
//
unlink(socket_path);

//
// Create socket file
//
ret = bind(server, (struct sockaddr *)&server_addr, sizeof(server_addr));
assert(ret == 0);

Abstract namespace sockets

Еще более простое решение - использовать abstract namespace (поддерживается только в Linux).

Если в  структуре sockaddr_un в поле sun_path в первый байт имени сокета записать '\0', сокет с этим именем будет создан не в файловой системе, а абстрактном пространстве имен.

Такой сокет будет автоматически освобожден при завершении приложения.