--- /dev/null
+#ifndef XBM_H
+#define XBM_H
+
+enum token_type {
+ TOKEN_NONE = 0,
+ TOKEN_IDENT,
+ TOKEN_INT,
+ TOKEN_SPECIAL,
+ TOKEN_OTHER,
+};
+
+#define MAX_TOKEN_SIZE (256)
+struct token {
+ char name[MAX_TOKEN_SIZE];
+ size_t pos;
+ enum token_type type;
+};
+
+/**
+ * tokenize - tokenize xbm file
+ * @buffer: buffer containing xbm file
+ * returns vector of tokens
+ */
+struct token *tokenize(char *buffer);
+
+#endif /* XBM_H */
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xbm.h"
+
+static char *current_buffer_position;
+static struct token *tokens;
+static int nr_tokens, alloc_tokens;
+
+static void add_token(enum token_type token_type)
+{
+ if (nr_tokens == alloc_tokens) {
+ alloc_tokens = (alloc_tokens + 16) * 2;
+ tokens = realloc(tokens, alloc_tokens * sizeof(struct token));
+ }
+ struct token *token = tokens + nr_tokens;
+ memset(token, 0, sizeof(*token));
+ nr_tokens++;
+ token->type = token_type;
+}
+
+static void get_identifier_token()
+{
+ struct token *token = tokens + nr_tokens - 1;
+ token->name[token->pos] = current_buffer_position[0];
+ token->pos++;
+ if (token->pos == MAX_TOKEN_SIZE - 1)
+ return;
+ current_buffer_position++;
+ switch (current_buffer_position[0]) {
+ case '\0':
+ return;
+ case 'a'...'z':
+ case 'A'...'Z':
+ case '_':
+ case '#':
+ get_identifier_token();
+ break;
+ default:
+ break;
+ }
+}
+
+static void get_number_token()
+{
+ struct token *token = tokens + nr_tokens - 1;
+ token->name[token->pos] = current_buffer_position[0];
+ token->pos++;
+ if (token->pos == MAX_TOKEN_SIZE - 1)
+ return;
+ current_buffer_position++;
+ switch (current_buffer_position[0]) {
+ case '\0':
+ return;
+ case '0'...'9':
+ case 'a'...'f':
+ case 'A'...'F':
+ case 'x':
+ get_number_token();
+ break;
+ default:
+ break;
+ }
+}
+
+static void get_special_char_token()
+{
+ struct token *token = tokens + nr_tokens - 1;
+ token->name[0] = current_buffer_position[0];
+ current_buffer_position++;
+}
+
+struct token *tokenize(char *buffer)
+{
+ current_buffer_position = buffer;
+
+ for (;;) {
+ switch (current_buffer_position[0]) {
+ case '\0':
+ goto out;
+ case 'a'...'z':
+ case 'A'...'Z':
+ case '_':
+ case '#':
+ add_token(TOKEN_IDENT);
+ get_identifier_token();
+ continue;
+ case '0'...'9':
+ add_token(TOKEN_INT);
+ get_number_token();
+ continue;
+ case '{':
+ add_token(TOKEN_SPECIAL);
+ get_special_char_token();
+ continue;
+ default:
+ break;
+ }
+ ++current_buffer_position;
+ }
+out:
+ add_token(TOKEN_NONE); /* vector end marker */
+ return tokens;
+}
--- /dev/null
+xbm-tokenize
--- /dev/null
+#define max_width 5
+#define max_height 5
+static unsigned char max_bits[] = {
+ 0x1F, 0x1B, 0x15, 0x1B, 0x1F };
--- /dev/null
+#define close_width 8
+#define close_height 8
+static unsigned char close_bits[] = {
+ 0xFF, 0xC3, 0xA5, 0x99, 0x99, 0xA5, 0xC3, 0xFF };
--- /dev/null
+#define x9_width 9
+#define x9_height 9
+static unsigned char x9_bits[] = {
+ 0xFF, 0x01, 0x83, 0x01, 0x45, 0x01, 0x29, 0x01, 0x11, 0x01, 0x29, 0x01,
+ 0x45, 0x01, 0x83, 0x01, 0xFF, 0x01 };
--- /dev/null
+CFLAGS += -g -Wall -O0 -std=c11
+CFLAGS += -I../../include
+LDFLAGS += `pkg-config --cflags --libs cairo`
+ASAN += -fsanitize=address
+
+PROGS = xbm-tokenize
+DEP_TOKENIZE = ../../src/common/buf.c ../../src/theme/xbm/tokenize.c
+
+all: $(PROGS)
+
+xbm-tokenize: xbm-tokenize.c $(DEP_TOKENIZE)
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(ASAN)
+
+clean :
+ $(RM) $(PROGS)
--- /dev/null
+#define _POSIX_C_SOURCE 200809L
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "buf.h"
+#include "xbm.h"
+
+/* Read file into buffer, because it's easier to tokenize that way */
+char *read_file(const char *filename)
+{
+ char *line = NULL;
+ size_t len = 0;
+ FILE *stream = fopen(filename, "r");
+ if (!stream) {
+ fprintf(stderr, "warn: cannot read '%s'\n", filename);
+ return NULL;
+ }
+ struct buf buffer;
+ buf_init(&buffer);
+ while ((getline(&line, &len, stream) != -1)) {
+ char *p = strrchr(line, '\n');
+ if (p)
+ *p = '\0';
+ buf_add(&buffer, line);
+ }
+ free(line);
+ fclose(stream);
+ return (buffer.buf);
+}
+
+int main(int argc, char **argv)
+{
+ struct token *tokens;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <xbm-file>\n", argv[0]);
+ return 1;
+ }
+
+ char *buffer = read_file(argv[1]);
+ if (!buffer)
+ exit(EXIT_FAILURE);
+ tokens = tokenize(buffer);
+ free(buffer);
+ for (struct token *t = tokens; t->type; t++)
+ printf("%s\n", t->name);
+}