Обычно true и false в С определяют так:
#define TRUE 1
#define FALSE 0
Но недавно встретил интересную запись следующего вида:
#define TRUE (0 == 0)
#define FALSE (0 != 0)
Обычно true и false в С определяют так:
#define TRUE 1
#define FALSE 0
Но недавно встретил интересную запись следующего вида:
#define TRUE (0 == 0)
#define FALSE (0 != 0)
Меня заинтересовал язык clojure, поэтому решил попробовать новую для себя ide IntelliJ IDEA. Версию community edition можно скачать на официальном сайте. Для сборки проектов я использую leiningen . В этом топике я покажу какие необходимо сделать настройки.
Для начала необходимо установить два плагина: La Clojure и Leiningen с помощью Plugin Manager.
Далее нужно настроить плагин Leiningen. Для этого открываем настройки File->Settings(Ctrl+Alt+S), находим строку с данным плагином и устанавливаем путь до утилиты lein.
После чего создадим проект с помощью lein из консоли:
lein new example
Откроем созданный проект в ide, используя Open Project, и выберем файл project.clj. Далее IntelliJ IDEA сгенерит все необходимые для нее файлы.Следующий шаг это добавление необходимых зависимостей для проекта. На данном примере я добавлю clojure-contrib и sqlitejdbc. Файл project.clj примет вид:
(defproject sqlite-example "1.0.0-SNAPSHOT"
:description "sqlite example"
:dependencies [[org.clojure/clojure "1.2.1"]
[org.clojure/clojure-contrib "1.2.0"]
[sqlitejdbc "0.5.6"]])
После чего нажимаем на вкладку Leiningen, выбираем deps и запускаем загрузку необходимых библиотек.Осталось лишь добавить установленные библиотеки в проект idea. Это необходимо сделать, потому что мы не создавали новый проект, а открыли уже существующий, сгенерированный с помощью утилиты lein. Выбираем File->Project Structure (или Ctrl+Alt+Shift+S), далее Modules и выбираем закладку Dependencies, затем нажимаем кнопку Add -> Libraries.
Читая An Introduction to Programming in Emacs Lisp, наткнулся на описание простых рекурсивных паттернов и решил сделать их описание.
В данном паттерне действие выполняется над каждым элементом списка. Алгоритм паттерна следующий:
(defun square-each (numbers-list)
"Square each of a NUMBERS LIST, recursively."
(if (not numbers-list)
nil
(cons (* (car numbers-list) (car numbers-list))
(square-each (cdr numbers-list)))))
(square-each ’(1 2 3))
⇒ (1 4 9)
В данном примере каждый элемент списка возводится в квадрат.
(defun print-elements-recursively (list)
"Print each element of LIST on a line of its own. Uses recursion."
(when list
(print (car list))
(print-elements-recursively (cdr list))))
В приведенном примере функция рекурсивно выводит каждый элемент.В этом паттерне действие производится над каждым элементом списка и результат
этого действия аккамулируется с результатом последующих элементов. Алгоритм имеет вид:
(defun add-elements (numbers-list)
"Add the elements of NUMBERS-LIST together."
(if (not numbers-list)
0
(+ (car numbers-list) (add-elements (cdr numbers-list)))))
(add-elements ’(1 2 3 4))
⇒ 10
Таким образом функция выводит сумму всех элементов списка.В данном паттерне каждый элемент списка проходит проверку. Если он удовлетворяет условию, то результат действия сохраняется.
Алгоримт имеет вид:
(defun keep-three-letter-words (word-list)
"Keep three letter words in WORD-LIST."
(cond ((not word-list) nil)
((eq 3 (length (symbol-name (car word-list))))
(cons (car word-list) (keep-three-letter-words (cdr word-list))))
(t (keep-three-letter-words (cdr word-list)))))
(keep-three-letter-words ’(one two three four five six))
⇒ (one two six)
В выше приведенном примере выделяется список символов, длина которого равна 3.Возникла необходимость в работе с документацией по исходному коду. Конечно есть много готовых инструментов, но хотелось бы что-нибудь интегрированное к emacs. Поэтому решил сделать модуль для него на основе org-mode. В начале упор будет сделан на язык С. Исходный код проекта находится на github.
Постоянно забываю команды git для создания новой удаленной ветки. Решил отметить это тут:
git push origin origin:refs/heads/new_branch
git checkout --track -b new_branch origin/new_branch
Чтобы удалить удаленную ветку:
git push origin :heads/new_branch
Вывести список удаленных веток можно командой:
git branch -r
/*
buffer - хранит полученные сообщения от netlink
size - размер полученных данных
*/
void show_route(char *buffer, int size)
{
/*
nlmp - указатель на структуру заголовка netlink
routemsg - полезная нагрузка
tb[RTA_MAX+1] - атрибуты маршрута
*/
struct nlmsghdr *nlmp;
struct rtmsg *routemsg;
struct rtattr * tb[RTA_MAX+1];
/*
Данные в буфере имеют следующий вид:
|nlmsghdr|data|nlmsghdr|data|....|nlmsghdr|data|
|-------------------size-----------------------|
*/
for(nlmp = (struct nlmsghdr *)buffer; size > sizeof(*nlmp);){
int len;
int req_len;
/*Проверяем целостность netlink сообщения*/
if (!NLMSG_OK(nlmp, size)) {
perror("NLMSG not OK\n");
return;
}
/*Это размер сообщения netlink*/
int len = nlmp->nlmsg_len;
/*Получаем размер полезной нагрузки*/
int req_len = len - sizeof(*nlmp);
/*Проверяем тип сообщения*/
/*Если он не относится к маршрутам, то переходим на следующее сообщение*/
switch(nlmp->nlmsg_type){
case RTM_DELROUTE:
printf("A route was deleted\n");
break;
case RTM_NEWROUTE:
printf("A route was added\n");
break;
default:
size -= NLMSG_ALIGN(len);
nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len));
continue;
}
/*Получаем указатель на полезную нагрузку и , после чего, выделяем атрибуты маршрута*/
routemsg = (struct rtmsg *)NLMSG_DATA(nlmp);
/*Данная функция описана ниже.*/
parseRtattr(tb, RTA_MAX, RTM_RTA(routemsg), len);
/*Код ниже выводит атрибуты маршрута*/
if(tb[RTA_IIF]){
int iface;
iface = *(int*)RTA_DATA(tb[RTA_IIF]);
printf("An input iface is %d\n", iface);
}
if(tb[RTA_OIF]){
int iface;
iface = *(int*)RTA_DATA(tb[RTA_OIF]);
printf("An output iface is %d\n", iface);
}
if(tb[RTA_DST]){
char routeAddr[128];
inet_ntop(AF_INET6, RTA_DATA(tb[RTA_DST]), routeAddr, sizeof(routeAddr));
printf("Destination route is %s\n", routeAddr);
}else if (routemsg->rtm_dst_len) {
printf( "0/%d \n", routemsg->rtm_dst_len);
} else {
printf("Destination route is default\n");
}
if(tb[RTA_SRC]){
char routeAddr[128];
inet_ntop(AF_INET6, RTA_DATA(tb[RTA_SRC]), routeAddr, sizeof(routeAddr));
printf("Source route is %s\n", routeAddr);
}
if(tb[RTA_GATEWAY]){
char routeAddr[128];
inet_ntop(AF_INET6, RTA_DATA(tb[RTA_GATEWAY]), routeAddr, sizeof(routeAddr));
printf("Gateway is %s\n", routeAddr);
}
if(tb[RTA_PRIORITY]){
int metric ;
metric = *(int*)RTA_DATA(tb[RTA_PRIORITY]);
printf("Mertic is %d\n", metric);
}
/*Переходим на следующее сообщение*/
size -= NLMSG_ALIGN(len);
nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len));
}//for(nlmp = (struct nlmsghdr *)buffer; size > sizeof(*nlmp);){
}
Полезная нагрузка в данном случае состоит из заголовка и атрибутов
void parseRtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
{
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
while(RTA_OK(rta, len)){
if(rta->rta_type <= max){
tb[rta->rta_type] = rta;
}
rta = RTA_NEXT(rta, len);
}
}
int main(int argc, char *argv[])
{
int nd = 0;
struct sockaddr_nl *local;
char buffer[16384];
nd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
local = malloc(sizeof(struct sockaddr_nl ));
memset(local, 0, sizeof(struct sockaddr_nl));
local->nl_family = AF_NETLINK;
/*Принимаем изменения, связанные с маршрутами ipv6*/
local->nl_groups = RTMGRP_IPV6_ROUTE;
local->nl_pid = getpid();
if(bind(nd, (struct sockaddr *)local , sizeof(struct sockaddr_nl)) < 0){
printf("Error bind\n");
return 1;
}
while(1){
/*
Эта структура непосредственно передается через сокет.
Она содержит в себе указатель на блок полезных данных,количество
данных блоков, а так же ряд дополнительных флагов и полей
*/
struct msghdr msg;
/*
Эта структура служит хранилищем полезных данных,
передаваемых через сокеты netlink. Полю iov_base присваивается указатель
на байтовый массив. Именно в этот байтовый массив будут записаны
данные сообщения.
*/
struct iovec iov;
int size = 0;
iov.iov_base = buffer;
iov.iov_len = 16000;
msg.msg_name = &local;
msg.msg_namelen = sizeof(*local);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
size = recvmsg(nd, &msg, MSG_DONTWAIT);
if(size < 0){
if(errno == EINTR || errno == EAGAIN){
usleep(250000);
continue;
}
}
show_route(buffer, size);
}
}
(in-package #:cl-event-callback)
;Объявим переменную, при изменении которой будет присходить событие
(defparameter *a* 1)
; Данная функция будет выполняться при получении события
(defun test () (print "test"))
;Создаем именнованное событие. В данном случае, если *a* больше 3, то
;будет вызываться функция test.
(defun new-event ()
(connect '(test) 'test-event '(> *a* 3)))
;Функция для изменения состояния переменной *a*
(defun event-change (var)
(setq *a* var))
;Удаляем именнованое событие
(defun del-test-event ()
(disconnect 'test-event))
(defun main ()
(new-event) ; <- Создаем событие
(thread-run-callbacks) ; <- Отслеживаем изменения состояния
(event-change 5) ; <- Изменяем переменную *a*, чем вызываем событие
(sleep 3)
(event-change 1) ; <- Возвращаем состояние *a*
(del-test-event) ; <- Удаляем событие
(thread-stop-callbacks))
(in-package #:cl-event-callback)
;Объявим функции для тестов
(defun test1 () (print "test1"))
(defun test2 () (print "test2"))
;Создадим события
(defun create-events()
(connect '(test1) 'test-one)
(connect '(test2) 'test-two))
;Функция удаления событий
(defun delete-events ()
(disconnect 'test-one)
(disconnect 'test-two))
(defun main ()
(create-events) ; <- Создаем события
(thread-run-callbacks) ; <- Отслеживаем изменения сотояния событий
(set-event-state 'test-one :trig) ; <- Вызываем событие вручную
(set-event-state 'test-two :trig-stop); <- Функция, подписанная на это событие вызовется один раз, после чего состояние события переведется в :not-trig
(sleep 2)
(set-event-state 'test-one :not-trig) ; <- Это событие переводим в состояние :not-trig
(delete-events)
(thread-stop-callbacks))
На текущий момент необходимо доделать следующее:
(require 'asdf-install)
или
(require "asdf-install")
После чего выполняем следующую команду:
(asdf-install:install :package-name)
где package-name - это название устанавливаемого пакета.
(push (truename #P"/path/to/packet") asdf:*central-registry*)
3. После чего устанавливаем пакет командой:
(asdf:oos 'asdf:load-op :package_name)