1 /*
2 * Copyright (c) 2019 Georg Brein. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <wchar.h>
35 #include <wctype.h>
36
37 #include "tnylpo.h"
38
39
40 /*
41 * return base name of Unix path
42 */
43 const char *
base_name(const char * path)44 base_name(const char *path) {
45 const char *cp = path + strlen(path);
46 while (cp != path && *(cp - 1) != '/') cp--;
47 return cp;
48 }
49
50
51 /*
52 * allocate memory, scream and die if there is no more memory available
53 */
54 void *
alloc(size_t s)55 alloc(size_t s) {
56 void *vp = malloc(s);
57 if (! vp) {
58 perr("out of memory");
59 exit(EXIT_FAILURE);
60 }
61 return vp;
62 }
63
64
65 /*
66 * same, but reallocates memory
67 */
resize(void * vp,size_t s)68 void *resize(void *vp, size_t s) {
69 void *tp = realloc(vp, s);
70 if (! tp) {
71 perr("out of memory");
72 exit(EXIT_FAILURE);
73 }
74 return tp;
75 }
76
77
78 /*
79 * convert a Unix character to the CP/M character set
80 * returns (-1) if the character cannot converted, and the 8-bit
81 * character value otherwise
82 */
83 int
to_cpm(wchar_t c)84 to_cpm(wchar_t c) {
85 int i;
86 wchar_t **cs;
87 /*
88 * control characters are passed through unaltered
89 */
90 if ((c >= 0x00 && c <= 0x1f) || c == 0x7f) return (int) c;
91 /*
92 * primary or alternate character set?
93 */
94 cs = charset ? conf_alt_charset : conf_charset;
95 /*
96 * check the potentially printable character range (skipping DEL)
97 */
98 for (i = 0x20; i < 0x100; i++) {
99 if (i == 0x7f || ! cs[i]) continue;
100 if (cs[i][0] == c) return i;
101 }
102 return (-1);
103 }
104
105
106 /*
107 * convert a CP/M character to a Unix character
108 * returns (wint_t) (-1) if the character cannot be translated and there
109 * is no representation for unprintable characters defined, and the
110 * Unix wchar otherwise
111 */
112 wint_t
from_cpm(unsigned char c)113 from_cpm(unsigned char c) {
114 wchar_t **cs;
115 /*
116 * control characters are passed through unaltered
117 */
118 if (c <= 0x1f /* US */ || c == 0x7f /* DEL */) return c;
119 /*
120 * primary or alternate character set?
121 */
122 cs = charset ? conf_alt_charset : conf_charset;
123 if (! cs[c]) {
124 /*
125 * replace untranslateable characters by the
126 * "unprintable" character, if one is defined
127 */
128 if (conf_unprintable) return conf_unprintable[0];
129 return (-1);
130 }
131 return cs[c][0];
132 }
133
134
135 /*
136 * same as from_cpm(), but characters in the range 0x5e ... 0x7e are
137 * mapped to 0x7f, 0x1f, 0x00 ... 0x1e to implement the "graphic
138 * character set" feature of the VT52
139 */
140 wint_t
from_graph(unsigned char c)141 from_graph(unsigned char c) {
142 wchar_t **cs;
143 /*
144 * control characters are passed through unaltered
145 */
146 if (c <= 0x1f /* US */ || c == 0x7f /* DEL */) return c;
147 /*
148 * map 0x5e ... 0x7e to the "graphic" positions
149 */
150 if (c >= 0x60 /* @ */ && c <= 0x7e /* ~ */) {
151 c -= 0x60; /* @ --> NUL; ~ --> RS */
152 } else if (c == 0x5f /* _ */) {
153 c = 0x1f /* US */;
154 } else if (c == 0x5e /* ^ */) {
155 c = 0x7f /* DEL */;
156 }
157 /*
158 * primary or alternate character set?
159 */
160 cs = charset ? conf_alt_charset : conf_charset;
161 if (! cs[c]) {
162 if (conf_unprintable) return conf_unprintable[0];
163 return (-1);
164 }
165 return cs[c][0];
166 }
167