[BUILD] Fix build warnings
[platform/upstream/kbd.git] / src / mapscrn.c
1 /*
2  * mapscrn.c
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <memory.h>
8 #include <string.h>
9 #include <fcntl.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/ioctl.h>
13 #include <linux/kd.h>
14 #include "kbd.h"
15 #include "paths.h"
16 #include "findfile.h"
17 #include "kdmapop.h"
18 #include "utf8.h"
19 #include "nls.h"
20
21 /* the two exported functions */
22 void saveoldmap(int fd, char *omfil);
23 void loadnewmap(int fd, char *mfil);
24
25 static int ctoi (char *);
26
27 /* search for the map file in these directories (with trailing /) */
28 static char *mapdirpath[] = { "", DATADIR "/" TRANSDIR "/", 0 };
29 static char *mapsuffixes[] = { "", ".trans", "_to_uni.trans", ".acm", 0 };
30
31 #ifdef MAIN
32 #include "getfd.h"
33 #include "version.h"
34
35 int verbose = 0;
36 int debug = 0;
37
38 int
39 main(int argc, char *argv[]) {
40         int fd;
41
42         set_progname(argv[0]);
43
44         setlocale(LC_ALL, "");
45         bindtextdomain(PACKAGE_NAME, LOCALEDIR);
46         textdomain(PACKAGE_NAME);
47
48         if (argc == 2 && !strcmp(argv[1], "-V"))
49             print_version_and_exit();
50
51         if (argc > 1 && !strcmp(argv[1], "-v")) {
52                 verbose = 1;
53                 argc--;
54                 argv++;
55         }
56
57         fd = getfd(NULL);
58
59         if (argc >= 3 && !strcmp(argv[1], "-o")) {
60             saveoldmap(fd, argv[2]);
61             argc -= 2;
62             argv += 2;
63             if (argc == 1)
64               exit(0);
65         }
66                 
67         if (argc != 2) {
68                 fprintf(stderr, _("usage: %s [-v] [-o map.orig] map-file\n"),
69                         progname);
70                 exit(1);
71         }
72         loadnewmap(fd, argv[1]);
73         exit(0);
74 }
75 #endif
76
77 /*
78  * Read two-column file (index, value) with index in 0-255
79  * and value in 0-65535. Acceptable representations:
80  * decimal (nnn), octal (0nnn), hexadecimal (0xnnn), Unicode (U+xxxx),
81  * character ('x').
82  * In the character encoding, x may be a single byte binary value
83  * (but not space, tab, comma, #) or a single Unicode value coded
84  * as a UTF-8 sequence.
85  *
86  * Store values in ubuf[], and small values also in buf[].
87  * Set u to 1 in case a value above 255 or a U+ occurs.
88  * Set lineno to line number of first error.
89  */
90 static int
91 parsemap(FILE *fp, char *buf, unsigned short *ubuf, int *u, int *lineno) {
92         char buffer[256];
93         int in, on, ln, ret = 0;
94         char *p, *q;
95
96         ln = 0;
97         while (fgets(buffer,sizeof(buffer)-1,fp)) {
98                 ln++;
99                 if (!*u && strstr(buffer, "U+"))
100                         *u = 1;
101                 p = strtok(buffer," \t\n");
102                 if (p && *p != '#') {
103                         q = strtok(NULL," \t\n#");
104                         if (q) {
105                                 in = ctoi(p);
106                                 on = ctoi(q);
107                                 if (in >= 0 && in < 256 &&
108                                     on >= 0 && on < 65536) {
109                                         ubuf[in] = on;
110                                         if (on < 256)
111                                                 buf[in] = on;
112                                         else
113                                                 *u = 1;
114                                 } else {
115                                         if (!ret)
116                                                 *lineno = ln;
117                                         ret = -1;
118                                 }
119                         }
120                 }
121         }
122         return ret;
123 }
124
125 static int
126 readnewmapfromfile(attr_unused int fd, char *mfil, char *buf, unsigned short *ubuf) {
127         FILE *fp;
128         struct stat stbuf;
129         int u = 0;
130         int lineno = 0;
131
132         if ((fp = findfile(mfil, mapdirpath, mapsuffixes)) == NULL) {
133                 fprintf(stderr, _("mapscrn: cannot open map file _%s_\n"),
134                         mfil);
135                 exit(1);
136         }
137         if (stat(pathname, &stbuf)) {
138                 perror(pathname);
139                 fprintf(stderr, _("Cannot stat map file"));
140                 exit(1);
141         }
142         if (stbuf.st_size == E_TABSZ) {
143                 if (verbose)
144                         printf(_("Loading binary direct-to-font screen map "
145                                  "from file %s\n"),
146                                pathname);
147                 if (fread(buf,E_TABSZ,1,fp) != 1) {
148                         fprintf(stderr,
149                                 _("Error reading map from file `%s'\n"),
150                                 pathname);
151                         exit(1);
152                 }
153         } else if (stbuf.st_size == 2*E_TABSZ) {
154                 if (verbose)
155                         printf(_("Loading binary unicode screen map "
156                                  "from file %s\n"),
157                                pathname);
158                 if (fread(ubuf,2*E_TABSZ,1,fp) != 1) {
159                         fprintf(stderr,
160                                 _("Error reading map from file `%s'\n"),
161                                 pathname);
162                         exit(1);
163                 }
164                 u = 1;
165         } else  {
166                 if (verbose)
167                         printf(_("Loading symbolic screen map from file %s\n"),
168                                pathname);
169                 if (parsemap(fp,buf,ubuf,&u,&lineno)) {
170                         fprintf(stderr,
171                                 _("Error parsing symbolic map "
172                                   "from `%s', line %d\n"),
173                                 pathname, lineno);
174                         exit(1);
175                 }
176         }
177         fpclose(fp);
178         return u;
179 }
180
181 void
182 loadnewmap(int fd, char *mfil) {
183         unsigned short ubuf[E_TABSZ];
184         char buf[E_TABSZ];
185         int i, u;
186
187         /* default: trivial straight-to-font */
188         for (i=0; i<E_TABSZ; i++) {
189                 buf[i] = i;
190                 ubuf[i] = (0xf000 + i);
191         }
192
193         u = 0;
194         if (mfil)
195                 u = readnewmapfromfile(fd, mfil, buf, ubuf);
196
197         /* do we need to use loaduniscrnmap() ? */
198         if (u) {
199                 /* yes */
200                 if (loaduniscrnmap(fd, ubuf))
201                         exit(1);
202         } else {
203                 /* no */
204                 if (loadscrnmap(fd,buf))
205                         exit(1);
206         }
207 }
208
209 /*
210  * Read decimal, octal, hexadecimal, Unicode (U+xxxx) or character
211  * ('x', x a single byte or a utf8 sequence).
212  */
213 int
214 ctoi(char *s) {
215         int i;
216
217         if ((strncmp(s,"0x",2) == 0) && 
218             (strspn(s+2,"0123456789abcdefABCDEF") == strlen(s+2)))
219                 (void)sscanf(s+2,"%x",&i);
220
221         else if ((*s == '0') &&
222                  (strspn(s,"01234567") == strlen(s)))
223                 (void)sscanf(s,"%o",&i);
224
225         else if (strspn(s,"0123456789") == strlen(s)) 
226                 (void)sscanf(s,"%d",&i);
227
228         else if ((strncmp(s,"U+",2) == 0) && strlen(s) == 6 &&
229                  (strspn(s+2,"0123456789abcdefABCDEF") == 4))
230                 (void)sscanf(s+2,"%x",&i);
231
232         else if ((strlen(s) == 3) && (s[0] == '\'') && (s[2] == '\''))
233                 i=s[1];
234
235         else if (s[0] == '\'') {
236                 int err;
237                 char *s1 = s+1;
238
239                 i = from_utf8(&s1, 0, &err);
240                 if (err || s1[0] != '\'' || s1[1] != 0)
241                         return -1;
242         }
243
244         else return -1;
245
246         return i;
247 }
248
249 void
250 saveoldmap(int fd, char *omfil) {
251         FILE *fp;
252         char buf[E_TABSZ];
253         unsigned short ubuf[E_TABSZ];
254         int i, havemap, haveumap;
255
256         if ((fp = fopen(omfil, "w")) == NULL) {
257                 perror(omfil);
258                 exit(1);
259         }
260         havemap = haveumap = 1;
261         if (getscrnmap(fd,buf))
262                 havemap = 0;
263         if (getuniscrnmap(fd,ubuf))
264                 haveumap = 0;
265         if (havemap && haveumap) {
266                 for (i = 0; i < E_TABSZ; i++) {
267                         if ((ubuf[i] & ~0xff) != 0xf000) {
268                                 havemap = 0;
269                                 break;
270                         }
271                 }
272         }
273         if (havemap) {
274                 if (fwrite(buf,sizeof(buf),1,fp) != 1) {
275                         fprintf(stderr, _("Error writing map to file\n"));
276                         exit(1);
277                 }
278         } else if (haveumap) {
279                 if (fwrite(ubuf,sizeof(ubuf),1,fp) != 1) {
280                         fprintf(stderr, _("Error writing map to file\n"));
281                         exit(1);
282                 }
283         } else {
284                 fprintf(stderr, _("Cannot read console map\n"));
285                 exit(1);
286         }
287         fclose(fp);
288
289         if (verbose)
290                 printf(_("Saved screen map in `%s'\n"), omfil);
291 }