mkfs: symlink support
[minix.git] / commands / cawf / device.c
blobc7c91191178dad12aae3b97eee3d435f06c1561d
1 /*
2 * device.c -- cawf(1) output device support functions
3 */
5 /*
6 * Copyright (c) 1991 Purdue University Research Foundation,
7 * West Lafayette, Indiana 47907. All rights reserved.
9 * Written by Victor A. Abell <abe@mace.cc.purdue.edu>, Purdue
10 * University Computing Center. Not derived from licensed software;
11 * derived from awf(1) by Henry Spencer of the University of Toronto.
13 * Permission is granted to anyone to use this software for any
14 * purpose on any computer system, and to alter it and redistribute
15 * it freely, subject to the following restrictions:
17 * 1. The author is not responsible for any consequences of use of
18 * this software, even if they arise from flaws in it.
20 * 2. The origin of this software must not be misrepresented, either
21 * by explicit claim or by omission. Credits must appear in the
22 * documentation.
24 * 3. Altered versions must be plainly marked as such, and must not
25 * be misrepresented as being the original software. Credits must
26 * appear in the documentation.
28 * 4. This notice may not be removed or altered.
31 #include "cawf.h"
32 #include <ctype.h>
34 static unsigned char *Convstr(char *s, int *len);
35 static int Convfont(char *nm, char *s, char **fn, unsigned char **fi);
37 #ifndef UNIX
38 #define strcasecmp strcmpi
39 #endif
44 * Convstr(s, len) - convert a string
47 static unsigned char *
48 Convstr(s, len)
49 char *s; /* input string */
50 int *len; /* length of result */
52 int c; /* character assembly */
53 unsigned char *cp; /* temporary character pointer */
54 char *em; /* error message */
55 int i; /* temporary index */
56 int l; /* length */
57 unsigned char *r; /* result string */
59 * Make space for the result.
61 if ((r = (unsigned char *)malloc(strlen((char *)s) + 1)) == NULL) {
62 (void) fprintf(stderr, "%s: out of string space at %s\n",
63 Pname, s);
64 return(NULL);
67 * Copy the input string to the result, processing '\\' escapes.
69 for (cp = r, l = 0; *s;) {
70 switch (*s) {
72 case '\\':
73 s++;
74 if (*s >= '0' && *s <= '7') {
76 * '\xxx' -- octal form
78 for (c = i = 0; i < 3; i++, s++) {
79 if (*s < '0' || *s > '7') {
80 em = "non-octal char";
81 bad_string:
82 (void) fprintf(stderr,
83 "%s: %s : %s\n",
84 Pname, em, (char *)r);
85 return(NULL);
87 c = (c << 3) + *s - '0';
89 if (c > 0377) {
90 em = "octal char > 0377";
91 goto bad_string;
93 *cp++ = c;
94 l++;
95 } else if (*s == 'x') {
97 * '\xyy' -- hexadecimal form
99 s++;
100 for (c = i = 0; i < 2; i++, s++) {
101 #if defined(__STDC__)
102 if ( ! isalpha(*s) && ! isdigit(*s))
103 #else
104 if ( ! isascii(*s) && ! isalpha(*s)
105 && ! isdigit(*s))
106 #endif
108 non_hex_char:
109 em = "non-hex char";
110 goto bad_string;
112 c = c << 4;
113 if (*s >= '0' && *s <= '9')
114 c += *s - '0';
115 else if ((*s >= 'a' && *s <= 'f')
116 || (*s >= 'A' && *s <= 'F'))
117 c += *s + 10 -
118 (isupper(*s) ? 'A' : 'a');
119 else
120 goto non_hex_char;
122 *cp++ = (unsigned char)c;
123 l++;
124 } else if (*s == 'E' || *s == 'e') {
126 * '\E' or '\e' -- ESCape
128 *cp++ = ESC;
129 l++;
130 s++;
131 } else if (*s == '\0') {
132 em = "no char after \\";
133 goto bad_string;
134 } else {
136 * escaped character (for some reason)
138 *cp++ = *s++;
139 l++;
141 break;
143 * Copy a "normal" character.
145 default:
146 *cp++ = *s++;
147 l++;
150 *cp = '\0';
151 *len = l;
152 return(r);
157 * Convfont(nm, s, fn, fi) - convert a font for a device
160 static int
161 Convfont(nm, s, fn, fi)
162 char *nm; /* output device name */
163 char *s; /* font definition string */
164 char **fn; /* font name address */
165 unsigned char **fi; /* initialization string address */
167 char *cp; /* temporary character pointer */
168 int len; /* length */
170 * Get the font name, allocate space for it and allocate space for
171 * a font structure.
173 if ((cp = strchr(s, '=')) == NULL) {
174 (void) fprintf(stderr, "%s: bad %s font line format: %s\n",
175 Pname, nm, s);
176 return(0);
178 if ((*fn = (char *)malloc(cp - s + 1)) == NULL) {
179 (void) fprintf(stderr, "%s: no space for %s font name %s\n",
180 Pname, nm, s);
181 return(0);
183 (void) strncpy(*fn, s, cp - s);
184 (*fn)[cp - s] = '\0';
186 * Assmble the font initialization string.
188 if ((*fi = Convstr(cp + 1, &len)) == NULL)
189 return(0);
190 return(len);
195 * Defdev() - define the output device
199 Defdev()
201 unsigned char *fi = NULL; /* last font initialization string */
202 char *fn = NULL; /* font name */
203 int fd = 0; /* found-device flag */
204 FILE *fs; /* file stream */
205 int err = 0; /* errror count */
206 int i; /* temporary index */
207 int len; /* length */
208 char line[MAXLINE]; /* line buffer */
209 char *p; /* output device configuration file */
210 char *s; /* temporary string pointer */
212 * Check for the built-in devices, ANSI, NONE or NORMAL (default).
214 Fstr.b = Fstr.i = Fstr.it = Fstr.r = NULL;
215 Fstr.bl = Fstr.il = Fstr.itl = Fstr.rl = 0;
216 if (Device == NULL || strcasecmp(Device, "normal") == 0) {
217 Fontctl = 0;
218 check_font:
219 if (Devfont) {
220 (void) fprintf(stderr,
221 "%s: font %s for device %s illegal\n",
222 Pname, Devfont, Device ? Device : "NORMAL");
223 return(1);
225 return(0);
227 Fontctl = 1;
228 if (strcasecmp(Device, "ansi") == 0) {
229 Fstr.b = Newstr((unsigned char *)"x[1m");
230 Fstr.it = Newstr((unsigned char *)"x[4m");
231 Fstr.r = Newstr((unsigned char *)"x[0m");
232 Fstr.b[0] = Fstr.it[0] = Fstr.r[0] = ESC;
233 Fstr.bl = Fstr.itl = Fstr.rl = 4;
234 goto check_font;
236 if (strcasecmp(Device, "none") == 0)
237 goto check_font;
239 * If a device configuration file path is supplied, use it.
241 if (Devconf)
242 p = Devconf;
243 else {
246 * Use the CAWFLIB environment if it is defined.
248 if ((p = getenv("CAWFLIB")) == NULL)
249 p = CAWFLIB;
250 len = strlen(p) + 1 + strlen(DEVCONFIG) + 1;
251 if ((s = (char *)malloc(len)) == NULL) {
252 (void) fprintf(stderr, "%s: no space for %s name\n",
253 Pname, DEVCONFIG);
254 return(1);
256 (void) sprintf(s, "%s/%s", p, DEVCONFIG);
257 p = s;
260 * Open the configuration file.
262 #ifdef UNIX
263 if ((fs = fopen(p, "r")) == NULL)
264 #else
265 if ((fs = fopen(p, "rt")) == NULL)
266 #endif
268 (void) fprintf(stderr, "%s: can't open config file: %s\n",
269 Pname, p);
270 return(1);
272 *line = ' ';
274 * Look for a device definition line -- a line that begins with a name.
276 while ( ! feof(fs)) {
277 if (*line == '\t' || *line == '#' || *line == ' ') {
278 (void) fgets(line, MAXLINE, fs);
279 continue;
281 if ((s = strrchr(line, '\n')) != NULL)
282 *s = '\0';
283 else
284 line[MAXLINE-1] = '\0';
286 * Match device name.
288 if (strcmp(Device, line) != 0) {
289 (void) fgets(line, MAXLINE, fs);
290 continue;
292 fd = 1;
294 * Read the parameter lines for the device.
296 while (fgets(line, MAXLINE, fs) != NULL) {
297 if (*line == ' ') {
298 for (i = 1; line[i] == ' '; i++)
300 } else if (*line == '\t')
301 i = 1;
302 else
303 break;
304 #if defined(__STDC__)
305 if ( ! isalpha(line[i])
306 #else
307 if ( ! isascii(line[i]) || ! isalpha(line[i])
308 #endif
309 || line[i+1] != '=')
310 break;
311 if ((s = strrchr(line, '\n')) != NULL)
312 *s = '\0';
313 else
314 line[MAXLINE-1] = '\0';
315 switch (line[i]) {
317 * \tb=<bolding_string>
319 case 'b':
320 if (Fstr.b != NULL) {
321 (void) fprintf(stderr,
322 "%s: dup bold for %s in %s: %s\n",
323 Pname, Device, p, line);
324 (void) free(Fstr.b);
325 Fstr.b = NULL;
327 if ((Fstr.b = Convstr(&line[i+2], &Fstr.bl))
328 == NULL)
329 err++;
330 break;
332 * \ti=<italicization_string>
334 case 'i':
335 if (Fstr.it != NULL) {
336 (void) fprintf(stderr,
337 "%s: dup italic for %s in %s: %s\n",
338 Pname, Device, p, line);
339 (void) free(Fstr.it);
340 Fstr.it = NULL;
342 if ((Fstr.it = Convstr(&line[i+2], &Fstr.itl))
343 == NULL)
344 err++;
345 break;
347 * \tr=<return_to_Roman_string>
349 case 'r':
350 if (Fstr.r != NULL) {
351 (void) fprintf(stderr,
352 "%s: dup roman for %s in %s: %s\n",
353 Pname, Device, p, line);
354 (void) free(Fstr.r);
355 Fstr.r = NULL;
357 if ((Fstr.r = Convstr(&line[i+2], &Fstr.rl))
358 == NULL)
359 err++;
360 break;
362 * \tf=<font_name>=<font_initialization_string>
364 case 'f':
365 if ( ! Devfont || Fstr.i)
366 break;
367 if ((i = Convfont(Device, &line[i+2], &fn, &fi))
368 < 0)
369 err++;
370 else if (fn && strcmp(Devfont, fn) == 0) {
371 Fstr.i = fi;
372 Fstr.il = i;
373 fi = NULL;
375 if (fn) {
376 (void) free(fn);
377 fn = NULL;
379 if (fi) {
380 (void) free((char *)fi);
381 fi = NULL;
383 break;
385 * ????
387 default:
388 (void) fprintf(stderr,
389 "%s: unknown device %s line: %s\n",
390 Pname, Device, line);
391 err++;
394 break;
396 (void) fclose(fs);
397 if (err)
398 return(1);
400 * See if the device stanza was located and the font exists.
402 if ( ! fd) {
403 (void) fprintf(stderr, "%s: can't find device %s in %s\n",
404 Pname, Device, p);
405 return(1);
407 if (Devfont && ! Fstr.i) {
408 (void) fprintf(stderr,
409 "%s: font %s for device %s not found in %s\n",
410 Pname, Devfont, Device, p);
411 return(1);
413 return(0);