dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

emacsql.c (4989B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include "sqlite3.h"
      5 
      6 #define TRUE 1
      7 #define FALSE 0
      8 
      9 char* escape(const char *message) {
     10     int i, count = 0, length_orig = strlen(message);
     11     for (i = 0; i < length_orig; i++) {
     12         if (strchr("\"\\", message[i])) {
     13             count++;
     14         }
     15     }
     16     char *copy = malloc(length_orig + count + 1);
     17     char *p = copy;
     18     while (*message) {
     19         if (strchr("\"\\", *message)) {
     20             *p = '\\';
     21             p++;
     22         }
     23         *p = *message;
     24         message++;
     25         p++;
     26     }
     27     *p = '\0';
     28     return copy;
     29 }
     30 
     31 void send_error(int code, const char *message) {
     32     char *escaped = escape(message);
     33     printf("error %d \"%s\"\n", code, escaped);
     34     free(escaped);
     35 }
     36 
     37 typedef struct {
     38     char *buffer;
     39     size_t size;
     40 } buffer;
     41 
     42 buffer* buffer_create() {
     43     buffer *buffer = malloc(sizeof(buffer));
     44     buffer->size = 4096;
     45     buffer->buffer = malloc(buffer->size * sizeof(char));
     46     return buffer;
     47 }
     48 
     49 int buffer_grow(buffer *buffer) {
     50     unsigned factor = 2;
     51     char *newbuffer = realloc(buffer->buffer, buffer->size * factor);
     52     if (newbuffer == NULL) {
     53         return FALSE;
     54     }
     55     buffer->buffer = newbuffer;
     56     buffer->size *= factor;
     57     return TRUE;
     58 }
     59 
     60 int buffer_read(buffer *buffer, size_t count) {
     61     while (buffer->size < count + 1) {
     62         if (buffer_grow(buffer) == FALSE) {
     63             return FALSE;
     64         }
     65     }
     66     size_t in = fread((void *) buffer->buffer, 1, count, stdin);
     67     buffer->buffer[count] = '\0';
     68     return in == count;
     69 }
     70 
     71 void buffer_free(buffer *buffer) {
     72     free(buffer->buffer);
     73     free(buffer);
     74 }
     75 
     76 int main(int argc, char **argv) {
     77     char *file = NULL;
     78     if (argc != 2) {
     79         fprintf(stderr,
     80                 "error: require exactly one argument, the DB filename\n");
     81         exit(EXIT_FAILURE);
     82     } else {
     83         file = argv[1];
     84     }
     85 
     86     /* On Windows stderr is not always unbuffered. */
     87 #if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__)
     88     setvbuf(stderr, NULL, _IONBF, 0);
     89 #endif
     90 
     91     sqlite3* db = NULL;
     92     if (sqlite3_initialize() != SQLITE_OK) {
     93         fprintf(stderr, "error: failed to initialize sqlite\n");
     94         exit(EXIT_FAILURE);
     95     }
     96     int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
     97     if (sqlite3_open_v2(file, &db, flags, NULL) != SQLITE_OK) {
     98         fprintf(stderr, "error: failed to open %s\n", file);
     99         exit(EXIT_FAILURE);
    100     }
    101 
    102     buffer *input = buffer_create();
    103     while (TRUE) {
    104         printf("#\n");
    105         fflush(stdout);
    106 
    107         /* Gather input from Emacs. */
    108         unsigned length;
    109         int result = scanf("%u ", &length);
    110         if (result == EOF) {
    111             break;
    112         } else if (result != 1) {
    113             send_error(SQLITE_ERROR, "middleware parsing error");
    114             break;  /* stream out of sync: quit program */
    115         }
    116         if (!buffer_read(input, length)) {
    117             send_error(SQLITE_NOMEM, "middleware out of memory");
    118             continue;
    119         }
    120 
    121         /* Parse SQL statement. */
    122         sqlite3_stmt *stmt = NULL;
    123         result = sqlite3_prepare_v2(db, input->buffer, length, &stmt, NULL);
    124         if (result != SQLITE_OK) {
    125             send_error(sqlite3_errcode(db), sqlite3_errmsg(db));
    126             continue;
    127         }
    128 
    129         /* Print out rows. */
    130         int first = TRUE, ncolumns = sqlite3_column_count(stmt);
    131         printf("(");
    132         while (sqlite3_step(stmt) == SQLITE_ROW) {
    133             if (first) {
    134                 printf("(");
    135                 first = FALSE;
    136             } else {
    137                 printf("\n (");
    138             }
    139             int i;
    140             for (i = 0; i < ncolumns; i++) {
    141                 if (i > 0) {
    142                     printf(" ");
    143                 }
    144                 int type = sqlite3_column_type(stmt, i);
    145                 switch (type) {
    146                 case SQLITE_INTEGER:
    147                     printf("%lld", sqlite3_column_int64(stmt, i));
    148                     break;
    149                 case SQLITE_FLOAT:
    150                     printf("%f", sqlite3_column_double(stmt, i));
    151                     break;
    152                 case SQLITE_NULL:
    153                     printf("nil");
    154                     break;
    155                 case SQLITE_TEXT:
    156                     fwrite(sqlite3_column_text(stmt, i), 1,
    157                            sqlite3_column_bytes(stmt, i), stdout);
    158                     break;
    159                 case SQLITE_BLOB:
    160                     printf("nil");
    161                     break;
    162                 }
    163             }
    164             printf(")");
    165         }
    166         printf(")\n");
    167         if (sqlite3_finalize(stmt) != SQLITE_OK) {
    168             /* Despite any error code, the statement is still freed.
    169              * http://stackoverflow.com/a/8391872
    170              */
    171             send_error(sqlite3_errcode(db), sqlite3_errmsg(db));
    172         } else {
    173             printf("success\n");
    174         }
    175     }
    176     buffer_free(input);
    177 
    178     sqlite3_close(db);
    179     sqlite3_shutdown();
    180     return EXIT_SUCCESS;
    181 }