Migrated to the Pulse Audio mainloop, deleted ALSA sound code.

--- hdswitch.c
+++ hdswitch.c
@@ -6,23 +6,24 @@
 ffmpeg -y -i unix:server.sock -f webm - | ffmpeg2theora --output /dev/stdout --format webm - | oggfwd -p -n event icecast.mi.hdm-stuttgart.de 80 xV2kxUG3 /test.ogv

 */
-// For accept4
+
+// For accept4() and open_memstream() (needs _POSIX_C_SOURCE 200809L which is also defined by _GNU_SOURCE)
+// sigemptyset() and co. (need _POSIX_SOURCE)
 #define _GNU_SOURCE

-// Required for open_memstream
-#define _POSIX_C_SOURCE 200809L
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>

 #include <SDL/SDL.h>
-#define GL_GLEXT_PROTOTYPES
-#include <GL/gl.h>
-
+#include <pulse/pulseaudio.h>
 #include <poll.h>

 #include <sys/socket.h>
 #include <sys/un.h>
+#include <sys/signalfd.h>
+#include <signal.h>
+#include <unistd.h>

 #include "drawable.h"
 #include "stb_image.h"
@@ -33,6 +34,20 @@
 #include "array.h"

+static int signals_init();
+static int signals_cleanup(int signal_fd);
+
+static void signals_cb(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata);
+static void sdl_event_check_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *tv, void *userdata);
+static void camera_frame_cb(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata);
+
+// Global stuff used by event callbacks
+size_t scene_count = 0;
+size_t scene_idx = 0;
+size_t ww, wh;
+bool something_to_render = false;
+
+
 typedef struct {
 	void*  data;
 	size_t size;
@@ -170,6 +185,7 @@
 	if (server_fd == -1)
 		return perror("socket"), false;

+	unlink("server.sock");
 	struct sockaddr_un addr = { AF_UNIX, "server.sock" };
 	if ( bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1 )
 		return perror("bind"), false;
@@ -195,7 +211,7 @@
 	free(header_ptr);
 }

