aboutsummaryrefslogtreecommitdiffstats
path: root/bie.c
blob: 66c97c9532f4bf7dc423d9386a60b09449710a19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
 * SPDX-License-Identifier: MIT
 */
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#include "eprintf.h"

#ifndef VERSION
#define VERSION "v0.1"
#endif

enum {
	ALIGN = 16,
};

static const char *usage = "[-hv] [--] output map input...";

static void help(void)
{
	fprintf(stderr,
		"Options:\n"
		"    -h  Show this help.\n"
		"    -v  Show version and license information.\n"
		"\n"
		"Please check the bie(1) man page for more information.\n");
}

static void version(void)
{
	fprintf(stderr,
		"bie %s\n"
		"Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>\n"
		"Licensed under the MIT license <https://opensource.org/licenses/MIT>\n"
		"There is NO WARRANTY, to the extent permitted by law.\n",
		VERSION);
}

static void slug(FILE *f, const char *text)
{
	bool leading = true;
	int c;

	while (c = *text++, c != '\0') {
		if (isalpha(c)) {
			leading = false;
			fputc(c, f);
			continue;
		}
		if (leading) continue;
		if (isdigit(c))
			fputc(c, f);
		else if (ispunct(c) || isspace(c))
			fputc('_', f);
	}
}

static void mapentry(FILE *map, const char *name, size_t pos, size_t size)
{
	fprintf(map, "BIE_ENTRY(");
	slug(map, name);
	fprintf(map, ", %zu, %zu)\n", pos, size);
}

static size_t dumpfile(FILE *dest, FILE *src)
{
	size_t size = 0;
	int c;

	while (c = fgetc(src), c != EOF) {
		size++;
		fputc(c, dest);
	}

	return size;
}

int main(int argc, char **argv)
{
	const char *argv0 = argv[0] != NULL ? argv[0] : "bie";
	FILE *dest, *map;
	size_t pos = 0;

	setprogname(argv0);

	for (argv++, argc--; argv[0] != NULL && argv[0][0] == '-' &&
		     argv[0][1] != '-' && argv[0][2] == '\0'; argv++, argc--) {
		switch (argv[0][1]) {
		case 'h':
			fprintf(stderr, "Usage: %s %s\n", argv0, usage);
			help();
			return EXIT_SUCCESS;
		case 'v':
			version();
			return EXIT_SUCCESS;
		}
	}

	if (argc < 3)
		eprintf("Invalid argument count\nUsage: %s %s", argv0, usage);

	dest = fopen(argv[0], "wb");
	if (dest == NULL)
		eprintf("Could not open `%s':", argv[0]);

	map = fopen(argv[1], "w");
	if (map == NULL)
		eprintf("Could not open `%s':", argv[1]);

	for (int i = 2; i < argc; i++) {
		size_t size;
		FILE *src;

		src = fopen(argv[i], "rb");
		if (src == NULL)
			eprintf("Could not open `%s':", argv[i]);
		size = dumpfile(dest, src);
		fclose(src);
		mapentry(map, argv[i], pos, size);
		pos += size;
		if (pos % ALIGN) {
			size_t pad = ALIGN - pos % ALIGN;
			for (size_t i = 0; i < pad; i++)
				fputc(0, dest);
			pos += pad;
		}
	}

	fclose(map);
	fclose(dest);
}