]> git.gir.st - base65536.git/blob - main.c
Removed long options in favour of `getopt()`, changed comment style to c89, fixed...
[base65536.git] / main.c
1 /* base65536 en- and decoder with usage similar to GNU's base64.
2 (C) 2016 Tobias Girstmair, http://isticktoit.net/
3 Released under the GNU GPL v3. See LICENSE for details. */
4
5 #define _XOPEN_SOURCE
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include "base65536.h"
11
12 #define VERSION "0.2"
13
14 #define DEFAULT_WRAP 72
15
16 #define COPYRIGHT "(C) 2016 Tobias Girstmair, GPLv3"
17 #define HELP_TEXT \
18 "Usage: %s [OPTION]... [FILE]\n"\
19 "Options: -d (decode), -i (ignore-garbage), -w COLS (wrap, default %d) "\
20 "-v (version) -h (help)\n"
21
22 struct ops {
23 FILE* f;
24 int d; /*decode*/
25 int i; /*ignore-garbage*/
26 int w; /*wrap*/
27 };
28
29 void do_encode (FILE* in, FILE* out, int wrap_column);
30 void do_decode (FILE* in, FILE* out, int ignore_garbage);
31
32 int main (int argc, char** argv) {
33 struct ops op = {stdin, 0, 0, DEFAULT_WRAP};
34 int opt;
35
36 opterr=0; /* suppress default error messages */
37 while ( (opt = getopt(argc, argv, "diw:vh")) != -1) {
38 switch (opt) {
39 case 'd': op.d = 1; break;
40 case 'i': op.i = 1; break;
41 case 'w': op.w = atoi (optarg); break;
42 case 'v':
43 fprintf (stderr, "base65536 %s\n%s\n", VERSION, COPYRIGHT);
44 return 0;
45 case 'h':
46 fprintf (stderr, HELP_TEXT, argv[0], DEFAULT_WRAP);
47 return 0;
48 default:
49 fprintf (stderr, "unknown option '-%c'.\n", optopt);
50 return 1;
51 }
52 }
53 if (argc-optind > 1) {
54 fprintf (stderr, "%s: extra operand '%s'. \n", argv[0], argv[argc-1]);
55 return 1;
56 } else if (optind < argc) {
57 if (strcmp (argv [optind], "-") != 0)
58 op.f = fopen (argv[optind], "rb");
59 }
60
61 if (op.d) {
62 do_decode (op.f, stdout, op.i);
63 } else {
64 do_encode (op.f, stdout, op.w);
65 }
66
67 if (op.f != stdin) fclose (op.f);
68
69 return 0;
70 }
71
72
73 void do_encode (FILE* in, FILE* out, int wrap_column) {
74 int in_char[2];
75 char out_utf8[5];
76 int unicode_cp;
77 long cnt = 0;
78
79 while (1) {
80 if ((in_char[0] = getc(in)) == EOF) break;
81 in_char[1] = getc(in);
82
83 unicode_cp = base65536_encode_char (in_char);
84 codepoint_to_utf8 (unicode_cp, out_utf8);
85 fprintf (out, "%s%s", wrap_column&&!(cnt%wrap_column)&&cnt?"\n":"", out_utf8);
86 cnt++;
87 if (in_char[1] == EOF) break;
88 }
89 printf ("\n");
90 }
91
92 void do_decode (FILE* in, FILE* out, int ignore_garbage) {
93 int out_char[2];
94 char in_utf8[5];
95 int unicode_cp;
96 int chars_written;
97
98 while (1) {
99 for (int i = 0; i < 5; i++) {
100 int c = getc (in);
101 if (c == EOF) {
102 return;
103 } else if (i != 0 && c < 0x80) { /* start of new asciichar */
104 ungetc (c, in);
105 in_utf8[i] = '\0';
106 break;
107 } else if (i != 0 && c >= 0xc0) { /* start of new utf8char */
108 ungetc (c, in);
109 in_utf8[i] = '\0';
110 break;
111 }
112 in_utf8[i] = c;
113 }
114 unicode_cp = utf8_to_codepoint (in_utf8);
115 /* ignore ascii-chars, because base65k won't map to those (but
116 whitespace may be added by the encoder / medium) */
117 if (unicode_cp < 0x80) continue;
118
119 chars_written = base65536_decode_char (unicode_cp, out_char);
120 if (chars_written > 0) {
121 fputc (out_char[0], out);
122 if (chars_written ==2) fputc (out_char[1], out);
123 } else {
124 if (!ignore_garbage) {
125 fprintf (stderr, "Unrecognized glyph %s\n", in_utf8);
126 return;
127 }
128 }
129 }
130 }
Imprint / Impressum