-void server_accept() {
+static void server_accept_cb(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
 	int client_fd = accept4(server_fd, NULL, NULL, SOCK_NONBLOCK);
 	if (client_fd == -1) {
 		perror("accept4");
@@ -215,7 +231,6 @@
 		perror("write");

 	//write(client_fd, header_ptr, header_size);
-
 }

 void server_write_frame(uint8_t track, uint64_t timecode_ms, void* frame_data, size_t frame_size) {
@@ -304,25 +319,25 @@
 	}

 	video_input_t video_inputs[] = {
-		{ "/dev/video0", 640, 480, NULL, 0 }//,
+		{ "/dev/video0", 640, 480, NULL, 0 },
 		//{ "/dev/video2", 640, 480, NULL, 0 },
-		//{ "/dev/video1", 640, 480, NULL, 0 }
+		{ "/dev/video1", 640, 480, NULL, 0 }
 	};

 	video_view_t *scenes[] = {
 		(video_view_t[]){
 			{ 'l', 0, 'c', 0,     0, -100, 0,     0 },
 			{ 0 }
-		}/*,
+		},
 		(video_view_t[]){
 			{ 'l', 0, 'c', 0,     0, -100, 0,     0 },
-			{ 'r', 0, 'b',16,     1,  -33, 0,     0 },
+			{ 'r', 0, 'b', 0,     1,  -33, 0,     0 },
 			{ 0 }
 		},
 		(video_view_t[]){
 			{ 'c', 0, 'c', 0,     1, -100, 0,     0 },
 			{ 0 }
-		}*//*,
+		}/*,
 		(video_view_t[]){
 			{ 'l', 0, 't', 0,     0, -100, 0,     0 },
 			{ 'r', 0, 'b', 0,     1,  -33, 0,     0 },
@@ -336,7 +351,7 @@

 	// Calculate rest of the configuration
 	size_t video_input_count = sizeof(video_inputs) / sizeof(video_inputs[0]);
-	size_t scene_count = sizeof(scenes) / sizeof(scenes[0]);
+	scene_count = sizeof(scenes) / sizeof(scenes[0]);

 	// Composite (output video) size
 	size_t composite_w = 0, composite_h = 0;
@@ -374,38 +389,44 @@
 	}

-
-	/*
-	//int v1w = 640, v1h = 480;  // video1 raw dimensions, best for HP Webcam HD 5210: 800x448
-	int v1w = 800, v1h = 448;  // video1 raw dimensions, best for HP Webcam HD 5210:
-	int v2w = 640, v2h = 480;  // video2 raw dimensions
-	int cw  = v1w, ch  = v1h;  // composite video dimensions
-	int ww  = cw,  wh  = ch;   // window dimensions
-	int cv1w = v1w,     cv1h = v1h,     cv1x = 0,         cv1y = 0;          // dimension and position of video1 in composite video
-	int cv2w = v2w / 4, cv2h = v2h / 4, cv2x = cw - cv2w, cv2y = ch - cv2h;  // dimension and position of video2 in composite video
-	*/
-
-
+	// Init mainloop
+	pa_mainloop* poll_mainloop = pa_mainloop_new();
+	pa_mainloop_api* mainloop = pa_mainloop_get_api(poll_mainloop);
+
+	// Init signal handling
+	int signal_fd = signals_init();
+	mainloop->io_new(mainloop, signal_fd, PA_IO_EVENT_INPUT, signals_cb, NULL);
+
+	// Init SDL
 	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
 	atexit(SDL_Quit);

-	size_t ww = composite_w, wh = composite_h;
+	ww = composite_w;
+	wh = composite_h;
 	SDL_Window* win = SDL_CreateWindow("HDSwitch", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, ww, wh, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
 	SDL_GLContext gl_ctx = SDL_GL_CreateContext(win);
-	//SDL_GL_SetSwapInterval(1);
 	SDL_GL_SetSwapInterval(0);
+
+	struct timeval now = { 0 }, interval = {0, 25*1000}, next_sdl_check_time = { 0 };
+	gettimeofday(&now, NULL);
+	timeradd(&now, &interval, &next_sdl_check_time);
+	mainloop->time_new(mainloop, &next_sdl_check_time, sdl_event_check_cb, NULL);
+

 	// Setup OpenGL stuff
 	check_required_gl_extentions();

+
+	// Setup videos and textures
 	for(size_t i = 0; i < video_input_count; i++) {
 		video_input_p vi = &video_inputs[i];

 		vi->cam = cam_open(vi->device_file);
 		cam_print_info(vi->cam);
-		cam_setup(vi->cam, __builtin_bswap32('YUYV'), vi->w, vi->h, 30, 1, NULL);
+		cam_setup(vi->cam, cam_pixel_format('YUYV'), vi->w, vi->h, 30, 1, NULL);
 		cam_print_frame_rate(vi->cam);

+		mainloop->io_new(mainloop, vi->cam->fd, PA_IO_EVENT_INPUT, camera_frame_cb, vi);
 		vi->tex = texture_new(vi->w, vi->h, GL_RG8);
 	}

@@ -484,227 +505,25 @@
 	}

-	/*
-	video->texture = texture_new(w, h, GL_RG8);
-
-	// Triangle strip for a basic quad. Quads were removed in OpenGL 3.2.
-	float tri_strip[] = {
-		-1.0, -1.0,     0, h,
-		-1.0,  1.0,     0, 0,
-		 1.0, -1.0,     w, h,
-		 1.0,  1.0,     w, 0
-	};
-	video->vertex_buffer = buffer_new(sizeof(tri_strip), tri_strip);
-
-	drawable_p video2 = drawable_new(GL_TRIANGLE_STRIP, "shaders/video.vs", "shaders/video.fs");
-	video2->texture = texture_new(w2, h2, GL_RG8);
-	float tri_strip2[] = {
-		0.25, -1.0,        0, h2,
-		0.25, -0.4375,     0,  0,
-		 1.0, -1.0,       w2, h2,
-		 1.0, -0.4375,    w2,  0
-	};
-	video2->vertex_buffer = buffer_new(sizeof(tri_strip2), tri_strip2);
-	*/
-
 	// Setup sound input and output
-	size_t latency = 5;
-
-	sound_p in = sound_open(argv[1], SOUND_CAPTURE, SOUND_NONBLOCK);
-	sound_configure(in, 48000, 2, SOUND_FORMAT_S16, true, latency);
-
-	sound_p out = sound_open("default", SOUND_PLAYBACK, SOUND_NONBLOCK);
-	sound_configure(out, 48000, 2, SOUND_FORMAT_S16, true, latency);
-
-	size_t buffer_size = in->buffer_size;
-	size_t buffer_filled = 0;
-	void* buffer = malloc(in->buffer_size);
-
-	// Startup
+
+
+	// Init local server
 	server_start(cw, ch);
+	mainloop->io_new(mainloop, server_fd, PA_IO_EVENT_INPUT, server_accept_cb, NULL);
+
+
+	// Start everything up
 	for(size_t i = 0; i < video_input_count; i++)
 		cam_stream_start(video_inputs[i].cam, 2);

-	// Prepare mainloop
-	size_t poll_fd_count = 1 + video_input_count + sound_poll_fds_count(in) + sound_poll_fds_count(out);
-	struct pollfd pollfds[poll_fd_count];
-
-	timeval_t mark;
+
+	// Do the loop
 	uint32_t start_ms = SDL_GetTicks();
-	size_t overruns = 0, underruns = 0, flushes = 0;
-	bool exit_mainloop = false;
-	size_t scene_idx = 0;
-	while (!exit_mainloop) {
-
-		// Handle SLD events
-		time_mark(&mark);
-			SDL_Event event;
-			while ( SDL_PollEvent(&event) ) {
-				if (event.type == SDL_QUIT) {
-					exit_mainloop = true;
-					break;
-				}
-
-				if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) {
-					ww = event.window.data1;
-					wh = event.window.data2;
-				}
-
-				if (event.type == SDL_KEYDOWN && event.key.keysym.sym >= SDLK_1 && event.key.keysym.sym <= SDLK_9) {
-					size_t num = event.key.keysym.sym - SDLK_1;
-					if (num < scene_count) {
-						printf("switching to scene %zu\n", num);
-						scene_idx = num;
-					}
-				}
-				/*
-				if (event.type == SDL_KEYDOWN) {
-					switch (event.key.keysym.sym) {
-						case SDLK_1:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "0" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_2:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "2" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_3:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "3" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_4:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "4" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_5:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "5" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_6:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "6" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_7:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "7" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_8:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "8" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_9:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "9" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-						case SDLK_0:
-							set_controls(cam, (cam_control_t[]){ (cam_control_t){ "Zoom, Absolute", "10" }, (cam_control_t){ NULL } } );
-							cam_print_info(cam);
-							break;
-					}
-				}
-				*/
-			}
-		double sdl_time = time_mark(&mark);
-
-		// Setup and do the poll
-		time_mark(&mark);
-			size_t poll_fds_used = 0;
-
-			pollfds[0] = (struct pollfd){ .fd = server_fd, .events = POLLIN, .revents = 0 };
-			poll_fds_used++;
-
-			for(size_t i = 0; i < video_input_count; i++) {
-				video_input_p vi = &video_inputs[i];
-				pollfds[1 + i] = (struct pollfd){ .fd = vi->cam->fd, .events = POLLIN, .revents = 0 };
-				poll_fds_used++;
-			}
-
-			struct pollfd* in_poll_fds = pollfds + poll_fds_used;
-			size_t in_poll_fd_count = sound_poll_fds(in,  pollfds + poll_fds_used, poll_fd_count - poll_fds_used);
-			poll_fds_used += in_poll_fd_count;
-
-			struct pollfd* out_poll_fds = pollfds + poll_fds_used;
-			size_t out_poll_fd_count = sound_poll_fds(out, pollfds + poll_fds_used, poll_fd_count - poll_fds_used);
-			poll_fds_used += out_poll_fd_count;
-
-			int active_fds = poll(pollfds, poll_fds_used, -1);
-			if (active_fds == -1) {
-				perror("poll");
-				continue;
-			}
-		double poll_time = time_mark(&mark);
-
-
-		double read_time = 0, write_time = 0;
-		double cam_time = 0, tex_update_time = 0, draw_time = 0, swap_time = 0;
-		ssize_t bytes_read = 0, bytes_written = 0;
-
-		// Read and write pending audio data
-		uint16_t in_revents  = sound_poll_fds_revents(in,  in_poll_fds,  in_poll_fd_count);
-		uint16_t out_revents = sound_poll_fds_revents(out, out_poll_fds, out_poll_fd_count);
-
-		if (in_revents & POLLIN) {
-			mark = time_now();
-
-			while( (bytes_read = sound_read(in, buffer + buffer_filled, buffer_size - buffer_filled)) < 0 ) {
-				sound_recover(in, bytes_read);
-				overruns++;
-			}
-			server_write_frame(2, SDL_GetTicks() - start_ms, buffer + buffer_filled, bytes_read);
-			buffer_filled += bytes_read;
-
-			read_time = time_mark(&mark);
-		}
-
-		if (out_revents & POLLOUT) {
-			mark = time_now();
-
-			while( (bytes_written = sound_write(out, buffer, buffer_filled)) < 0 ) {
-				sound_recover(out, bytes_written);
-				underruns++;
-			}
-
-			if (bytes_written < (ssize_t)buffer_filled) {
-				// Samples still left in buffer, move to front of buffer.
-				memmove(buffer, buffer + bytes_written, buffer_filled - bytes_written);
-				buffer_filled = buffer_filled - bytes_written;
-			} else {
-				buffer_filled = 0;
-			}
-
-			write_time = time_mark(&mark);
-		}
-
-		// Flush the buffer if underruns cause the sample to queue up and create latency.
-		if (buffer_filled > buffer_size / 2) {
-			buffer_filled = 0;
-			flushes++;
-		}
-
-		// Upload new video frames to the GPU
-		bool something_to_render = false;
-		for(size_t i = 0; i < video_input_count; i++) {
-			video_input_p vi = &video_inputs[i];
-
-			if (pollfds[1 + i].revents & POLLIN) {
-				mark = time_now();
-
-				cam_buffer_t frame = cam_frame_get(vi->cam);
-				cam_time += time_mark(&mark);
-
-				texture_update(vi->tex, GL_RG, frame.ptr);
-				tex_update_time += time_mark(&mark);
-
-				cam_frame_release(vi->cam);
-
-				something_to_render = true;
-			}
-		}
-
-		// Render new video frames
+	while ( pa_mainloop_iterate(poll_mainloop, true, NULL) >= 0 ) {
+		// Render new video frames if one or more frames have been uploaded
 		if (something_to_render) {
 			video_view_p scene = scenes[scene_idx];
-			mark = time_now();

 			fbo_bind(composite_video);
 				glClearColor(0, 0, 0, 0);
@@ -730,17 +549,11 @@
 			glViewport(0, 0, ww, wh);

 			drawable_draw(gui);
-			draw_time = time_mark(&mark);

 			SDL_GL_SwapWindow(win);
-			swap_time = time_mark(&mark);
-		}
-
-		// Accept new clients
-		if (pollfds[0].revents & POLLIN)
-			server_accept();
-
-
+		}
+	}
+
 		// Output stats
 		/*
 		printf("poll: %zu fds, %d active, %4.1lf ms  ", poll_fds_used, active_fds, poll_time);
@@ -756,10 +569,8 @@

 		//printf("poll: %.1lf ms (%.1lf fps), cam: %.1lf ms, tex update: %.1lf ms, draw: %.1lf ms, swap: %.1lf\n",
 		//	poll_time, 1000.0 / poll_time, frame_time, tex_update_time, draw_time, swap_time);
-	}
-
-	sound_close(in);
-	sound_close(out);
+
+	server_close();

 	for(size_t i = 0; i < video_input_count; i++) {
 		video_input_p vi = &video_inputs[i];
@@ -777,8 +588,6 @@
 		}
 	}

-	server_close();
-
 	drawable_destroy(stream);
 	drawable_destroy(gui);
 	drawable_destroy(video_on_composite);
@@ -791,5 +600,110 @@
 	SDL_GL_DeleteContext(gl_ctx);
 	SDL_DestroyWindow(win);

+	pa_mainloop_free(poll_mainloop);
+	signals_cleanup(signal_fd);
+
 	return 0;
+}
+
+
+
+//
+// Signal handling
+//
+
+static int signals_init() {
+	// Setup SIGINT and SIGTERM to terminate our poll loop. For that we read them via a signal fd.
+	// To prevent the signals from interrupting our process we need to block them first.
+	sigset_t signal_mask;
+	sigemptyset(&signal_mask);
+	sigaddset(&signal_mask, SIGINT);
+	sigaddset(&signal_mask, SIGTERM);
+
+	if ( sigprocmask(SIG_BLOCK, &signal_mask, NULL) == -1 )
+		return perror("sigprocmask"), -1;
+
+	int signals = signalfd(-1, &signal_mask, SFD_NONBLOCK | SFD_CLOEXEC);
+	if (signals == -1) {
+		perror("signalfd");
+
+		if ( sigprocmask(SIG_UNBLOCK, &signal_mask, NULL) == -1 )
+			perror("sigprocmask");
+
+		return -1;
+	}
+
+	return signals;
+}
+
+static int signals_cleanup(int signal_fd) {
+	close(signal_fd);
+
+	sigset_t signal_mask;
+	sigemptyset(&signal_mask);
+	sigaddset(&signal_mask, SIGINT);
+	sigaddset(&signal_mask, SIGTERM);
+	if ( sigprocmask(SIG_UNBLOCK, &signal_mask, NULL) == -1 )
+		return perror("sigprocmask"), -1;
+
+	return 1;
+}
+
+
+
+//
+// Event handling callbacks.
+//
+
+// Called when a signal is received
+static void signals_cb(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
+	struct signalfd_siginfo siginfo = {0};
+
+	if ( read(fd, &siginfo, sizeof(siginfo)) == -1 ) {
+		perror("read(signalfd)");
+		return;
+	}
+
+	mainloop->quit(mainloop, 0);
+}
+
+// Called periodically to handle pending SDL events
+static void sdl_event_check_cb(pa_mainloop_api *mainloop, pa_time_event *e, const struct timeval *tv, void *userdata) {
+	SDL_Event event;
+	while ( SDL_PollEvent(&event) ) {
+		if (event.type == SDL_QUIT) {
+			mainloop->quit(mainloop, 0);
+			break;
+		}
+
+		if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) {
+			ww = event.window.data1;
+			wh = event.window.data2;
+		}
+
+		if (event.type == SDL_KEYDOWN && event.key.keysym.sym >= SDLK_1 && event.key.keysym.sym <= SDLK_9) {
+			size_t num = event.key.keysym.sym - SDLK_1;
+			if (num < scene_count) {
+				printf("switching to scene %zu\n", num);
+				scene_idx = num;
+			}
+		}
+	}
+
+	// Restart the timer for the next time
+	struct timeval now = { 0 }, interval = {0, 25*1000}, next_sdl_check_time = { 0 };
+	gettimeofday(&now, NULL);
+	timeradd(&now, &interval, &next_sdl_check_time);
+	mainloop->time_restart(e, &next_sdl_check_time);
+}
+
+// Upload new video frames to the GPU
+static void camera_frame_cb(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
+	video_input_p video_input = userdata;
+
+	cam_buffer_t frame = cam_frame_get(video_input->cam);
+		texture_update(video_input->tex, GL_RG, frame.ptr);
+	cam_frame_release(video_input->cam);
+
+	something_to_render = true;
 }


don't load rpi functions unless bcm_host loads

--- src/glx/glx.c
+++ src/glx/glx.c
@@ -225,10 +225,12 @@

     env(LIBGL_XREFRESH, g_xrefresh, "xrefresh will be called on cleanup");
     env(LIBGL_STACKTRACE, g_stacktrace, "stacktrace will be printed on crash");
-    bcm_host_init = dlsym(bcm_host, "bcm_host_init");
-    bcm_host_deinit = dlsym(bcm_host, "bcm_host_deinit");
-    if (bcm_host_init && bcm_host_deinit)
-        g_bcmhost = true;
+    if (bcm_host) {
+        bcm_host_init = dlsym(bcm_host, "bcm_host_init");
+        bcm_host_deinit = dlsym(bcm_host, "bcm_host_deinit");
+        if (bcm_host_init && bcm_host_deinit)
+            g_bcmhost = true;
+    }
     if (g_xrefresh || g_stacktrace || g_bcmhost) {
         // TODO: a bit gross. Maybe look at this: http://stackoverflow.com/a/13290134/293352
         signal(SIGBUS, signal_handler);


fixed typo.

fixed typo.

--- src/grntest.c
+++ src/grntest.c
@@ -1258,7 +1258,7 @@
     }
   }
   if (grntest_detail_on) {
-    fprintf(grntest_logfp, "\"detail\" :[\n");
+    fprintf(grntest_logfp, "\"detail\": [\n");
   }

   thread_main(ctx, task_num);


Fix indent

Fix indent

--- src/groonga.c
+++ src/groonga.c
@@ -3230,7 +3230,7 @@
       }
       COND_SIGNAL(q_cond);
     }
-  CRITICAL_SECTION_LEAVE(q_critical_section);
+    CRITICAL_SECTION_LEAVE(q_critical_section);
   }
 }


http: return "400 Bad Request" for invalid argument error

--- src/groonga.c
+++ src/groonga.c
@@ -672,10 +672,16 @@
   } else {
     GRN_BULK_REWIND(outbuf);
     output_envelope(ctx, expr_rc, &head, outbuf, &foot);
-    if (expr_rc == GRN_NO_SUCH_FILE_OR_DIRECTORY) {
+    switch (expr_rc) {
+    case GRN_INVALID_ARGUMENT :
+      GRN_TEXT_SETS(ctx, body, "HTTP/1.1 400 Bad Request\r\n");
+      break;
+    case GRN_NO_SUCH_FILE_OR_DIRECTORY :
       GRN_TEXT_SETS(ctx, body, "HTTP/1.1 404 Not Found\r\n");
-    } else {
+      break;
+    default :
       GRN_TEXT_SETS(ctx, body, "HTTP/1.1 500 Internal Server Error\r\n");
+      break;
     }
     GRN_TEXT_PUTS(ctx, body, "Content-Type: ");
     GRN_TEXT_PUTS(ctx, body, grn_ctx_get_mime_type(ctx));


tone down warning to avoid junk in the system log. closes #125

--- hgd-netd.c
+++ hgd-netd.c
@@ -1074,7 +1074,7 @@
 	if (correct_desp == NULL) {
 		DPRINTF(HGD_D_DEBUG, "Despatching '%s' handler", tokens[0]);

-		DPRINTF(HGD_D_WARN, "Invalid command");
+		DPRINTF(HGD_D_INFO, "Invalid command");
 		hgd_sock_send_line(sess->sock_fd, sess->ssl,
 		    "err|" HGD_RESP_E_INVCMD);
 		num_bad_commands++;
@@ -1095,7 +1095,7 @@
 	if ((crypto_pref == HGD_CRYPTO_PREF_ALWAYS) &&
 	    (correct_desp->secure) &&
 	    (sess->ssl == NULL)) {
-		DPRINTF(HGD_D_WARN, "Client '%s' is trying to bypass SSL",
+		DPRINTF(HGD_D_INFO, "Client '%s' is trying to bypass SSL",
 		    sess->cli_str);
 		hgd_sock_send_line(sess->sock_fd, sess->ssl,
 		    "err|" HGD_RESP_E_SSLREQ);
@@ -1105,7 +1105,7 @@

 	/* user should be authenticated for some comands */
 	if (correct_desp->auth_needed && sess->user == NULL) {
-		DPRINTF(HGD_D_DEBUG, "User not authenticated to use '%s'",
+		DPRINTF(HGD_D_INFO, "User not authenticated to use '%s'",
 		    correct_desp->cmd);
 		hgd_sock_send_line(sess->sock_fd, sess->ssl,
 		    "err|" HGD_RESP_E_DENY);
@@ -1119,8 +1119,8 @@
 		    "expecting %d, got %d",
 		    correct_desp->authlevel, sess->user->perms);
 		if (!(sess->user->perms & correct_desp->authlevel)) {
-			DPRINTF(HGD_D_WARN,
-			    "Client '%s' is trying to invoke admin  commands",
+			DPRINTF(HGD_D_INFO,
+			    "'%s': unauthorised use of admin command",
 			    sess->cli_str);
 			hgd_sock_send_line(sess->sock_fd, sess->ssl,
 			    "err|" HGD_RESP_E_DENY);
@@ -1177,7 +1177,7 @@
 		exit = hgd_parse_line(&sess, recv_line);
 		free(recv_line);
 		if (num_bad_commands >= HGD_MAX_BAD_COMMANDS) {
-			DPRINTF(HGD_D_WARN,"Client abused server, "
+			DPRINTF(HGD_D_INFO,"Client abused server, "
 			    "kicking '%s'", sess.cli_str);
 			/* laters */
 			hgd_sock_send_line(cli_fd, sess.ssl,


[GC] --gc-debug was to restrictive

[GC] --gc-debug was to restrictive

* allocating  just 1 PObj (PMC,STRING,Buffer) per memory pool,
  if --gc_debug is set, isn't really a good strategy for running
  more than a PIR one-line (tcl tests were totally starved with it)

git-svn-id: 6e74a02f85675cec270f5d931b0f6998666294a3@14336 d31e2699-5ff4-0310-a27c-f18f2fbe73fe

--- src/headers.c
+++ src/headers.c
@@ -17,9 +17,6 @@
 #include "parrot/parrot.h"
 #include <assert.h>

-#define GC_DEBUG_PMC_HEADERS_PER_ALLOC 1
-#define GC_DEBUG_BUFFER_HEADERS_PER_ALLOC 1
-#define GC_DEBUG_STRING_HEADERS_PER_ALLOC 1
 #ifndef GC_IS_MALLOC
 #  define PMC_HEADERS_PER_ALLOC 512
 #  define BUFFER_HEADERS_PER_ALLOC 256
@@ -85,8 +82,7 @@
 struct Small_Object_Pool *
 new_pmc_pool(Interp *interpreter)
 {
-    int num_headers = GC_DEBUG(interpreter) ?
-        GC_DEBUG_PMC_HEADERS_PER_ALLOC : PMC_HEADERS_PER_ALLOC;
+    int num_headers = PMC_HEADERS_PER_ALLOC;
     struct Small_Object_Pool *pmc_pool =
         new_small_object_pool(interpreter, sizeof(PMC), num_headers);

@@ -112,8 +108,7 @@
 new_bufferlike_pool(Interp *interpreter,
         size_t actual_buffer_size)
 {
-    int num_headers = GC_DEBUG(interpreter) ?
-            GC_DEBUG_BUFFER_HEADERS_PER_ALLOC : BUFFER_HEADERS_PER_ALLOC;
+    int num_headers = BUFFER_HEADERS_PER_ALLOC;
     size_t buffer_size =
             (actual_buffer_size + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
     struct Small_Object_Pool *pool =
@@ -162,8 +157,7 @@
     }
     else
         pool = make_bufferlike_pool(interpreter, sizeof(STRING));
-    pool->objects_per_alloc = GC_DEBUG(interpreter) ?
-            GC_DEBUG_STRING_HEADERS_PER_ALLOC : STRING_HEADERS_PER_ALLOC;
+    pool->objects_per_alloc = STRING_HEADERS_PER_ALLOC;
     return pool;
 }


Fix error if DOD is invoked when a sized_header_pool exists but has no memory allocated.

git-svn-id: 6e74a02f85675cec270f5d931b0f6998666294a3@4943 d31e2699-5ff4-0310-a27c-f18f2fbe73fe

--- src/headers.c
+++ src/headers.c
@@ -278,7 +278,8 @@
             start_arena_memory;

     for (i = 0; i < interpreter->arena_base->num_sized; i++) {
-        if (interpreter->arena_base->sized_header_pools[i]) {
+        if (interpreter->arena_base->sized_header_pools[i] &&
+            interpreter->arena_base->sized_header_pools[i]->start_arena_memory) {
             if (min > interpreter->arena_base->
                     sized_header_pools[i]->start_arena_memory)
                 min = interpreter->arena_base->sized_header_pools[i]->


Use macros to reduce code duplication

Use macros to reduce code duplication

--- src/hirlite.c
+++ src/hirlite.c
@@ -18,6 +18,25 @@
 #include "rlite/pubsub.h"

 #define UNSIGN(val) ((unsigned char *)val)
+
+#define CHECK_END()\
+	if (retval != RL_END) {\
+		__rliteSetError(c->context, RLITE_ERR, "Unexpected early end");\
+		goto cleanup;\
+	}
+
+#define CHECK_OOM_ELSE(item, els)\
+	if (!(item)) {\
+		els;\
+		__rliteSetError(c->context,RLITE_ERR_OOM,"Out of memory");\
+		retval = RL_OUT_OF_MEMORY;\
+		goto cleanup;\
+	}
+
+#define CHECK_OOM(item) CHECK_OOM_ELSE(item, );
+
+#define MALLOC(target, size)\
+	CHECK_OOM(target = rl_malloc(size));

 #define RLITE_SERVER_ERR(c, retval)\
 	if (retval == RL_WRONG_TYPE) {\
@@ -163,45 +182,24 @@
 	long vlen, i;
 	double score;

-	c->reply = createReplyObject(RLITE_REPLY_ARRAY);
-	if (!c->reply) {
-		__rliteSetError(c->context,RLITE_ERR_OOM,"Out of memory");
-		goto cleanup;
-	}
+	CHECK_OOM(c->reply = createReplyObject(RLITE_REPLY_ARRAY));
 	if (retval == RL_NOT_FOUND) {
 		c->reply->elements = 0;
 		return;
 	}
 	c->reply->elements = withscores ? (iterator->size * 2) : iterator->size;
-	c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
-	if (!c->reply->element) {
-		c->reply->elements = 0;
-		rliteFreeReplyObject(c);
-		__rliteSetError(c->context,RLITE_ERR_OOM,"Out of memory");
-		goto cleanup;
-	}
+	MALLOC(c->reply->element, sizeof(rliteReply*) * c->reply->elements);
 	i = 0;
 	while ((retval = rl_zset_iterator_next(iterator, NULL, withscores ? &score : NULL, &vstr, &vlen)) == RL_OK) {
-		c->reply->element[i] = createTakeStringObject((char *)vstr, vlen);
-		if (!c->reply->element[i]) {
-			__rliteSetError(c->context,RLITE_ERR_OOM,"Out of memory");
-			goto cleanup;
-		}
+		CHECK_OOM(c->reply->element[i] = createTakeStringObject((char *)vstr, vlen));
 		i++;
 		if (withscores) {
-			c->reply->element[i] = createDoubleObject(score);
-			if (!c->reply->element[i]) {
-				__rliteSetError(c->context,RLITE_ERR_OOM,"Out of memory");
-				goto cleanup;
-			}
+			CHECK_OOM(c->reply->element[i] = createDoubleObject(score));
 			i++;
 		}
 	}

-	if (retval != RL_END) {
-		__rliteSetError(c->context, RLITE_ERR, "Unexpected early end");
-		goto cleanup;
-	}
+	CHECK_END();
 	iterator = NULL;
 cleanup:
 	if (iterator) {
@@ -848,7 +846,7 @@
 		return;
 	}
 	c->reply->elements = c->context->enqueuedCommandsLength;
-	c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
+	MALLOC(c->reply->element, sizeof(rliteReply*) * c->reply->elements);
 	rliteClient *client;
 	struct rliteCommand *command;
 	for (i = 0; i < c->reply->elements; i++) {
@@ -923,12 +921,8 @@
 		while (newAlloc < watchc + c->context->watchedKeysLength) {
 			newAlloc *= 2;
 		}
-		tmp = rl_realloc(c->context->watchedKeys, sizeof(struct watched_key*) * newAlloc);
-		if (tmp == NULL) {
-			c->reply = NULL;
-			__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-			return;
-		}
+		CHECK_OOM_ELSE(tmp = rl_realloc(c->context->watchedKeys, sizeof(struct watched_key*) * newAlloc),
+				c->reply = NULL);
 		c->context->watchedKeysAlloc = newAlloc;
 		c->context->watchedKeys = tmp;
 	}
@@ -1005,100 +999,76 @@
 	}
 }

-int rliteAppendCommandClient(rliteClient *client) {
-	if (client->argc == 0) {
+int rliteAppendCommandClient(rliteClient *c) {
+	if (c->argc == 0) {
 		return RLITE_ERR;
 	}

 	unsigned char *oldhash = NULL, *newhash = NULL;
 	void *tmp;
 	size_t newAlloc;
-	struct rliteCommand *command = rliteLookupCommand(client->argv[0], client->argvlen[0]);
+	struct rliteCommand *command = rliteLookupCommand(c->argv[0], c->argvlen[0]);
 	int i, retval = RLITE_OK;
 	if (!command) {
-		retval = addReplyErrorFormat(client->context, "unknown command '%s'", (char*)client->argv[0]);
-		flagTransactions(client);
-	} else if ((command->arity > 0 && command->arity != client->argc) ||
-		(client->argc < -command->arity)) {
-		retval = addReplyErrorFormat(client->context, "wrong number of arguments for '%s' command", command->name);
-		flagTransactions(client);
+		retval = addReplyErrorFormat(c->context, "unknown command '%s'", (char*)c->argv[0]);
+		flagTransactions(c);
+	} else if ((command->arity > 0 && command->arity != c->argc) ||
+		(c->argc < -command->arity)) {
+		retval = addReplyErrorFormat(c->context, "wrong number of arguments for '%s' command", command->name);
+		flagTransactions(c);
 	} else {
-		RL_CALL(refresh_rlite_fp, RL_OK, client->context);
-
-		if (client->context->inTransaction && (command->proc != execCommand && command->proc != discardCommand &&
+		RL_CALL(refresh_rlite_fp, RL_OK, c->context);
+
+		if (c->context->inTransaction && (command->proc != execCommand && command->proc != discardCommand &&
 					command->proc != multiCommand && command->proc != watchCommand)) {
-			if (client->context->enqueuedCommandsLength == client->context->enqueuedCommandsAlloc) {
-				newAlloc = client->context->enqueuedCommandsAlloc * 2;
+			if (c->context->enqueuedCommandsLength == c->context->enqueuedCommandsAlloc) {
+				newAlloc = c->context->enqueuedCommandsAlloc * 2;
 				if (newAlloc == 0) {
 					newAlloc = 4;
 				}
-				tmp = rl_realloc(client->context->enqueuedCommands, sizeof(rliteClient *) * newAlloc);
-				if (!tmp) {
-					retval = RL_OUT_OF_MEMORY;
-					__rliteSetError(client->context, RLITE_ERR_OOM, "Out of memory");
-					goto cleanup;
-				}
-				client->context->enqueuedCommands = tmp;
-				client->context->enqueuedCommandsAlloc = newAlloc;
+				CHECK_OOM(tmp = rl_realloc(c->context->enqueuedCommands, sizeof(rliteClient *) * newAlloc));
+				c->context->enqueuedCommands = tmp;
+				c->context->enqueuedCommandsAlloc = newAlloc;
 			}
-			client->context->enqueuedCommands[client->context->enqueuedCommandsLength] = rl_malloc(sizeof(rliteClient));
-			client->context->enqueuedCommands[client->context->enqueuedCommandsLength]->flags = 0;
-			if (!client->context->enqueuedCommands[client->context->enqueuedCommandsLength]) {
-				retval = RL_OUT_OF_MEMORY;
-				__rliteSetError(client->context, RLITE_ERR_OOM, "Out of memory");
-				goto cleanup;
+
+			MALLOC(c->context->enqueuedCommands[c->context->enqueuedCommandsLength], sizeof(rliteClient));
+			c->context->enqueuedCommands[c->context->enqueuedCommandsLength]->flags = 0;
+#define COMMAND c->context->enqueuedCommands[c->context->enqueuedCommandsLength]
+			COMMAND->argc = c->argc;
+			MALLOC(COMMAND->argvlen, sizeof(size_t) * c->argc);
+			CHECK_OOM_ELSE(COMMAND->argv = rl_malloc(sizeof(char *) * c->argc),
+					rl_free(COMMAND->argvlen));
+			for (i = 0; i < c->argc; i++) {
+				COMMAND->argvlen[i] = c->argvlen[i];
+				// TODO free argv
+				MALLOC(COMMAND->argv[i], sizeof(char) * (c->argvlen[i] + 1));
+				memcpy(COMMAND->argv[i], c->argv[i], c->argvlen[i]);
+				COMMAND->argv[i][c->argvlen[i]] = 0;
 			}
-#define COMMAND client->context->enqueuedCommands[client->context->enqueuedCommandsLength]
-			COMMAND->argc = client->argc;
-			COMMAND->argvlen = rl_malloc(sizeof(size_t) * client->argc);
-			if (!COMMAND->argvlen) {
-				retval = RL_OUT_OF_MEMORY;
-				__rliteSetError(client->context, RLITE_ERR_OOM, "Out of memory");
-				goto cleanup;
+
+			c->context->enqueuedCommands[c->context->enqueuedCommandsLength]->context = c->context;
+			c->context->enqueuedCommandsLength++;
+			c->reply = createStatusObject(RLITE_QUEUED);
+			retval = addReply(c->context, c->reply);
+		} else {
+			c->reply = NULL;
+
+			if (c->context->writeCommand) {
+				RL_CALL(rl_dirty_hash, RL_OK, c->context->db, &oldhash);
 			}
-			COMMAND->argv = rl_malloc(sizeof(char *) * client->argc);
-			if (!COMMAND->argv) {
-				rl_free(COMMAND->argvlen);
-				retval = RL_OUT_OF_MEMORY;
-				__rliteSetError(client->context, RLITE_ERR_OOM, "Out of memory");
-				goto cleanup;
+
+			command->proc(c);
+			if (c->reply) {
+				retval = addReply(c->context, c->reply);
 			}
-			for (i = 0; i < client->argc; i++) {
-				COMMAND->argvlen[i] = client->argvlen[i];
-				COMMAND->argv[i] = rl_malloc(sizeof(char) * (client->argvlen[i] + 1));
-				if (!COMMAND->argv[i]) {
-					// TODO free argv
-					retval = RL_OUT_OF_MEMORY;
-					__rliteSetError(client->context, RLITE_ERR_OOM, "Out of memory");
-					goto cleanup;
-				}
-				memcpy(COMMAND->argv[i], client->argv[i], client->argvlen[i]);
-				COMMAND->argv[i][client->argvlen[i]] = 0;
-			}
-
-			client->context->enqueuedCommands[client->context->enqueuedCommandsLength]->context = client->context;
-			client->context->enqueuedCommandsLength++;
-			client->reply = createStatusObject(RLITE_QUEUED);
-			retval = addReply(client->context, client->reply);
-		} else {
-			client->reply = NULL;
-
-			if (client->context->writeCommand) {
-				RL_CALL(rl_dirty_hash, RL_OK, client->context->db, &oldhash);
-			}
-
-			command->proc(client);
-			if (client->reply) {
-				retval = addReply(client->context, client->reply);
-			}
-
-			if (client->context->writeCommand) {
-				RL_CALL(rl_dirty_hash, RL_OK, client->context->db, &newhash);
+
+			if (c->context->writeCommand) {
+				RL_CALL(rl_dirty_hash, RL_OK, c->context->db, &newhash);
 				if (newhash && (!oldhash || memcmp(newhash, oldhash, 20) != 0)) {
-					client->context->writeCommand(rl_get_selected_db(client->context->db), client->argc, client->argv, client->argvlen);
+					c->context->writeCommand(rl_get_selected_db(c->context->db), c->argc, c->argv, c->argvlen);
 				}
 			}
-			RL_CALL(rl_commit, RL_OK, client->context->db);
+			RL_CALL(rl_commit, RL_OK, c->context->db);
 		}
 	}
 cleanup:
@@ -1193,6 +1163,7 @@
 	double score = 0, *scores = NULL;
 	int j, elements = (c->argc - 2) / 2;
 	int added = 0;
+	int retval;

 	if (c->argc % 2) {
 		c->reply = createErrorObject(RLITE_SYNTAXERR);
@@ -1202,17 +1173,12 @@
 	/* Start parsing all the scores, we need to emit any syntax error
 	 * before executing additions to the sorted set, as the command should
 	 * either execute fully or nothing at all. */
-	scores = rl_malloc(sizeof(double) * elements);
-	if (!scores) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(scores, sizeof(double) * elements);
 	for (j = 0; j < elements; j++) {
 		if (getDoubleFromObjectOrReply(c, c->argv[2+j*2], c->argvlen[2+j*2], &scores[j],NULL)
 			!= RLITE_OK) goto cleanup;
 	}

-	int retval;
 	for (j = 0; j < elements; j++) {
 		score = scores[j];
 		if (incr) {
@@ -1276,18 +1242,16 @@
 	const size_t keylen = c->argvlen[1];
 	long deleted = 0;
 	int j;
+	int retval;

 	// memberslen needs long, we have size_t (unsigned long)
 	// it would be great not to need this
-	long *memberslen = rl_malloc(sizeof(long) * (c->argc - 2));
-	if (!memberslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	long *memberslen;
+	MALLOC(memberslen, sizeof(long) * (c->argc - 2));
 	for (j = 2; j < c->argc; j++) {
 		memberslen[j - 2] = c->argvlen[j];
 	}
-	int retval = rl_zrem(c->context->db, key, keylen, c->argc - 2, (unsigned char **)&c->argv[2], memberslen, &deleted);
+	retval = rl_zrem(c->context->db, key, keylen, c->argc - 2, (unsigned char **)&c->argv[2], memberslen, &deleted);
 	rl_free(memberslen);
 	RLITE_SERVER_ERR(c, retval);

@@ -1388,6 +1352,7 @@
 	double *weights = NULL;
 	unsigned char **keys = NULL;
 	long *keys_len = NULL;
+	int retval;

 	/* expect setnum input keys to be given */
 	if ((getLongFromObjectOrReply(c, c->argv[2], c->argvlen[2], &setnum, NULL) != RLITE_OK))
@@ -1411,11 +1376,7 @@
 				c->reply = createErrorObject(RLITE_SYNTAXERR);
 				return;
 			}
-			weights = rl_malloc(sizeof(double) * setnum);
-			if (!weights) {
-				__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-				return;
-			}
+			MALLOC(weights, sizeof(double) * setnum);
 			for (i = 0; i < setnum; i++) {
 				if (getDoubleFromObjectOrReply(c,c->argv[j + 1 + i],c->argvlen[j + 1 + i], &weights[i],
 						"weight value is not a float") != RLITE_OK) {
@@ -1443,23 +1404,15 @@
 		}
 	}

-	keys = rl_malloc(sizeof(unsigned char *) * (1 + setnum));
-	if (!keys) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	keys_len = rl_malloc(sizeof(long) * (1 + setnum));
-	if (!keys_len) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(keys, sizeof(unsigned char *) * (1 + setnum));
+	MALLOC(keys_len, sizeof(long) * (1 + setnum));
 	keys[0] = UNSIGN(c->argv[1]);
 	keys_len[0] = (long)c->argvlen[1];
 	for (i = 0; i < setnum; i++) {
 		keys[i + 1] = UNSIGN(c->argv[3 + i]);
 		keys_len[i + 1] = c->argvlen[3 + i];
 	}
-	int retval = (op == RLITE_OP_UNION ? rl_zunionstore : rl_zinterstore)(c->context->db, setnum + 1, keys, keys_len, weights, aggregate);
+	retval = (op == RLITE_OP_UNION ? rl_zunionstore : rl_zinterstore)(c->context->db, setnum + 1, keys, keys_len, weights, aggregate);
 	RLITE_SERVER_ERR(c, retval);
 	zcardCommand(c);
 cleanup:
@@ -1713,26 +1666,11 @@
 	unsigned char **values = NULL;
 	long *valueslen = NULL;

-	fields = rl_malloc(sizeof(unsigned char *) * fieldc);
-	if (!fields) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	fieldslen = rl_malloc(sizeof(long) * fieldc);
-	if (!fieldslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	values = rl_malloc(sizeof(unsigned char *) * fieldc);
-	if (!values) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	valueslen = rl_malloc(sizeof(long) * fieldc);
-	if (!valueslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(fields, sizeof(unsigned char *) * fieldc);
+	MALLOC(fieldslen, sizeof(long) * fieldc);
+	MALLOC(values, sizeof(unsigned char *) * fieldc);
+	MALLOC(valueslen, sizeof(long) * fieldc);
+
 	for (i = 0, j = 2; i < fieldc; i++) {
 		fields[i] = UNSIGN(c->argv[j]);
 		fieldslen[i] = c->argvlen[j++];
@@ -1806,11 +1744,7 @@
 		return;
 	}

-	memberslen = rl_malloc(sizeof(long) * (c->argc - 2));
-	if (!memberslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(memberslen, sizeof(long) * (c->argc - 2));
 	for (j = 3; j < c->argc; j++) {
 		memberslen[j - 3] = c->argvlen[j];
 	}
@@ -1881,11 +1815,8 @@
 	int j, retval;
 	// memberslen needs long, we have size_t (unsigned long)
 	// it would be great not to need this
-	long *memberslen = rl_malloc(sizeof(long) * (c->argc - 2));
-	if (!memberslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	long *memberslen;
+	MALLOC(memberslen, sizeof(long) * (c->argc - 2));
 	for (j = 2; j < c->argc; j++) {
 		memberslen[j - 2] = c->argvlen[j];
 	}
@@ -1963,12 +1894,7 @@
 		return;
 	}
 	c->reply->elements = iterator->size * (fields + values);
-	c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
-	if (!c->reply->element) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		retval = RL_OUT_OF_MEMORY;
-		goto cleanup;
-	}
+	MALLOC(c->reply->element, sizeof(rliteReply*) * c->reply->elements);
 	while ((retval = rl_hash_iterator_next(iterator,
 					NULL, fields ? &field : NULL, fields ? &fieldlen : NULL,
 					NULL, values ? &value : NULL, values ? &valuelen : NULL
@@ -1983,10 +1909,7 @@
 		}
 	}

-	if (retval != RL_END) {
-		__rliteSetError(c->context, RLITE_ERR, "Unexpected early end");
-		goto cleanup;
-	}
+	CHECK_END();
 	retval = RL_OK;
 cleanup:
 	if (retval != RL_OK) {
@@ -2038,46 +1961,37 @@
 	long *fieldslen = NULL;
 	unsigned char **values = NULL;
 	long *valueslen = NULL;
-
-	fields = rl_malloc(sizeof(unsigned char *) * fieldc);
-	if (!fields) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	fieldslen = rl_malloc(sizeof(long) * fieldc);
-	if (!fieldslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	int retval;
+
+	MALLOC(fields, sizeof(unsigned char *) * fieldc);
+	MALLOC(fieldslen, sizeof(long) * fieldc);
 	for (i = 0; i < fieldc; i++) {
 		fields[i] = (unsigned char *)c->argv[2 + i];
 		fieldslen[i] = (long)c->argvlen[2 + i];
 	}

-	int retval = rl_hmget(c->context->db, key, keylen, fieldc, fields, fieldslen, &values, &valueslen);
-	RLITE_SERVER_ERR(c, retval);
-	c->reply = createReplyObject(RLITE_REPLY_ARRAY);
-	if (!c->reply) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	retval = rl_hmget(c->context->db, key, keylen, fieldc, fields, fieldslen, &values, &valueslen);
+	RLITE_SERVER_ERR(c, retval);
+	CHECK_OOM(c->reply = createReplyObject(RLITE_REPLY_ARRAY));
 	c->reply->elements = fieldc;
-	c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
-	if (!c->reply->element) {
-		rl_free(c->reply);
-		c->reply = NULL;
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	CHECK_OOM_ELSE(c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements),
+			rl_free(c->reply); c->reply = NULL);

 	for (i = 0; i < fieldc; i++) {
 		if (retval == RL_NOT_FOUND || valueslen[i] < 0) {
-			c->reply->element[i] = createReplyObject(RLITE_REPLY_NIL);
+			CHECK_OOM(c->reply->element[i] = createReplyObject(RLITE_REPLY_NIL));
 		} else {
-			c->reply->element[i] = createTakeStringObject((char *)values[i], valueslen[i]);
-		}
-	}
-cleanup:
+			CHECK_OOM(c->reply->element[i] = createTakeStringObject((char *)values[i], valueslen[i]));
+		}
+	}
+cleanup:
+	if (retval == RL_OUT_OF_MEMORY) {
+		for (;;i--) {
+			rliteFreeReplyObject(c->reply->element[i]);
+			if (i == 0) break;
+		}
+		c->reply = NULL;
+	}
 	rl_free(fields);
 	rl_free(fieldslen);
 	rl_free(values);
@@ -2088,27 +2002,19 @@
 	unsigned char *key = UNSIGN(c->argv[1]);
 	size_t keylen = c->argvlen[1];

-	int i, memberc = c->argc - 2;
+	int retval, i, memberc = c->argc - 2;
 	unsigned char **members = NULL;
 	long *memberslen = NULL;
 	long count;

-	members = rl_malloc(sizeof(unsigned char *) * memberc);
-	if (!members) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	memberslen = rl_malloc(sizeof(long) * memberc);
-	if (!memberslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(members, sizeof(unsigned char *) * memberc);
+	MALLOC(memberslen, sizeof(long) * memberc);
 	for (i = 0; i < memberc; i++) {
 		members[i] = (unsigned char *)c->argv[2 + i];
 		memberslen[i] = (long)c->argvlen[2 + i];
 	}

-	int retval = rl_sadd(c->context->db, key, keylen, memberc, members, memberslen, &count);
+	retval = rl_sadd(c->context->db, key, keylen, memberc, members, memberslen, &count);
 	RLITE_SERVER_ERR(c, retval);
 	c->reply = createLongLongObject(count);
 cleanup:
@@ -2179,7 +2085,7 @@
 		} else {
 			c->reply = createReplyObject(RLITE_REPLY_ARRAY);
 			c->reply->elements = count;
-			c->reply->element = rl_malloc(sizeof(rliteReply*) * count);
+			MALLOC(c->reply->element, sizeof(rliteReply*) * count);
 			for (i = 0; i < count; i++) {
 				c->reply->element[i] = createStringObject((char *)members[i], memberslen[i]);
 			}
@@ -2201,27 +2107,19 @@
 	unsigned char *key = UNSIGN(c->argv[1]);
 	size_t keylen = c->argvlen[1];

-	int i, memberc = c->argc - 2;
+	int retval, i, memberc = c->argc - 2;
 	unsigned char **members = NULL;
 	long *memberslen = NULL;
 	long count;

-	members = rl_malloc(sizeof(unsigned char *) * memberc);
-	if (!members) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	memberslen = rl_malloc(sizeof(long) * memberc);
-	if (!memberslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(members, sizeof(unsigned char *) * memberc);
+	MALLOC(memberslen, sizeof(long) * memberc);
 	for (i = 0; i < memberc; i++) {
 		members[i] = (unsigned char *)c->argv[2 + i];
 		memberslen[i] = (long)c->argvlen[2 + i];
 	}

-	int retval = rl_srem(c->context->db, key, keylen, memberc, members, memberslen, &count);
+	retval = rl_srem(c->context->db, key, keylen, memberc, members, memberslen, &count);
 	RLITE_SERVER_ERR(c, retval);
 	c->reply = createLongLongObject(count);
 cleanup:
@@ -2234,16 +2132,8 @@
 	unsigned char **keys = NULL, **members = NULL;
 	long *keyslen = NULL, j, membersc, *memberslen = NULL;

-	keys = rl_malloc(sizeof(unsigned char *) * keyc);
-	if (!keys) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	keyslen = rl_malloc(sizeof(long) * keyc);
-	if (!keyslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(keys, sizeof(unsigned char *) * keyc);
+	MALLOC(keyslen, sizeof(long) * keyc);
 	for (i = 0; i < keyc; i++) {
 		keys[i] = UNSIGN(c->argv[1 + i]);
 		keyslen[i] = c->argvlen[1 + i];
@@ -2253,12 +2143,8 @@
 	c->reply = createReplyObject(RLITE_REPLY_ARRAY);
 	c->reply->elements = membersc;
 	if (membersc > 0) {
-		c->reply->element = rl_malloc(sizeof(rliteReply*) * membersc);
-		if (!c->reply->element) {
-			rl_free(c->reply);
-			__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-			goto cleanup;
-		}
+		CHECK_OOM_ELSE(c->reply->element = rl_malloc(sizeof(rliteReply*) * membersc),
+				rl_free(c->reply); c->reply = NULL);
 		for (j = 0; j < membersc; j++) {
 			c->reply->element[j] = createStringObject((char *)members[j], memberslen[j]);
 		}
@@ -2283,16 +2169,8 @@
 	unsigned char *target = UNSIGN(c->argv[1]);
 	long targetlen = c->argvlen[1];

-	keys = rl_malloc(sizeof(unsigned char *) * keyc);
-	if (!keys) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	keyslen = rl_malloc(sizeof(long) * keyc);
-	if (!keyslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(keys, sizeof(unsigned char *) * keyc);
+	MALLOC(keyslen, sizeof(long) * keyc);
 	for (i = 0; i < keyc; i++) {
 		keys[i] = UNSIGN(c->argv[2 + i]);
 		keyslen[i] = c->argvlen[2 + i];
@@ -2311,16 +2189,8 @@
 	unsigned char **keys = NULL, **members = NULL;
 	long *keyslen = NULL, j, membersc, *memberslen = NULL;

-	keys = rl_malloc(sizeof(unsigned char *) * keyc);
-	if (!keys) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	keyslen = rl_malloc(sizeof(long) * keyc);
-	if (!keyslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(keys, sizeof(unsigned char *) * keyc);
+	MALLOC(keyslen, sizeof(long) * keyc);
 	for (i = 0; i < keyc; i++) {
 		keys[i] = UNSIGN(c->argv[1 + i]);
 		keyslen[i] = c->argvlen[1 + i];
@@ -2330,12 +2200,8 @@
 	c->reply = createReplyObject(RLITE_REPLY_ARRAY);
 	c->reply->elements = membersc;
 	if (membersc > 0) {
-		c->reply->element = rl_malloc(sizeof(rliteReply*) * membersc);
-		if (!c->reply->element) {
-			rl_free(c->reply);
-			__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-			goto cleanup;
-		}
+		CHECK_OOM_ELSE(c->reply->element = rl_malloc(sizeof(rliteReply*) * membersc),
+				rl_free(c->reply); c->reply = NULL);
 		for (j = 0; j < membersc; j++) {
 			c->reply->element[j] = createStringObject((char *)members[j], memberslen[j]);
 		}
@@ -2360,16 +2226,8 @@
 	unsigned char *target = UNSIGN(c->argv[1]);
 	long targetlen = c->argvlen[1];

-	keys = rl_malloc(sizeof(unsigned char *) * keyc);
-	if (!keys) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	keyslen = rl_malloc(sizeof(long) * keyc);
-	if (!keyslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(keys, sizeof(unsigned char *) * keyc);
+	MALLOC(keyslen, sizeof(long) * keyc);
 	for (i = 0; i < keyc; i++) {
 		keys[i] = UNSIGN(c->argv[2 + i]);
 		keyslen[i] = c->argvlen[2 + i];
@@ -2388,16 +2246,8 @@
 	unsigned char **keys = NULL, **members = NULL;
 	long *keyslen = NULL, j, membersc, *memberslen = NULL;

-	keys = rl_malloc(sizeof(unsigned char *) * keyc);
-	if (!keys) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	keyslen = rl_malloc(sizeof(long) * keyc);
-	if (!keyslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(keys, sizeof(unsigned char *) * keyc);
+	MALLOC(keyslen, sizeof(long) * keyc);
 	for (i = 0; i < keyc; i++) {
 		keys[i] = UNSIGN(c->argv[1 + i]);
 		keyslen[i] = c->argvlen[1 + i];
@@ -2407,14 +2257,10 @@
 	c->reply = createReplyObject(RLITE_REPLY_ARRAY);
 	c->reply->elements = membersc;
 	if (membersc > 0) {
-		c->reply->element = rl_malloc(sizeof(rliteReply*) * membersc);
-		if (!c->reply->element) {
-			rl_free(c->reply);
-			__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-			goto cleanup;
-		}
+		CHECK_OOM_ELSE(c->reply->element = rl_malloc(sizeof(rliteReply*) * membersc),
+				rl_free(c->reply); c->reply = NULL);
 		for (j = 0; j < membersc; j++) {
-			c->reply->element[j] = createStringObject((char *)members[j], memberslen[j]);
+			CHECK_OOM(c->reply->element[j] = createStringObject((char *)members[j], memberslen[j]));
 		}
 	}
 cleanup:
@@ -2437,16 +2283,8 @@
 	unsigned char *target = UNSIGN(c->argv[1]);
 	long targetlen = c->argvlen[1];

-	keys = rl_malloc(sizeof(unsigned char *) * keyc);
-	if (!keys) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	keyslen = rl_malloc(sizeof(long) * keyc);
-	if (!keyslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(keys, sizeof(unsigned char *) * keyc);
+	MALLOC(keyslen, sizeof(long) * keyc);
 	for (i = 0; i < keyc; i++) {
 		keys[i] = UNSIGN(c->argv[2 + i]);
 		keyslen[i] = c->argvlen[2 + i];
@@ -2464,27 +2302,19 @@
 	unsigned char *key = UNSIGN(c->argv[1]);
 	size_t keylen = c->argvlen[1];

-	int i, valuec = c->argc - 2;
+	int retval, i, valuec = c->argc - 2;
 	unsigned char **values = NULL;
 	long *valueslen = NULL;
 	long count;

-	values = rl_malloc(sizeof(unsigned char *) * valuec);
-	if (!values) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	valueslen = rl_malloc(sizeof(long) * valuec);
-	if (!valueslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(values, sizeof(unsigned char *) * valuec);
+	MALLOC(valueslen, sizeof(long) * valuec);
 	for (i = 0; i < valuec; i++) {
 		values[i] = (unsigned char *)c->argv[2 + i];
 		valueslen[i] = (long)c->argvlen[2 + i];
 	}

-	int retval = rl_push(c->context->db, key, keylen, create, left, valuec, values, valueslen, &count);
+	retval = rl_push(c->context->db, key, keylen, create, left, valuec, values, valueslen, &count);
 	if (retval == RL_NOT_FOUND) {
 		c->reply = createLongLongObject(0);
 	} else {
@@ -2604,13 +2434,13 @@

 	int retval = rl_lrange(c->context->db, key, keylen, start, stop, &size, &values, &valueslen);
 	RLITE_SERVER_ERR(c, retval);
-	c->reply = createReplyObject(RLITE_REPLY_ARRAY);
+	CHECK_OOM(c->reply = createReplyObject(RLITE_REPLY_ARRAY));
 	if (retval == RL_NOT_FOUND) {
 		c->reply->elements = 0;
 		return;
 	}
 	c->reply->elements = size;
-	c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
+	MALLOC(c->reply->element, sizeof(rliteReply*) * c->reply->elements);
 	for (i = 0; i < size; i++) {
 		c->reply->element[i] = createStringObject((char *)values[i], valueslen[i]);
 	}
@@ -2874,13 +2704,8 @@

 	c->reply = createReplyObject(RLITE_REPLY_ARRAY);
 	c->reply->elements = keyc;
-	c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
-	if (!c->reply->element) {
-		rl_free(c->reply);
-		c->reply = NULL;
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	CHECK_OOM_ELSE(c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements),
+			rl_free(c->reply); c->reply = NULL);

 	for (i = 0; i < keyc; i++) {
 		key = (unsigned char *)c->argv[1 + i];
@@ -3178,26 +3003,18 @@
 	int updated;
 	unsigned char **elements = NULL;
 	long *elementslen = NULL;
-	int i, elementc = c->argc - 2;
+	int retval, i, elementc = c->argc - 2;

 	if (elementc > 0) {
-		elements = rl_malloc(sizeof(unsigned char *) * elementc);
-		if (!elements) {
-			__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-			goto cleanup;
-		}
-		elementslen = rl_malloc(sizeof(long) * elementc);
-		if (!elementslen) {
-			__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-			goto cleanup;
-		}
+		MALLOC(elements, sizeof(unsigned char *) * elementc);
+		MALLOC(elementslen, sizeof(long) * elementc);
 		for (i = 0; i < elementc; i++) {
 			elements[i] = UNSIGN(c->argv[i + 2]);
 			elementslen[i] = c->argvlen[i + 2];
 		}
 	}

-	int retval = rl_pfadd(c->context->db, key, keylen, elementc, elements, elementslen, &updated);
+	retval = rl_pfadd(c->context->db, key, keylen, elementc, elements, elementslen, &updated);
 	RLITE_SERVER_ERR(c, retval);
 	if (retval == RL_OK) {
 		c->reply = createLongLongObject(updated);
@@ -3214,23 +3031,15 @@
 	long count;
 	const unsigned char **elements = NULL;
 	long *elementslen = NULL;
-	int i, elementc = c->argc - 1;
-
-	elements = rl_malloc(sizeof(unsigned char *) * elementc);
-	if (!elements) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	elementslen = rl_malloc(sizeof(long) * elementc);
-	if (!elementslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	int retval, i, elementc = c->argc - 1;
+
+	MALLOC(elements, sizeof(unsigned char *) * elementc);
+	MALLOC(elementslen, sizeof(long) * elementc);
 	for (i = 0; i < elementc; i++) {
 		elements[i] = UNSIGN(c->argv[i + 1]);
 		elementslen[i] = c->argvlen[i + 1];
 	}
-	int retval = rl_pfcount(c->context->db, elementc, elements, elementslen, &count);
+	retval = rl_pfcount(c->context->db, elementc, elements, elementslen, &count);
 	RLITE_SERVER_ERR(c, retval);
 	if (retval == RL_OK) {
 		c->reply = createLongLongObject(count);
@@ -3248,24 +3057,16 @@
 	long keylen = c->argvlen[1];
 	const unsigned char **elements = NULL;
 	long *elementslen = NULL;
-	int i, elementc = c->argc - 2;
-
-	elements = rl_malloc(sizeof(unsigned char *) * elementc);
-	if (!elements) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	elementslen = rl_malloc(sizeof(long) * elementc);
-	if (!elementslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	int retval, i, elementc = c->argc - 2;
+
+	MALLOC(elements, sizeof(unsigned char *) * elementc);
+	MALLOC(elementslen, sizeof(long) * elementc);
 	for (i = 0; i < elementc; i++) {
 		elements[i] = UNSIGN(c->argv[i + 2]);
 		elementslen[i] = c->argvlen[i + 2];
 	}

-	int retval = rl_pfmerge(c->context->db, key, keylen, elementc, elements, elementslen);
+	retval = rl_pfmerge(c->context->db, key, keylen, elementc, elements, elementslen);
 	RLITE_SERVER_ERR(c, retval);
 	if (retval == RL_OK) {
 		c->reply = createStatusObject(RLITE_STR_OK);
@@ -3293,13 +3094,8 @@
 		if (retval == RL_OK) {
 			c->reply = createReplyObject(RLITE_REPLY_ARRAY);
 			c->reply->elements = size;
-			c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
-			if (!c->reply->element) {
-				rl_free(c->reply);
-				c->reply = NULL;
-				__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-				goto cleanup;
-			}
+			CHECK_OOM_ELSE(c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements),
+					rl_free(c->reply); c->reply = NULL);
 			for (i = 0; i < size; i++) {
 				c->reply->element[i] = createLongLongObject(elements[i]);
 			}
@@ -3563,13 +3359,8 @@
 		return;
 	}
 	c->reply->elements = size;
-	c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
-	if (!c->reply->element) {
-		rl_free(c->reply);
-		c->reply = NULL;
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	CHECK_OOM_ELSE(c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements),
+			rl_free(c->reply); c->reply = NULL);

 	for (i = 0; i < size; i++) {
 		c->reply->element[i] = createStringObject((char *)result[i], resultlen[i]);
@@ -3844,11 +3635,14 @@
 	// allocing the maximum number possible
 	// this is wasteful, but no need to worry about realloc
 	// and it is not that many probably anyway... hopefully
-	unsigned char **getv = rl_malloc(sizeof(unsigned char *) * c->argc);
-	long *getvlen = rl_malloc(sizeof(long) * c->argc);
+	unsigned char **getv = NULL;
+	long *getvlen = NULL;
 	long i, objc;
 	unsigned char **objv;
 	long *objvlen;
+
+	MALLOC(getv, sizeof(unsigned char *) * c->argc);
+	MALLOC(getvlen, sizeof(long) * c->argc);

 	/* The SORT command has an SQL-alike syntax, parse it */
 	j = 2;
@@ -3924,10 +3718,11 @@
 		if (retval == RL_OK) {
 			c->reply = createReplyObject(RLITE_REPLY_ARRAY);
 			c->reply->elements = objc;
-			c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements);
+			CHECK_OOM_ELSE(c->reply->element = rl_malloc(sizeof(rliteReply*) * c->reply->elements),
+					free(c->reply); c->reply = NULL);
 			for (i = 0; i < objc; i++) {
-				c->reply->element[i] = createStringObject((char *)objv[i], objvlen[i]);
-				rl_free(objv[i]);
+				// TODO free elements on oom
+				CHECK_OOM(c->reply->element[i] = createTakeStringObject((char *)objv[i], objvlen[i]));
 			}
 			rl_free(objv);
 			rl_free(objvlen);
@@ -3965,20 +3760,12 @@
 }

 static void pubsubVarargCommand(rliteClient *c, const char *type, int func(rlite *db, int argc, unsigned char **argv, long *argvlen)) {
-	int i = 0, argc = c->argc - 1;
+	int retval, i = 0, argc = c->argc - 1;
 	unsigned char **args = NULL;
 	long *argslen = NULL;

-	args = rl_malloc(sizeof(unsigned char *) * argc);
-	if (!args) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
-	argslen = rl_malloc(sizeof(long) * argc);
-	if (!argslen) {
-		__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
-		goto cleanup;
-	}
+	MALLOC(args, sizeof(unsigned char *) * argc);
+	MALLOC(argslen, sizeof(long) * argc);
 	for (i = 0; i < argc; i++) {
 		args[i] = (unsigned char *)c->argv[1 + i];
 		argslen[i] = (long)c->argvlen[1 + i];


fixing a DOS issue with read errors on HTTP (now failing properly instead of endless loop)

git-svn-id: 793bb72743a407948e3701719c462b6a765bc435@552 35dc7657-300d-0410-a2e5-dc2837fedb53

--- src/httpget.c
+++ src/httpget.c
@@ -99,8 +99,9 @@
 		}
 		else if(errno != EINTR) {
 			error("Error reading from socket or unexpected EOF.");
-			/* simply invalidate on error */
-			pos=0;
+			string[pos] = 0;
+			/* bail out to prevent endless loop */
+			return -1;
 		}
 	}

@@ -260,6 +261,7 @@
 	unsigned int myport = 0;
 	int sock;
 	int relocate, numrelocs = 0;
+	int ret = 0; /* return value from readstring */
 	struct sockaddr_in server;
 	FILE *myfile;
 	/*
@@ -561,11 +563,19 @@
 		}
 		relocate = FALSE;
 		purl[0] = '\0';
-		if (readstring (response, linelength-1, myfile)
-		    == linelength-1) {
-			fprintf(stderr, "Command exceeds max. length\n");
-			http_failure;
-		}
+		#define safe_readstring \
+		ret = readstring(response, linelength-1, myfile); \
+		if(ret == linelength-1) \
+		{ \
+			error("HTTP response line exceeds max. length"); \
+			http_failure; \
+		} \
+		else if(ret < 0) \
+		{ \
+			error("readstring failed"); \
+			http_failure; \
+		}
+		safe_readstring;
 		debug1("<response>\n%s</response>",response);
 		if ((sptr = strchr(response, ' '))) {
 			switch (sptr[1]) {
@@ -579,11 +589,7 @@
 			}
 		}
 		do {
-			if (readstring (response, linelength-1, myfile)
-			    == linelength-1) {
-				fprintf(stderr, "URL exceeds max. length\n");
-				http_failure;
-			}
+			safe_readstring;
 			if (!strncmp(response, "Location: ", 10))
 			{
 				size_t needed_length;


backend/x11: don't transform pointer events

We do this in a backend independent way in wlr_cursor now.

--- backend/x11/input_device.c
+++ backend/x11/input_device.c
@@ -32,21 +32,11 @@
 		int16_t x, int16_t y, xcb_timestamp_t time) {
 	struct wlr_x11_backend *x11 = output->x11;
 	struct wlr_output *wlr_output = &output->wlr_output;
-
-	struct wlr_box box = { .x = x, .y = y };
-	wlr_box_transform(&box, wlr_output->transform, wlr_output->width,
-		wlr_output->height, &box);
-	box.x /= wlr_output->scale;
-	box.y /= wlr_output->scale;
-
-	int output_width, output_height;
-	wlr_output_effective_resolution(wlr_output, &output_width, &output_height);
-
 	struct wlr_event_pointer_motion_absolute event = {
 		.device = &output->pointer_dev,
 		.time_msec = time,
-		.x = (double)box.x / output_width,
-		.y = (double)box.y / output_height,
+		.x = (double)x / wlr_output->width,
+		.y = (double)y / wlr_output->height,
 	};
 	wlr_signal_emit_safe(&output->pointer.events.motion_absolute, &event);


Fix memory leak in idevice_device_list_free

--- src/idevice.c
+++ src/idevice.c
@@ -134,8 +134,9 @@
 {
 	if (devices) {
 		int i = 0;
-		while (devices[i++]) {
+		while (devices[i]) {
 			free(devices[i]);
+			i++;
 		}
 		free(devices);
 	}


Remove prototypes of removed prune queries.

--- bacula/src/cats/sql_cmds.h
+++ bacula/src/cats/sql_cmds.h
@@ -31,13 +31,6 @@
 extern const char CATS_IMP_EXP *list_pool;
 extern const char CATS_IMP_EXP *drop_deltabs[];
 extern const char CATS_IMP_EXP *create_delindex;
-extern const char CATS_IMP_EXP *insert_delcand;
-extern const char CATS_IMP_EXP *select_backup_del;
-extern const char CATS_IMP_EXP *select_verify_del;
-extern const char CATS_IMP_EXP *select_restore_del;
-extern const char CATS_IMP_EXP *select_admin_del;
-extern const char CATS_IMP_EXP *select_migrate_del;
-extern const char CATS_IMP_EXP *select_copy_del;
 extern const char CATS_IMP_EXP *select_job;
 extern const char CATS_IMP_EXP *count_select_job;
 extern const char CATS_IMP_EXP *del_File;


Add more sm_check debug

Add more sm_check debug

--- bacula/src/dird/ua_prune.c
+++ bacula/src/dird/ua_prune.c
@@ -96,6 +96,8 @@
          del->max_ids);
    }
    del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
+   /* **FIXME*** remove in production */
+   sm_check(__FILE__, __LINE__, true);
 // Dmsg2(150, "row=%d val=%d\n", del->num_ids-1, del->JobId[del->num_ids-1]);
    return 0;
 }
@@ -305,8 +307,12 @@

 bail_out:
    db_unlock(ua->db);
+   /* ***FIXME*** remove this for production */
+   sm_check(__FILE__, __LINE__, true);
    if (del.JobId) {
       free(del.JobId);
+      /* ***FIXME*** remove this for production */
+      sm_check(__FILE__, __LINE__, true);
    }
    return 1;
 }


Correct debug message

Correct debug message

git-svn-id: bb0627f6f70d46b61088c62c6186faa4b96a9496@8330 91ce42f0-d328-0410-95d8-f526ca767f89

--- bacula/src/stored/askdir.c
+++ bacula/src/stored/askdir.c
@@ -401,7 +401,7 @@
    /* Throw out records where FI is zero -- i.e. nothing done */
    if (!zero && dcr->VolFirstIndex == 0 &&
         (dcr->StartBlock != 0 || dcr->EndBlock != 0)) {
-      Dmsg0(000, "JobMedia problem FI=0 StartBlock!=0\n");
+      Dmsg0(100, "JobMedia FI=0 StartBlock!=0 record suppressed\n");
       return true;
    }


lib/tree: move struct inode_item into item.h

--- lib/tree/item.h
+++ lib/tree/item.h
@@ -6,6 +6,29 @@
 #include "key.h"

+enum item_key {
+	KEY_INODE = 0x01,
+};
+
+
+struct __attribute__((__packed__)) inode_item {
+	uint32_t i_attr;  // file attributes
+	uint16_t i_mode;  // type and permissions
+
+	uint16_t i_uid;   // owner
+	uint16_t i_gid;   // group
+
+	uint32_t i_size;  // length in bytes of file content
+
+	int64_t  i_atime; // access time
+	int64_t  i_ctime; // creation time
+	int64_t  i_mtime; // modification time
+
+	uint32_t i_nlink; // hard link ref count
+
+	uint32_t i_gen;   // generation
+};
+
 struct item_data {
 	uint32_t len;
 	void *data;


lib/tree: fix hdr.next handling in node_split

--- lib/tree/node.c
+++ lib/tree/node.c
@@ -213,7 +213,7 @@
 		this_addr = node_alloc();

 		if (this->hdr.leaf) {
-			this = (node_ptr)leaf_init(this_addr, parent_addr, 0, new_addr);
+			this = (node_ptr)leaf_init(this_addr, parent_addr, 0, 0);
 		} else {
 			this = (node_ptr)branch_init(this_addr, parent_addr);
 		}
@@ -243,9 +243,12 @@
 	if (this->hdr.leaf) {
 		new = (node_ptr)leaf_init(new_addr, parent_addr, this_addr,
 			this->hdr.next);
+		this->hdr.next = new_addr;
+
 		leaf_split_post((leaf_ptr)this, (leaf_ptr)new);
 	} else {
 		new = (node_ptr)branch_init(new_addr, parent_addr);
+
 		branch_split_post((branch_ptr)this, (branch_ptr)new, was_root);
 	}


brya: Remove duplicate keyboard support defines

This removes some duplicate keyboard defines that crept in from
splitting larger patches and merging. sorry.

BRANCH=none
BUG=b:173575131
TEST=buildall passes

Signed-off-by: Caveh Jalali <08e24a66aefda7a55ca7d73f8903e0fb16eec763@chromium.org>
Change-Id: I541da5ea29477fbaaacb7467fdb98156670e1ec3
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2738915
Reviewed-by: Furquan Shaikh <6be5c96c464778f89679b1062a2e0a6af93d2aa5@chromium.org>

--- baseboard/brya/baseboard.h
+++ baseboard/brya/baseboard.h
@@ -28,18 +28,6 @@
 #define CONFIG_CRC8

 #define CONFIG_EXTPOWER_GPIO
-
-/* Common Keyboard Defines */
-#define CONFIG_CMD_KEYBOARD
-#define CONFIG_KEYBOARD_BOARD_CONFIG
-#define CONFIG_KEYBOARD_COL2_INVERTED
-#define CONFIG_KEYBOARD_KEYPAD
-#define CONFIG_KEYBOARD_PROTOCOL_8042
-#ifdef CONFIG_KEYBOARD_VIVALDI
-#define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2
-#else
-#define CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI3
-#endif

 /* Host communication */
 #define CONFIG_HOSTCMD_ESPI


Use zip_source_call.

Use zip_source_call.

--- lib/zip_close.c
+++ lib/zip_close.c
@@ -45,11 +45,11 @@

 static int add_data(struct zip *, struct zip_source *, struct zip_dirent *,
 		    FILE *);
-static int add_data_comp(zip_source_callback, void *, struct zip_stat *,
+static int add_data_comp(struct zip_source *, struct zip_stat *,
 			 FILE *, struct zip_error *);
-static int add_data_uncomp(struct zip *, zip_source_callback, void *,
+static int add_data_uncomp(struct zip *, struct zip_source *,
 			   struct zip_stat *, FILE *);
-static void ch_set_error(struct zip_error *, zip_source_callback, void *);
+static void ch_set_error(struct zip_error *, struct zip_source *);
 static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
 static int write_cdir(struct zip *, struct zip_cdir *, FILE *);
 static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
@@ -317,23 +317,20 @@

 static int
-add_data(struct zip *za, struct zip_source *zs, struct zip_dirent *de, FILE *ft)
+add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de,
+	 FILE *ft)
 {
     off_t offstart, offend;
-    zip_source_callback cb;
-    void *ud;
     struct zip_stat st;

-    cb = zs->f;
-    ud = zs->ud;
-
-    if (cb(ud, &st, sizeof(st), ZIP_SOURCE_STAT) < (zip_int64_t)sizeof(st)) {
-	ch_set_error(&za->error, cb, ud);
-	return -1;
-    }
-
-    if (cb(ud, NULL, 0, ZIP_SOURCE_OPEN) < 0) {
-	ch_set_error(&za->error, cb, ud);
+    if (zip_source_call(src, &st, sizeof(st),
+			ZIP_SOURCE_STAT) < (zip_int64_t)sizeof(st)) {
+	ch_set_error(&za->error, src);
+	return -1;
+    }
+
+    if (zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) {
+	ch_set_error(&za->error, src);
 	return -1;
     }

@@ -343,16 +340,16 @@
 	return -1;

     if (st.comp_method != ZIP_CM_STORE) {
-	if (add_data_comp(cb, ud, &st, ft, &za->error) < 0)
+	if (add_data_comp(src, &st, ft, &za->error) < 0)
 	    return -1;
     }
     else {
-	if (add_data_uncomp(za, cb, ud, &st, ft) < 0)
-	    return -1;
-    }
-
-    if (cb(ud, NULL, 0, ZIP_SOURCE_CLOSE) < 0) {
-	ch_set_error(&za->error, cb, ud);
+	if (add_data_uncomp(za, src, &st, ft) < 0)
+	    return -1;
+    }
+
+    if (zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE) < 0) {
+	ch_set_error(&za->error, src);
 	return -1;
     }

@@ -388,14 +385,14 @@

 static int
-add_data_comp(zip_source_callback cb, void *ud, struct zip_stat *st,FILE *ft,
+add_data_comp(struct zip_source *src, struct zip_stat *st, FILE *ft,
 	      struct zip_error *error)
 {
     char buf[BUFSIZE];
     zip_int64_t n;

     st->comp_size = 0;
-    while ((n=cb(ud, buf, sizeof(buf), ZIP_SOURCE_READ)) > 0) {
+    while ((n=zip_source_call(src, buf, sizeof(buf), ZIP_SOURCE_READ)) > 0) {
 	if (fwrite(buf, 1, n, ft) != (size_t)n) {
 	    _zip_error_set(error, ZIP_ER_WRITE, errno);
 	    return -1;
@@ -404,7 +401,7 @@
 	st->comp_size += n;
     }
     if (n < 0) {
-	ch_set_error(error, cb, ud);
+	ch_set_error(error, src);
 	return -1;
     }

@@ -415,7 +412,7 @@

 static int
-add_data_uncomp(struct zip *za, zip_source_callback cb, void *ud,
+add_data_uncomp(struct zip *za, struct zip_source *src,
 		struct zip_stat *st, FILE *ft)
 {
     char b1[BUFSIZE], b2[BUFSIZE];
@@ -452,8 +449,8 @@
     end = 0;
     while (!end) {
 	if (zstr.avail_in == 0 && !flush) {
-	    if ((n=cb(ud, b1, sizeof(b1), ZIP_SOURCE_READ)) < 0) {
-		ch_set_error(&za->error, cb, ud);
+	    if ((n=zip_source_call(src, b1, sizeof(b1), ZIP_SOURCE_READ)) < 0) {
+		ch_set_error(&za->error, src);
 		deflateEnd(&zstr);
 		return -1;
 	    }
@@ -499,11 +496,12 @@

 static void
-ch_set_error(struct zip_error *error, zip_source_callback cb, void *ud)
+ch_set_error(struct zip_error *error, struct zip_source *src)
 {
     int e[2];

-    if ((cb(ud, e, sizeof(e), ZIP_SOURCE_ERROR)) < (zip_int64_t)sizeof(e)) {
+    if ((zip_source_call(src, e, sizeof(e),
+			 ZIP_SOURCE_ERROR)) < (zip_int64_t)sizeof(e)) {
 	error->zip_err = ZIP_ER_INTERNAL;
 	error->sys_err = 0;
     }


Force binary mode for output zip files on Windows.

According to Pierre Joye, Windows in some environments per default
creates text files (ignoring the "b" in the fdopen mode argument).

--- lib/zip_close.c
+++ lib/zip_close.c
@@ -606,6 +606,14 @@
 	return NULL;
     }

+#ifdef _WIN32
+    /*
+      According to Pierre Joye, Windows in some environments per
+      default creates text files, so force binary mode.
+    */
+    _setmode(_fileno(tfp), _O_BINARY );
+#endif
+
     *outp = tfp;
     return temp;
 }


public API

public API

git-svn-id: a4d7c1866f8397a4106e0b57fc4fbf792bbdaaaf@7551 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b

--- libavutil/aes.h
+++ libavutil/aes.h
@@ -32,4 +32,14 @@
  */
 int av_aes_init(struct AVAES *a, uint8_t *key, int key_bits, int decrypt);

+/**
+ * encrypts / decrypts.
+ * @param count number of 16 byte blocks
+ * @param dst destination array, can be equal to src
+ * @param src source array, can be equal to dst
+ * @param iv initalization vector for CBC mode, if NULL then ECB will be used
+ * @param decrypt 0 for encryption, 1 for decryption
+ */
+void aes_crypt(AVAES *a, uint8_t *dst, uint8_t *src, int count, uint8_t *iv, int decrypt);
+
 #endif /* AES_H */


Add fallback for DECLARE_ALIGNED and DECLARE_ASM_CONST.

git-svn-id: a4d7c1866f8397a4106e0b57fc4fbf792bbdaaaf@11919 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b

--- libavutil/mem.h
+++ libavutil/mem.h
@@ -35,6 +35,10 @@
 #elif _MSVC
   #define DECLARE_ALIGNED(n,t,v)      __declspec(align(n)) t v
   #define DECLARE_ASM_CONST(n,t,v)    __declspec(align(n)) static const t v
+#else
+  #warning No align and asm directives, this might fail.
+  #define DECLARE_ALIGNED(n,t,v)      t v
+  #define DECLARE_ASM_CONST(n,t,v)    static const t v
 #endif

 /**


Reduce rounding in the mode allocator and remove a scaling loop. This breaks the bitstream.

--- libcelt/modes.c
+++ libcelt/modes.c
@@ -206,7 +206,7 @@

 static void compute_allocation_table(CELTMode *mode, int res)
 {
-   int i, j, eband, nBark;
+   int i, j, nBark;
    celt_int16_t *allocVectors, *allocEnergy;
    const int C = CHANNELS(mode);

@@ -221,38 +221,31 @@
    /* Compute per-codec-band allocation from per-critical-band matrix */
    for (i=0;i<BITALLOC_SIZE;i++)
    {
-      eband = 0;
+      celt_int32_t current = 0;
+      int eband = 0;
       for (j=0;j<nBark;j++)
       {
          int edge, low;
          celt_int32_t alloc;
          edge = mode->eBands[eband+1]*res;
          alloc = band_allocation[i*BARK_BANDS+j];
-         alloc = alloc*C*mode->mdctSize/4;
+         alloc = alloc*C*mode->mdctSize;
          if (edge < bark_freq[j+1])
          {
             int num, den;
             num = alloc * (edge-bark_freq[j]);
             den = bark_freq[j+1]-bark_freq[j];
             low = (num+den/2)/den;
-            allocVectors[i*mode->nbEBands+eband] += low;
+            allocVectors[i*mode->nbEBands+eband] = (current+low+128)/256;
+            current=0;
             eband++;
-            allocVectors[i*mode->nbEBands+eband] += alloc-low;
+            current += alloc-low;
          } else {
-            allocVectors[i*mode->nbEBands+eband] += alloc;
-         }
+            current += alloc;
+         }
       }
-   }
-   for (i=0;i<mode->nbAllocVectors;i++)
-   {
-      for (j=0;j<mode->nbEBands;j++)
-         allocVectors[i*mode->nbEBands+j] = (allocVectors[i*mode->nbEBands+j]+32)/64;
-   }
-   /*for (i=0;i<mode->nbAllocVectors;i++)
-   {
-      for (j=0;j<mode->nbEBands;j++)
-         allocVectors[i*mode->nbEBands+j] += C;
-   }*/
+      allocVectors[i*mode->nbEBands+eband] = (current+128)/256;
+   }
    mode->allocVectors = allocVectors;
 }


Fixes a couple of bugs

Fixes a couple of bugs

We must NOT check for EINTR after calling close()

--- libchula/util.c
+++ libchula/util.c
@@ -198,17 +198,23 @@
 ret_t
 chula_atoi (const char *str, int *ret_value)
 {
-	int tmp;
+	int   tmp;
+    char *endptr = NULL;

     if (str == NULL) {
         return ret_error;
     }

 	errno = 0;
-	tmp = strtol (str, NULL, 10);
+	tmp = strtol (str, &endptr, 10);
 	if (errno != 0) {
 		return ret_error;
 	}
+
+    if (str == endptr) {
+        /* No digits were found */
+        return ret_error;
+    }

 	*ret_value = tmp;
 	return ret_ok;
@@ -758,14 +764,7 @@
 		return ret_error;
 	}

-	do {
-#ifdef _WIN32
-		re = closesocket (fd);
-#else
-		re = close (fd);
-#endif
-	} while ((re == -1) && (errno == EINTR));
-
+    re = close (fd);
 	TRACE (ENTRIES",close_fd", "fd=%d re=%d\n", fd, re);
 	return (re == 0) ? ret_ok : ret_error;
 }


Make sure that the persistent signature is never optimized # better func to call (cmp)

--- libhfuzz/main.c
+++ libhfuzz/main.c
@@ -24,7 +24,7 @@
      * signature, to prevent optimizing it out by clever compiler/link
      * optimizers
      */
-    if (time(NULL) == 0) {
+    if (time(NULL) == -10) {
       return (int)strlen(LIBHFUZZ_module_main);
     }
     return HonggfuzzMain(argc, argv);


api: do not try to call ngli_gpu_ctx_end_draw() if ngli_gpu_ctx_begin_draw() failed

--- libnodegl/api.c
+++ libnodegl/api.c
@@ -327,7 +327,7 @@

     ret = ngli_gpu_ctx_begin_draw(s->gpu_ctx, t);
     if (ret < 0)
-        goto end;
+        return ret;

     const int64_t cpu_start_time = s->hud ? ngli_gettime_relative() : 0;

@@ -362,17 +362,12 @@
         ngli_hud_draw(s->hud);
     }

-end:;
     if (s->render_pass_started) {
         ngli_gpu_ctx_end_render_pass(s->gpu_ctx);
         s->render_pass_started = 0;
     }

-    int end_ret = ngli_gpu_ctx_end_draw(s->gpu_ctx, t);
-    if (end_ret < 0)
-        return end_ret;
-
-    return ret;
+    return ngli_gpu_ctx_end_draw(s->gpu_ctx, t);
 }

 static int dispatch_cmd(struct ngl_ctx *s, cmd_func_type cmd_func, void *arg)


dot: fix inactive color on table headers

--- libnodegl/dot.c
+++ libnodegl/dot.c
@@ -170,7 +170,12 @@
         ngli_bstr_printf(b, "\"0.%u 0.2 0.8\"", hue); /* color of all the entries, more pale than HSLFMT */
     else
         ngli_bstr_print(b, INACTIVE_COLOR);
-    ngli_bstr_printf(b, ">
%s
", colspan, hue, label);
+    ngli_bstr_printf(b, ">
%s
", label);
 }

 static void table_footer(struct bstr *b)


refactor server SHA-1 certificate definition into a new block


fixed bugs in utf8_resize, utf8_iter and utf8_get.


Correct case of DBus in interface name When introspecting, free the dautm if needed, only call introspect_children if it is not NULL, fix args, only print arg names if a name is present, and close tags

--- libspi/droute.c
+++ libspi/droute.c
@@ -149,6 +149,7 @@
   char *str;
   DBusMessage *reply;
   GSList *l;
+  void *datum;

   if (strcmp (dbus_message_get_member (message), "Introspect"))
     {
@@ -157,6 +158,7 @@
   xml = g_string_new (NULL);
   /* below code stolen from dbus-glib */
   g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
+  g_string_append_printf (xml, "<node name=\"%s\">\n", path);

   /* We are introspectable, though I guess that was pretty obvious */
   g_string_append_printf (xml, "  <interface name=\"%s\">\n",
@@ -207,13 +209,13 @@

   g_string_append (xml, "    </method>\n");
   g_string_append (xml, "  </interface>\n");
-  g_string_append_printf (xml, "<node name=\"%s\">\n", path);
   /* end of stolen code */

   for (l = data->interfaces; l; l = g_slist_next (l))
     {
       iface_def = (DRouteInterface *) l->data;
-      if (!(*iface_def->get_datum) (path, data->user_data))
+      datum = (*iface_def->get_datum) (path, data->user_data);
+      if (!datum)
 	continue;
       g_string_append_printf (xml, "<interface name=\"%s\">\n",
 			      iface_def->name);
@@ -225,21 +227,30 @@
 				    (method->type ==
 				     DROUTE_METHOD ? "method" : "signal"),
 				    method->name);
-	    g_string_append (xml, "<arg type=\"");
-	    g_string_append_len (xml, p, strcspn (p, ",:"));
-	    p += strcspn (p, ",");
-	    if (*p == ',')
-	      p++;
-	    g_string_append (xml, "\" name=\"");
-	    g_string_append_len (xml, p, strcspn (p, ",:"));
-	    p += strcspn (p, ",");
-	    if (*p == ',')
-	      p++;
-	    g_string_append_printf (xml, "\" direction=\"%s\"/>\n",
-				    (*p == 'o' ? "out" : "in"));
-	    p += strcspn (p, ":");
-	    if (*p == ':')
-	      p++;
+	    while (*p)
+	      {
+		g_string_append (xml, "<arg type=\"");
+		g_string_append_len (xml, p, strcspn (p, ",:"));
+		p += strcspn (p, ",");
+		if (*p == ',')
+		  p++;
+		if (strcspn (p, ",:") > 0)
+		  {
+		    g_string_append (xml, "\" name=\"");
+		    g_string_append_len (xml, p, strcspn (p, ",:"));
+		    p += strcspn (p, ",");
+		  }
+		if (*p == ',')
+		  p++;
+		g_string_append_printf (xml, "\" direction=\"%s\"/>\n",
+					(*p == 'o' ? "out" : "in"));
+		p += strcspn (p, ":");
+		if (*p == ':')
+		  p++;
+	      }
+	    g_string_append_printf (xml, "</%s>\n",
+				    (method->type ==
+				     DROUTE_METHOD ? "method" : "signal"));
 	  }
       if (iface_def->properties)
 	for (property = iface_def->properties; property->name; property++)
@@ -252,8 +263,15 @@
 				    (property->get ? "read" : ""),
 				    (property->set ? "write" : ""));
 	  }
-    }
-  (*data->introspect_children) (path, xml, data->user_data);
+      if (iface_def->free_datum)
+	(*iface_def->free_datum) (datum);
+      g_string_append (xml, "</interface>\n");
+    }
+  if (data->introspect_children)
+    {
+      (*data->introspect_children) (path, xml, data->user_data);
+    }
+  g_string_append (xml, "</node>\n");
   str = g_string_free (xml, FALSE);
   reply = dbus_message_new_method_return (message);
   if (reply)
@@ -282,13 +300,13 @@
   dbus_error_init (&error);
   if (!member)
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-  if (iface && !strcmp (iface, "org.freedesktop.dbus.Properties"))
+  if (iface && !strcmp (iface, "org.freedesktop.DBus.Properties"))
     {
       if (!strcmp (member, "GetAll"))
 	return prop_get_all (bus, message, data);
       return prop (bus, message, data);
     }
-  else if (iface && !strcmp (iface, "org.freedesktop.dbus.Introspectable"))
+  else if (iface && !strcmp (iface, "org.freedesktop.DBus.Introspectable"))
     {
       return introspect (bus, message, data);
     }


share attributes

share attributes

--- libutil/share.h
+++ libutil/share.h
@@ -28,10 +28,15 @@

 /*
  * objects shared on a host
+ * shares can be block devices, sockets or filesystems
+ * shares can contain attribute metadata
+ * to indicate uptime, availability
  */
 struct ep_share {
     int name;
     int type;
+    int label;
+    int attributes;
     void *data;
     struct ep_operations ops;
 };


Turn a comment into english

Turn a comment into english

git-svn-id: 2c9807fa3ff65b17195bd55dc8a6c4261e10127b@390 d4fa192b-c00b-0410-8231-f00ffab90ce4

--- bin/varnishd/cache_fetch.c
+++ bin/varnishd/cache_fetch.c
@@ -19,10 +19,10 @@
 #include "cache.h"

 /*
- * Chunked encoding is a hack.  We prefer to have a single or a few
- * large storage objects, and a terribly long list of small ones.
+ * Chunked encoding is a hack.  We prefer to have a single chunk or a
+ * few large chunks, and not a terribly long list of small ones.
  * If our stevedore can trim, we alloc big chunks and trim the last one
- * at the end know the result.
+ * at the end when we know the result.
  *
  * Good testcase: http://www.washingtonpost.com/
  */


binutils: bfd: realign R_RISCV_RVC_JUMP

binutils: bfd: realign R_RISCV_RVC_JUMP

--- binutils/bfd/elfxx-riscv.c
+++ binutils/bfd/elfxx-riscv.c
@@ -657,20 +657,20 @@
 	 TRUE),			/* pcrel_offset */

   /* 11-bit PC-relative jump offset.  */
-  HOWTO (R_RISCV_RVC_JUMP,	/* type */
-	 0,			/* rightshift */
-	 2,			/* size (0 = byte, 1 = short, 2 = long) */
-	 32,			/* bitsize */
-	 TRUE,			/* pc_relative */
-	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
-				/* This needs complex overflow
-				   detection, because the upper 36
-				   bits must match the PC + 4.  */
-	 bfd_elf_generic_reloc,	/* special_function */
-	 "R_RISCV_RVC_JUMP",	/* name */
-	 FALSE,			/* partial_inplace */
-	 0,			/* src_mask */
+  HOWTO (R_RISCV_RVC_JUMP,		/* type */
+	 0,				/* rightshift */
+	 2,				/* size */
+	 32,				/* bitsize */
+	 TRUE,				/* pc_relative */
+	 0,				/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+					/* This needs complex overflow
+					   detection, because the upper 36
+					   bits must match the PC + 4.  */
+	 bfd_elf_generic_reloc,		/* special_function */
+	 "R_RISCV_RVC_JUMP",		/* name */
+	 FALSE,				/* partial_inplace */
+	 0,				/* src_mask */
 	 ENCODE_RVC_J_IMM (-1U),	/* dst_mask */
 	 TRUE),		/* pcrel_offset */
 };


Oops. Forgot a debugline, making the removal unnecessarily uncompleted

git-svn-id: e83610e039cfba8c8d2298de401ee743c87985a4@369 0208b46f-8ce1-0310-ae57-d63fbe48b28d

--- shifter.c
+++ shifter.c
@@ -324,7 +324,6 @@
     if(shifter_get_vsync() > ((313-topborder)*512)) {
       lowerborder = LOWERBORDER+47;
     }
-    lowerborder = 313;
     syncreg = data;
     return;
   case 0xff8260:


Version 0.1.1

Version 0.1.1

--- shmfile.c
+++ shmfile.c
@@ -60,7 +60,7 @@
 static volatile const char *copyright = "Copyright (c) 2017 Timothy Savannah   All Rights Reserved,  licensed under terms of Lesser GNU Public License version 2.1";

 static volatile const char *product_name = "shmfile";
-static volatile const char *version   = "Version 0.1.0";
+static volatile const char *version   = "Version 0.1.1";

 void _fshm_printCopyrightVersion(void)


inet: Remove is_bound fn

inet: Remove is_bound fn

It's now quite simple. It's better to open-code one.

Signed-off-by: Pavel Emelyanov <c9a32589e048e044184536f7ac71ef92fe82df3e@parallels.com>

--- sk-inet.c
+++ sk-inet.c
@@ -344,13 +344,6 @@
 	return ret;
 }

-static bool is_bound(struct inet_sk_info *ii)
-{
-	/* zero port is reserved */
-	return ii->ie->src_port;
-}
-
-
 static int open_inet_sk(struct file_desc *d);
 static int post_open_inet_sk(struct file_desc *d, int sk);

@@ -483,7 +476,7 @@
 	 * bind() and listen(), and that's all.
 	 */

-	if (is_bound(ii)) {
+	if (ie->src_port) {
 		if (inet_bind(sk, ii))
 			goto err;
 	}


sk-unix: Defile log prefix

sk-unix: Defile log prefix

For grepability sake.

Signed-off-by: Cyrill Gorcunov <7a1ea01eee6961eb1e372e3508c2670446d086f4@openvz.org>
Signed-off-by: Pavel Emelyanov <c9a32589e048e044184536f7ac71ef92fe82df3e@parallels.com>

--- sk-unix.c
+++ sk-unix.c
@@ -31,6 +31,9 @@
 #include "protobuf.h"
 #include "protobuf/sk-unix.pb-c.h"

+#undef	LOG_PREFIX
+#define LOG_PREFIX "sk unix: "
+
 struct unix_sk_desc {
 	struct socket_desc	sd;
 	unsigned int		type;


unix: Add _all_ peers into must-dump list

When dumping a unix socket we must make sure, that all connections
are dumped or -x option is used. Currently only peers with non-matching
ids are added into check. Fix this.

Signed-off-by: Pavel Emelyanov <c9a32589e048e044184536f7ac71ef92fe82df3e@parallels.com>

--- sk-unix.c
+++ sk-unix.c
@@ -168,15 +168,15 @@
 				       ue.ino, ue.peer, peer->peer_ino, peer->name);
 				goto err;
 			}
-
-			/*
-			 * It can be external socket, so we defer dumping
-			 * until all sockets the program owns are processed.
-			 */
-			if (!peer->sd.already_dumped && list_empty(&peer->list)) {
-				show_one_unix("Add a peer", peer);
-				list_add_tail(&peer->list, &unix_sockets);
-			}
+		}
+
+		/*
+		 * It can be external socket, so we defer dumping
+		 * until all sockets the program owns are processed.
+		 */
+		if (!peer->sd.already_dumped && list_empty(&peer->list)) {
+			show_one_unix("Add a peer", peer);
+			list_add_tail(&peer->list, &unix_sockets);
 		}

 		if ((ue.type != SOCK_DGRAM) && (


working for two simple args

working for two simple args

--- snoctxt.c
+++ snoctxt.c
@@ -6,12 +6,47 @@
     int lines = 0;
     size_t len;
     while(fgetln(foo, &len)) {
-        foo += len;
         lines++;
     }
     return lines;
 }

+
+char** copy_lines(FILE* snoc_dst, int nlines) {
+    int i = 0;
+    char* lnptr = NULL;
+    char** lines = NULL;
+    size_t len;
+
+    rewind(snoc_dst);
+    lines = (char**)malloc(sizeof(char*) * nlines);
+    while((lnptr = fgetln(snoc_dst, &len))) {
+        lines[i] = (char*)malloc(sizeof(char) * len+1);
+        strncpy(lines[i], lnptr, len);
+        i++;
+    }
+
+    rewind(snoc_dst);
+    return lines;
+}
+
+
+void fprintln(FILE* dst, char** lines, int nlines) {
+    int i = 0;
+
+    for (i = 0; i < nlines; i++) {
+        fprintf(dst, "%s", lines[i]);
+    }
+}
+
+void free_array(void** array, int size){
+    int i;
+    for (i = 0; i < size; i++) {
+        free(array[i]);
+    }
+
+    free(array);
+}

 int main(int argc, char *argv []) {
     if (argc > 0) {
@@ -19,35 +54,26 @@
         size_t len = 0;
         int nlines = 0;
         int ilines = 0;
-        char* lnptr = NULL;
         char** lines = NULL;
+        char** newlines = NULL;
         char* s_snoc_src = argv[1];
         char* s_snoc_dst = argv[2];
         FILE* snoc_src = fopen(s_snoc_src, "r");
         FILE* snoc_dst = fopen(s_snoc_dst, "r+");

         nlines = count_ln(snoc_dst);
-        lines = (char**)malloc(sizeof(char) * 512 * nlines);
-        rewind(snoc_dst);
+        ilines = count_ln(snoc_src);
+        lines = copy_lines(snoc_dst, nlines);

-        for (i = 0; i < nlines; i++) {
-            lnptr = fgetln(snoc_dst, &len);
-            lines[i] = (char*)malloc(sizeof(char) * len);
-            strcpy(lines[i], lnptr);
-        }
+        newlines =  copy_lines(snoc_src, ilines);
+        snoc_dst = freopen(s_snoc_dst, "w", snoc_dst);

-        rewind(snoc_dst);
+        fprintln(snoc_dst, newlines, ilines);
+        fprintln(snoc_dst, lines, nlines);

-        while(lnptr = fgetln(snoc_src, &len)){
-            fprintf(snoc_dst, "%s", lnptr);
-            ilines += len;
-        }
-
-        fseek(snoc_dst, ilines, SEEK_SET);
-        for (i = 0; i < nlines; i++) {
-            fprintf(snoc_dst, "%s", lines[i]);
-        }
-
+        free_array((void**)lines, nlines);
+        free_array((void**)newlines, ilines);
+
         fclose(snoc_src);
         fclose(snoc_dst);
     }


sockets: Nitpick for dgram dumping

sockets: Nitpick for dgram dumping

Signed-off-by: Cyrill Gorcunov <7a1ea01eee6961eb1e372e3508c2670446d086f4@openvz.org>

--- sockets.c
+++ sockets.c
@@ -131,6 +131,10 @@
 		}

 		break;
+	case TCP_CLOSE:
+		if (sk->type != SOCK_DGRAM)
+			return 0;
+		break;
 	default:
 		pr_err("Unknown state %d\n", sk->state);
 		return 0;


sockets: Make crtools check report error when DIAG is incomplete

Absense of packet and netlink diag is OK at dump -- we can be on
older kernel and will fail later if _really_ need these sockets.

During check stage all diag is expected to be in place.

Signed-off-by: Pavel Emelyanov <c9a32589e048e044184536f7ac71ef92fe82df3e@parallels.com>

--- sockets.c
+++ sockets.c
@@ -602,7 +602,7 @@
 					PACKET_SHOW_FANOUT | PACKET_SHOW_RING_CFG;
 	tmp = do_collect_req(nl, &req, sizeof(req), packet_receive_one, NULL);
 	if (tmp) {
-		if (tmp == -ENOENT) /* Fedora 19 */
+		if (pid != 0 && tmp == -ENOENT) /* Fedora 19 */
 			pr_warn("The currect kernel doesn't support packet_diag\n");
 		else
 			err = tmp;
@@ -613,7 +613,7 @@
 	req.r.n.ndiag_show	= NDIAG_SHOW_GROUPS;
 	tmp = do_collect_req(nl, &req, sizeof(req), netlink_receive_one, NULL);
 	if (tmp) {
-		if (tmp == -ENOENT) /* Going to be in 3.10 */
+		if (pid != 0 && tmp == -ENOENT) /* Going to be in 3.10 */
 			pr_warn("The currect kernel doesn't support netlink_diag\n");
 		else
 			err = tmp;


sock: Fix ret code collection when dumping sockets option

Signed-off-by: Pavel Emelyanov <c9a32589e048e044184536f7ac71ef92fe82df3e@parallels.com>

--- sockets.c
+++ sockets.c
@@ -159,7 +159,7 @@
 	tv.tv_usec = soe->so_rcv_tmo_usec;
 	ret |= restore_opt(sk, SOL_SOCKET, SO_RCVTIMEO, &tv);

-	ret = restore_bound_dev(sk, soe);
+	ret |= restore_bound_dev(sk, soe);

 	/* The restore of SO_REUSEADDR depends on type of socket */

@@ -226,7 +226,7 @@
 	soe->has_so_no_check = true;
 	soe->so_no_check = val ? true : false;

-	ret = dump_bound_dev(sk, soe);
+	ret |= dump_bound_dev(sk, soe);

 	return ret;
 }


Added SSP base class for LPC43xx.

Added SSP base class for LPC43xx.

error: pathspec 'platform/nxp/lpc43xx/ssp_base.c' did not match any file(s) known to git

--- platform/nxp/lpc43xx/ssp_base.c
+++ platform/nxp/lpc43xx/ssp_base.c
@@ -0,0 +1,301 @@
+/*
+ * ssp_base.c
+ * Copyright (C) 2014 xent
+ * Project is distributed under the terms of the GNU General Public License v3.0
+ */
+
+#include <assert.h>
+#include <memory.h>
+#include <platform/nxp/ssp_base.h>
+#include <platform/nxp/lpc43xx/clocking.h>
+#include <platform/nxp/lpc43xx/system.h>
+/*----------------------------------------------------------------------------*/
+#define CHANNEL_RANGE                   4
+#define CHANNEL_INDEX(channel, index)   ((channel) * CHANNEL_RANGE + (index))
+#define CHANNEL_MISO(channel)           ((channel) * CHANNEL_RANGE + 0)
+#define CHANNEL_MOSI(channel)           ((channel) * CHANNEL_RANGE + 1)
+#define CHANNEL_SCK(channel)            ((channel) * CHANNEL_RANGE + 2)
+#define CHANNEL_SSEL(channel)           ((channel) * CHANNEL_RANGE + 3)
+/*----------------------------------------------------------------------------*/
+struct SspBlockDescriptor
+{
+  LPC_SSP_Type *reg;
+  /* Peripheral interrupt request identifier */
+  irq_t irq;
+  /* Reset control identifier */
+  enum sysDeviceReset reset;
+  /* Peripheral clock branch */
+  enum sysClockBranch periperalBranch;
+  /* Clock to register interface */
+  enum sysClockBranch registerBranch;
+};
+/*----------------------------------------------------------------------------*/
+static enum result setDescriptor(uint8_t, const struct SspBase *,
+    struct SspBase *);
+static enum result setupPins(struct SspBase *, const struct SspBaseConfig *);
+/*----------------------------------------------------------------------------*/
+static enum result sspInit(void *, const void *);
+static void sspDeinit(void *);
+/*----------------------------------------------------------------------------*/
+static const struct EntityClass sspTable = {
+    .size = 0, /* Abstract class */
+    .init = sspInit,
+    .deinit = sspDeinit
+};
+/*----------------------------------------------------------------------------*/
+static const struct SspBlockDescriptor sspBlockEntries[2] = {
+    {
+        .reg = LPC_SSP0,
+        .irq = SSP0_IRQ,
+        .registerBranch = CLK_M4_SSP0,
+        .periperalBranch = CLK_APB0_SSP0,
+        .reset = RST_SSP0
+    },
+    {
+        .reg = LPC_SSP1,
+        .irq = SSP1_IRQ,
+        .registerBranch = CLK_M4_SSP1,
+        .periperalBranch = CLK_APB2_SSP1,
+        .reset = RST_SSP1
+    }
+};
+/*----------------------------------------------------------------------------*/
+const struct PinEntry sspPins[] = {
+    {
+        .key = PIN(PORT_0, 0), /* SSP1_MISO */
+        .channel = CHANNEL_MISO(1),
+        .value = 1
+    }, {
+        .key = PIN(PORT_0, 1), /* SSP1_MOSI */
+        .channel = CHANNEL_MOSI(1),
+        .value = 1
+    }, {
+        .key = PIN(PORT_1, 0), /* SSP0_SSEL */
+        .channel = CHANNEL_SSEL(0),
+        .value = 5
+    }, {
+        .key = PIN(PORT_1, 1), /* SSP0_MISO */
+        .channel = CHANNEL_MISO(0),
+        .value = 5
+    }, {
+        .key = PIN(PORT_1, 2), /* SSP0_MOSI */
+        .channel = CHANNEL_MOSI(0),
+        .value = 5
+    }, {
+        .key = PIN(PORT_1, 3), /* SSP1_MISO */
+        .channel = CHANNEL_MISO(1),
+        .value = 5
+    }, {
+        .key = PIN(PORT_1, 4), /* SSP1_MOSI */
+        .channel = CHANNEL_MOSI(1),
+        .value = 5
+    }, {
+        .key = PIN(PORT_1, 5), /* SSP1_SSEL */
+        .channel = CHANNEL_SSEL(1),
+        .value = 5
+    }, {
+        .key = PIN(PORT_1, 19), /* SSP1_SCK */
+        .channel = CHANNEL_SCK(1),
+        .value = 1
+    }, {
+        .key = PIN(PORT_1, 20), /* SSP1_SSEL */
+        .channel = CHANNEL_SSEL(1),
+        .value = 1
+    }, {
+        .key = PIN(PORT_3, 0), /* SSP0_SCK */
+        .channel = CHANNEL_SCK(0),
+        .value = 5
+    }, {
+        .key = PIN(PORT_3, 3), /* SSP0_SCK */
+        .channel = CHANNEL_SCK(0),
+        .value = 2
+    }, {
+        .key = PIN(PORT_3, 6), /* SSP0_MISO */
+        .channel = CHANNEL_MISO(0),
+        .value = 5
+    }, {
+        .key = PIN(PORT_3, 6), /* SSP0_SSEL */
+        .channel = CHANNEL_SSEL(0),
+        .value = 2
+    }, {
+        .key = PIN(PORT_3, 7), /* SSP0_MISO */
+        .channel = CHANNEL_MISO(0),
+        .value = 2
+    }, {
+        .key = PIN(PORT_3, 7), /* SSP0_MOSI */
+        .channel = CHANNEL_MOSI(0),
+        .value = 5
+    }, {
+        .key = PIN(PORT_3, 8), /* SSP0_MOSI */
+        .channel = CHANNEL_MOSI(0),
+        .value = 2
+    }, {
+        .key = PIN(PORT_3, 8), /* SSP0_SSEL */
+        .channel = CHANNEL_SSEL(0),
+        .value = 5
+    }, {
+        .key = PIN(PORT_9, 0), /* SSP0_SSEL */
+        .channel = CHANNEL_SSEL(0),
+        .value = 7
+    }, {
+        .key = PIN(PORT_9, 1), /* SSP0_MISO */
+        .channel = CHANNEL_MISO(0),
+        .value = 7
+    }, {
+        .key = PIN(PORT_9, 2), /* SSP0_MOSI */
+        .channel = CHANNEL_MOSI(0),
+        .value = 7
+    }, {
+        .key = PIN(PORT_F, 0), /* SSP0_SCK */
+        .channel = CHANNEL_SCK(0),
+        .value = 0
+    }, {
+        .key = PIN(PORT_F, 1), /* SSP0_SSEL */
+        .channel = CHANNEL_SSEL(0),
+        .value = 2
+    }, {
+        .key = PIN(PORT_F, 2), /* SSP0_MISO */
+        .channel = CHANNEL_MISO(0),
+        .value = 2
+    }, {
+        .key = PIN(PORT_F, 3), /* SSP0_MOSI */
+        .channel = CHANNEL_MOSI(0),
+        .value = 2
+    }, {
+        .key = PIN(PORT_F, 4), /* SSP1_SCK */
+        .channel = CHANNEL_SCK(1),
+        .value = 0
+    }, {
+        .key = PIN(PORT_F, 5), /* SSP1_SSEL */
+        .channel = CHANNEL_SSEL(1),
+        .value = 2
+    }, {
+        .key = PIN(PORT_F, 6), /* SSP1_MISO */
+        .channel = CHANNEL_MISO(1),
+        .value = 2
+    }, {
+        .key = PIN(PORT_F, 7), /* SSP1_MOSI */
+        .channel = CHANNEL_MOSI(1),
+        .value = 2
+    }, {
+        .key = PIN(PORT_CLK, 0), /* SSP1_SCK */
+        .channel = CHANNEL_SCK(1),
+        .value = 6
+    }, {
+        .key = 0 /* End of pin function association list */
+    }
+};
+/*----------------------------------------------------------------------------*/
+const struct EntityClass * const SspBase = &sspTable;
+static struct SspBase *descriptors[2] = {0};
+/*----------------------------------------------------------------------------*/
+static enum result setDescriptor(uint8_t channel,
+    const struct SspBase *state, struct SspBase *interface)
+{
+  assert(channel < ARRAY_SIZE(descriptors));
+
+  return compareExchangePointer((void **)(descriptors + channel), state,
+      interface) ? E_OK : E_BUSY;
+}
+/*----------------------------------------------------------------------------*/
+static enum result setupPins(struct SspBase *interface,
+    const struct SspBaseConfig *config)
+{
+  const pin_t pinArray[4] = {
+      config->miso, config->mosi, config->sck, config->cs
+  };
+  const struct PinEntry *pinEntry;
+  struct Pin pin;
+
+  for (uint8_t index = 0; index < 4; ++index)
+  {
+    if (pinArray[index])
+    {
+      pinEntry = pinFind(sspPins, pinArray[index],
+          CHANNEL_INDEX(interface->channel, index));
+      if (!pinEntry)
+        return E_VALUE;
+      pinInput((pin = pinInit(pinArray[index])));
+      pinSetFunction(pin, pinEntry->value);
+    }
+  }
+
+  return E_OK;
+}
+/*----------------------------------------------------------------------------*/
+void SSP0_ISR(void)
+{
+  if (descriptors[0])
+    descriptors[0]->handler(descriptors[0]);
+}
+/*----------------------------------------------------------------------------*/
+void SSP1_ISR(void)
+{
+  if (descriptors[1])
+    descriptors[1]->handler(descriptors[1]);
+}
+/*----------------------------------------------------------------------------*/
+uint32_t sspGetClock(const struct SspBase *interface)
+{
+  const void *clock = 0;
+
+  switch (interface->channel)
+  {
+    case 0:
+      clock = Ssp0Clock;
+      break;
+
+    case 1:
+      clock = Ssp1Clock;
+      break;
+
+    default:
+      return 0;
+  }
+
+  return clockFrequency(clock);
+}
+/*----------------------------------------------------------------------------*/
+static enum result sspInit(void *object, const void *configBase)
+{
+  const struct SspBaseConfig * const config = configBase;
+  struct SspBase * const interface = object;
+  enum result res;
+
+  /* Try to set peripheral descriptor */
+  interface->channel = config->channel;
+  if ((res = setDescriptor(interface->channel, 0, interface)) != E_OK)
+    return res;
+
+  /*
+   * Pin setup is not similar to other device families due to differences in
+   * the pin tables. One pin may have more than two alternate functions of the
+   * same peripheral channel.
+   */
+  if ((res = setupPins(interface, config)) != E_OK)
+    return res;
+
+  const struct SspBlockDescriptor *entry = &sspBlockEntries[interface->channel];
+
+  /* Enable clocks to register interface and peripheral */
+  sysClockEnable(entry->periperalBranch);
+  sysClockEnable(entry->registerBranch);
+  /* Clear registers to default values */
+  sysResetEnable(entry->reset);
+
+  interface->handler = 0;
+  interface->irq = entry->irq;
+  interface->reg = entry->reg;
+
+  return E_OK;
+}
+/*----------------------------------------------------------------------------*/
+static void sspDeinit(void *object)
+{
+  const struct SspBase * const interface = object;
+  const struct SspBlockDescriptor *entry = &sspBlockEntries[interface->channel];
+
+  sysClockDisable(entry->registerBranch);
+  sysClockDisable(entry->periperalBranch);
+  setDescriptor(interface->channel, interface, 0);
+}