source: trunk/minix/commands/cawf/device.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 9.0 KB
Line 
1/*
2 * device.c -- cawf(1) output device support functions
3 */
4
5/*
6 * Copyright (c) 1991 Purdue University Research Foundation,
7 * West Lafayette, Indiana 47907. All rights reserved.
8 *
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.
12 *
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:
16 *
17 * 1. The author is not responsible for any consequences of use of
18 * this software, even if they arise from flaws in it.
19 *
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.
23 *
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.
27 *
28 * 4. This notice may not be removed or altered.
29 */
30
31#include "cawf.h"
32#include <ctype.h>
33
34_PROTOTYPE(static unsigned char *Convstr,(char *s, int *len));
35_PROTOTYPE(static int Convfont,(char *nm, char *s, char **fn,
36 unsigned char **fi));
37
38#ifndef UNIX
39#define strcasecmp strcmpi
40#endif
41
42
43
44/*
45 * Convstr(s, len) - convert a string
46 */
47
48static unsigned char *
49Convstr(s, len)
50 char *s; /* input string */
51 int *len; /* length of result */
52{
53 int c; /* character assembly */
54 unsigned char *cp; /* temporary character pointer */
55 char *em; /* error message */
56 int i; /* temporary index */
57 int l; /* length */
58 unsigned char *r; /* result string */
59/*
60 * Make space for the result.
61 */
62 if ((r = (unsigned char *)malloc(strlen((char *)s) + 1)) == NULL) {
63 (void) fprintf(stderr, "%s: out of string space at %s\n",
64 Pname, s);
65 return(NULL);
66 }
67/*
68 * Copy the input string to the result, processing '\\' escapes.
69 */
70 for (cp = r, l = 0; *s;) {
71 switch (*s) {
72
73 case '\\':
74 s++;
75 if (*s >= '0' && *s <= '7') {
76 /*
77 * '\xxx' -- octal form
78 */
79 for (c = i = 0; i < 3; i++, s++) {
80 if (*s < '0' || *s > '7') {
81 em = "non-octal char";
82bad_string:
83 (void) fprintf(stderr,
84 "%s: %s : %s\n",
85 Pname, em, (char *)r);
86 return(NULL);
87 }
88 c = (c << 3) + *s - '0';
89 }
90 if (c > 0377) {
91 em = "octal char > 0377";
92 goto bad_string;
93 }
94 *cp++ = c;
95 l++;
96 } else if (*s == 'x') {
97 /*
98 * '\xyy' -- hexadecimal form
99 */
100 s++;
101 for (c = i = 0; i < 2; i++, s++) {
102#if defined(__STDC__)
103 if ( ! isalpha(*s) && ! isdigit(*s))
104#else
105 if ( ! isascii(*s) && ! isalpha(*s)
106 && ! isdigit(*s))
107#endif
108 {
109non_hex_char:
110 em = "non-hex char";
111 goto bad_string;
112 }
113 c = c << 4;
114 if (*s >= '0' && *s <= '9')
115 c += *s - '0';
116 else if ((*s >= 'a' && *s <= 'f')
117 || (*s >= 'A' && *s <= 'F'))
118 c += *s + 10 -
119 (isupper(*s) ? 'A' : 'a');
120 else
121 goto non_hex_char;
122 }
123 *cp++ = (unsigned char)c;
124 l++;
125 } else if (*s == 'E' || *s == 'e') {
126 /*
127 * '\E' or '\e' -- ESCape
128 */
129 *cp++ = ESC;
130 l++;
131 s++;
132 } else if (*s == '\0') {
133 em = "no char after \\";
134 goto bad_string;
135 } else {
136 /*
137 * escaped character (for some reason)
138 */
139 *cp++ = *s++;
140 l++;
141 }
142 break;
143 /*
144 * Copy a "normal" character.
145 */
146 default:
147 *cp++ = *s++;
148 l++;
149 }
150 }
151 *cp = '\0';
152 *len = l;
153 return(r);
154}
155
156
157/*
158 * Convfont(nm, s, fn, fi) - convert a font for a device
159 */
160
161static int
162Convfont(nm, s, fn, fi)
163 char *nm; /* output device name */
164 char *s; /* font definition string */
165 char **fn; /* font name address */
166 unsigned char **fi; /* initialization string address */
167{
168 char *cp; /* temporary character pointer */
169 int len; /* length */
170/*
171 * Get the font name, allocate space for it and allocate space for
172 * a font structure.
173 */
174 if ((cp = strchr(s, '=')) == NULL) {
175 (void) fprintf(stderr, "%s: bad %s font line format: %s\n",
176 Pname, nm, s);
177 return(0);
178 }
179 if ((*fn = (char *)malloc(cp - s + 1)) == NULL) {
180 (void) fprintf(stderr, "%s: no space for %s font name %s\n",
181 Pname, nm, s);
182 return(0);
183 }
184 (void) strncpy(*fn, s, cp - s);
185 (*fn)[cp - s] = '\0';
186/*
187 * Assmble the font initialization string.
188 */
189 if ((*fi = Convstr(cp + 1, &len)) == NULL)
190 return(0);
191 return(len);
192}
193
194
195/*
196 * Defdev() - define the output device
197 */
198
199int
200Defdev()
201{
202 unsigned char *fi = NULL; /* last font initialization string */
203 char *fn = NULL; /* font name */
204 int fd = 0; /* found-device flag */
205 FILE *fs; /* file stream */
206 int err = 0; /* errror count */
207 int i; /* temporary index */
208 int len; /* length */
209 char line[MAXLINE]; /* line buffer */
210 char *p; /* output device configuration file */
211 char *s; /* temporary string pointer */
212/*
213 * Check for the built-in devices, ANSI, NONE or NORMAL (default).
214 */
215 Fstr.b = Fstr.i = Fstr.it = Fstr.r = NULL;
216 Fstr.bl = Fstr.il = Fstr.itl = Fstr.rl = 0;
217 if (Device == NULL || strcasecmp(Device, "normal") == 0) {
218 Fontctl = 0;
219check_font:
220 if (Devfont) {
221 (void) fprintf(stderr,
222 "%s: font %s for device %s illegal\n",
223 Pname, Devfont, Device ? Device : "NORMAL");
224 return(1);
225 }
226 return(0);
227 }
228 Fontctl = 1;
229 if (strcasecmp(Device, "ansi") == 0) {
230 Fstr.b = Newstr((unsigned char *)"x[1m");
231 Fstr.it = Newstr((unsigned char *)"x[4m");
232 Fstr.r = Newstr((unsigned char *)"x[0m");
233 Fstr.b[0] = Fstr.it[0] = Fstr.r[0] = ESC;
234 Fstr.bl = Fstr.itl = Fstr.rl = 4;
235 goto check_font;
236 }
237 if (strcasecmp(Device, "none") == 0)
238 goto check_font;
239/*
240 * If a device configuration file path is supplied, use it.
241 */
242 if (Devconf)
243 p = Devconf;
244 else {
245
246 /*
247 * Use the CAWFLIB environment if it is defined.
248 */
249 if ((p = getenv("CAWFLIB")) == NULL)
250 p = CAWFLIB;
251 len = strlen(p) + 1 + strlen(DEVCONFIG) + 1;
252 if ((s = (char *)malloc(len)) == NULL) {
253 (void) fprintf(stderr, "%s: no space for %s name\n",
254 Pname, DEVCONFIG);
255 return(1);
256 }
257 (void) sprintf(s, "%s/%s", p, DEVCONFIG);
258 p = s;
259 }
260/*
261 * Open the configuration file.
262 */
263#ifdef UNIX
264 if ((fs = fopen(p, "r")) == NULL)
265#else
266 if ((fs = fopen(p, "rt")) == NULL)
267#endif
268 {
269 (void) fprintf(stderr, "%s: can't open config file: %s\n",
270 Pname, p);
271 return(1);
272 }
273 *line = ' ';
274/*
275 * Look for a device definition line -- a line that begins with a name.
276 */
277 while ( ! feof(fs)) {
278 if (*line == '\t' || *line == '#' || *line == ' ') {
279 (void) fgets(line, MAXLINE, fs);
280 continue;
281 }
282 if ((s = strrchr(line, '\n')) != NULL)
283 *s = '\0';
284 else
285 line[MAXLINE-1] = '\0';
286 /*
287 * Match device name.
288 */
289 if (strcmp(Device, line) != 0) {
290 (void) fgets(line, MAXLINE, fs);
291 continue;
292 }
293 fd = 1;
294 /*
295 * Read the parameter lines for the device.
296 */
297 while (fgets(line, MAXLINE, fs) != NULL) {
298 if (*line == ' ') {
299 for (i = 1; line[i] == ' '; i++)
300 ;
301 } else if (*line == '\t')
302 i = 1;
303 else
304 break;
305#if defined(__STDC__)
306 if ( ! isalpha(line[i])
307#else
308 if ( ! isascii(line[i]) || ! isalpha(line[i])
309#endif
310 || line[i+1] != '=')
311 break;
312 if ((s = strrchr(line, '\n')) != NULL)
313 *s = '\0';
314 else
315 line[MAXLINE-1] = '\0';
316 switch (line[i]) {
317 /*
318 * \tb=<bolding_string>
319 */
320 case 'b':
321 if (Fstr.b != NULL) {
322 (void) fprintf(stderr,
323 "%s: dup bold for %s in %s: %s\n",
324 Pname, Device, p, line);
325 (void) free(Fstr.b);
326 Fstr.b = NULL;
327 }
328 if ((Fstr.b = Convstr(&line[i+2], &Fstr.bl))
329 == NULL)
330 err++;
331 break;
332 /*
333 * \ti=<italicization_string>
334 */
335 case 'i':
336 if (Fstr.it != NULL) {
337 (void) fprintf(stderr,
338 "%s: dup italic for %s in %s: %s\n",
339 Pname, Device, p, line);
340 (void) free(Fstr.it);
341 Fstr.it = NULL;
342 }
343 if ((Fstr.it = Convstr(&line[i+2], &Fstr.itl))
344 == NULL)
345 err++;
346 break;
347 /*
348 * \tr=<return_to_Roman_string>
349 */
350 case 'r':
351 if (Fstr.r != NULL) {
352 (void) fprintf(stderr,
353 "%s: dup roman for %s in %s: %s\n",
354 Pname, Device, p, line);
355 (void) free(Fstr.r);
356 Fstr.r = NULL;
357 }
358 if ((Fstr.r = Convstr(&line[i+2], &Fstr.rl))
359 == NULL)
360 err++;
361 break;
362 /*
363 * \tf=<font_name>=<font_initialization_string>
364 */
365 case 'f':
366 if ( ! Devfont || Fstr.i)
367 break;
368 if ((i = Convfont(Device, &line[i+2], &fn, &fi))
369 < 0)
370 err++;
371 else if (fn && strcmp(Devfont, fn) == 0) {
372 Fstr.i = fi;
373 Fstr.il = i;
374 fi = NULL;
375 }
376 if (fn) {
377 (void) free(fn);
378 fn = NULL;
379 }
380 if (fi) {
381 (void) free((char *)fi);
382 fi = NULL;
383 }
384 break;
385 /*
386 * ????
387 */
388 default:
389 (void) fprintf(stderr,
390 "%s: unknown device %s line: %s\n",
391 Pname, Device, line);
392 err++;
393 }
394 }
395 break;
396 }
397 (void) fclose(fs);
398 if (err)
399 return(1);
400/*
401 * See if the device stanza was located and the font exists.
402 */
403 if ( ! fd) {
404 (void) fprintf(stderr, "%s: can't find device %s in %s\n",
405 Pname, Device, p);
406 return(1);
407 }
408 if (Devfont && ! Fstr.i) {
409 (void) fprintf(stderr,
410 "%s: font %s for device %s not found in %s\n",
411 Pname, Devfont, Device, p);
412 return(1);
413 }
414 return(0);
415}
Note: See TracBrowser for help on using the repository browser.