2 /* Functions that emulate UNIX catgets */
\r
4 /* Copyright (C) 1999,2000,2001 Jim Hall <jhall@freedos.org> */
\r
7 This library is free software; you can redistribute it and/or
\r
8 modify it under the terms of the GNU Lesser General Public
\r
9 License as published by the Free Software Foundation; either
\r
10 version 2.1 of the License, or (at your option) any later version.
\r
12 This library is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
15 Lesser General Public License for more details.
\r
17 You should have received a copy of the GNU Lesser General Public
\r
18 License along with this library; if not, write to the Free Software
\r
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
22 #include <stdio.h> /* sprintf */
\r
23 #include <stdlib.h> /* getenv */
\r
24 #include <string.h> /* strchr */
\r
25 #include <sys/stat.h>
\r
29 #include "src/lib/nyan/kitten.h"
\r
35 struct db_list *next;
\r
40 typedef struct db_list db_t;
\r
42 db_t *db_insert (char *key, char *value);
\r
43 db_t *db_fetch (char *key);
\r
46 /* External functions */
\r
48 int get_line (int file, char *buffer, int size);
\r
51 /* Local prototypes */
\r
53 int catread (char *catfile); /* Reads a catfile into the hash */
\r
54 char *processEscChars(char *line); /* Converts c escape sequences to chars */
\r
58 nl_catd _kitten_catalog = 0; /* _kitten_catalog descriptor, either 0 or 1 */
\r
62 #if defined(__SMALL__) /* it's not very portable ;) */
\r
65 /* assert we are running in small model */
\r
66 /* else pointer below has to be done correctly */
\r
67 char verify_small_pointers[sizeof(void*) == 2 ? 1 : -1];
\r
70 int dos_open(char *filename, int mode);
\r
71 #define open(filename,mode) dos_open(filename,mode)
\r
73 int dos_read(int file, void *ptr, unsigned count);
\r
74 #define read(file, ptr, count) dos_read(file,ptr,count)
\r
76 void dos_close(int file);
\r
77 #define close(file) dos_close(file)
\r
81 #pragma aux dos_open = \
\r
87 parm [dx] [ax] value [ax];
\r
89 #pragma aux dos_read = \
\r
95 parm [bx] [dx] [cx] value [ax];
\r
97 #pragma aux dos_close = \
\r
104 int dos_open(char *filename, int mode)
\r
108 if (mode); /* mode ignored - readonly supported */
\r
111 r.h.al = 0; /* read mode only supoported now !! */
\r
112 r.x.dx = (unsigned)filename;
\r
120 int dos_read(int file, void *ptr, unsigned count)
\r
127 r.x.dx = (unsigned)ptr;
\r
135 void dos_close(int file)
\r
152 pascal kittengets(int set_number, int message_number, char *message)
\r
154 /* get message from a message _kitten_catalog */
\r
156 /* 'message' should really be const, but not when it is returned */
\r
158 /* On success, catgets() returns a pointer to an internal buffer
\r
159 area containing the null-terminated message string. On failure,
\r
160 catgets() returns the value 'message'. */
\r
166 /* fetch the message that goes with the set/message number */
\r
168 sprintf (key, "%d.%d", set_number, message_number);
\r
169 ptr = db_fetch (key);
\r
171 /* printf("\ncatgets %s\n",message); */
\r
175 /* printf("------> %s\n",ptr->value); */
\r
177 return (ptr->value);
\r
186 kittenopen(char *name)
\r
188 /* catopen() returns a message _kitten_catalog descriptor of type nl_catd on
\r
189 success. On failure, it returns -1. */
\r
191 /* 'flag' is completely ignored here. */
\r
193 char catfile[256]; /* full path to the msg _kitten_catalog */
\r
194 char *nlsptr; /* ptr to NLSPATH */
\r
195 char *lang; /* ptr to LANG */
\r
199 /* Open the _kitten_catalog file */
\r
201 /* The value of `_kitten_catalog' will be set based on catread */
\r
203 if (_kitten_catalog)
\r
205 /* Already one open */
\r
207 printf("cat already open\n");
\r
211 /* If the message _kitten_catalog file name contains a directory separator,
\r
212 assume that this is a real path to the _kitten_catalog file. Note that
\r
213 catread will return a true or false value based on its ability
\r
214 to read the catfile. */
\r
216 if (strchr (name, '\\'))
\r
218 /* first approximation: 'name' is a filename */
\r
220 printf("found \\\n");
\r
222 _kitten_catalog = catread (name);
\r
223 return (_kitten_catalog);
\r
226 /* If the message _kitten_catalog file name does not contain a directory
\r
227 separator, then we need to try to locate the message _kitten_catalog on
\r
228 our own. We will use several methods to find it. */
\r
230 /* We will need the value of LANG, and may need a 2-letter abbrev of
\r
231 LANG later on, so get it now. */
\r
233 lang = getenv ("LANG");
\r
237 /* printf("no lang= found\n"); */
\r
239 /* Return failure - we won't be able to locate the cat file */
\r
244 /* step through NLSPATH */
\r
246 nlsptr = getenv ("NLSPATH");
\r
249 if (nlsptr == NULL)
\r
251 /* printf("no NLSPATH= found\n"); */
\r
253 /* Return failure - we won't be able to locate the cat file */
\r
257 /* printf("nlsptr:%s\n",nlsptr); */
\r
261 char *tok = strchr(nlsptr, ';');
\r
265 if (tok == NULL) tok = nlsptr + strlen(nlsptr);
\r
267 /* Try to find the _kitten_catalog file in each path from NLSPATH */
\r
269 /* Rule #1: %NLSPATH%\%LANG%\cat */
\r
271 memcpy(catfile,nlsptr,toklen);
\r
272 sprintf(catfile+toklen,"\\%s\\%s",lang,name);
\r
274 _kitten_catalog = catread (catfile);
\r
275 if (_kitten_catalog)
\r
277 return (_kitten_catalog);
\r
280 /* Rule #2: %NLSPATH%\cat.%LANG% */
\r
282 sprintf(catfile+toklen,"\\%s.%s",name, lang);
\r
284 _kitten_catalog = catread (catfile);
\r
286 if (_kitten_catalog)
\r
288 return (_kitten_catalog);
\r
291 /* Rule #3: if LANG looks to be in format "en-UK" then
\r
292 %NLSPATH%\cat.EN */
\r
294 if (lang[2] == '-')
\r
297 sprintf(catfile+toklen,"\\%s.%s",name,lang);
\r
300 _kitten_catalog = catread (catfile);
\r
301 if (_kitten_catalog)
\r
303 return (_kitten_catalog);
\r
307 /* Grab next tok for the next while iteration */
\r
309 if (*nlsptr) nlsptr++;
\r
313 /* We could not find it. Return failure. */
\r
319 catread (char *catfile)
\r
321 int file; /* pointer to the catfile */
\r
322 char *key; /* part of key-value for hash */
\r
323 char *value; /* part of key-value for hash */
\r
324 char inBuffer[256]; /* the string read from the file */
\r
326 /* Open the catfile for reading */
\r
328 /*printf("catread %s\n",catfile); */
\r
330 file = open (catfile, O_RDONLY | O_TEXT);
\r
333 /* Cannot open the file. Return failure */
\r
334 /* printf("catread: cant read %s\n",catfile); */
\r
338 /*printf("catread %s success\n",catfile);*/
\r
340 /* Read the file into memory */
\r
342 while (get_line (file, inBuffer, sizeof(inBuffer)))
\r
344 /* Break into parts. Entries should be of the form:
\r
345 "1.2:This is a message" */
\r
347 /* A line that starts with '#' is considered a comment, and will
\r
348 be thrown away without reading it. */
\r
350 if (inBuffer[0] == '#') /* comment */
\r
353 if ((key = strchr (inBuffer, ':')) != NULL)
\r
357 value = processEscChars(key+1);
\r
359 db_insert (inBuffer, value);
\r
366 /* Return success */
\r
374 /* close a message _kitten_catalog */
\r
376 _kitten_catalog = 0;
\r
382 * Process strings, converting \n, \t, \v, \b, \r, \f, \\, \ddd, \xdd and \x0dd
\r
383 * to actual chars. (Note: \x is an extension to support hexadecimal)
\r
384 * This method is used to allow the message _kitten_catalog to use c escape sequences.
\r
385 * Modifies the line in-place (always same size or shorter).
\r
386 * Returns a pointer to input string.
\r
389 int mystrtoul(char *src, int base, int size, int *error)
\r
395 for (; size > 0; size--)
\r
400 if (ch >= '0' && ch <= '9') digit = ch - '0';
\r
401 else if (ch >= 'A' && ch <= 'Z') digit = ch - 'A' + 10;
\r
402 else if (ch >= 'a' && ch <= 'z') digit = ch - 'a' + 10;
\r
413 ret = ret * base + digit;
\r
422 char *processEscChars(char *line)
\r
424 register char *src = line, *dst = line;
\r
426 /* used when converting \xdd and \ddd (hex or octal) characters */
\r
429 if (line == NULL) return NULL;
\r
431 /* cycle through copying characters, except when a \ is encountered. */
\r
432 for ( ; *src != '\0'; src++, dst++)
\r
438 src++; /* point to char following slash */
\r
441 case '\\': /* a single slash */
\r
444 case 'n': /* a newline (linefeed) */
\r
447 case 'r': /* a carriage return */
\r
450 case 't': /* a horizontal tab */
\r
453 case 'v': /* a vertical tab */
\r
456 case 'b': /* a backspace */
\r
459 case 'a': /* alert */
\r
462 case 'f': /* formfeed */
\r
465 case 'x': /* extension supporting hex numbers \xdd or \x0dd */
\r
468 ch = mystrtoul(src+1,16,2, &error); /* get value */
\r
469 if (!error) /* store character */
\r
473 else /* error so just store x (loose slash) */
\r
480 default: /* just store letter (loose slash) or handle octal */
\r
484 ch = mystrtoul(src,8,3, &error); /* get value */
\r
485 if (!error) /* store character */
\r
500 /* ensure '\0' terminated */
\r
509 get_line (int file, char *str, int size)
\r
513 /* now, read the string */
\r
515 for ( ; size > 0; )
\r
517 if (read(file,str,1) <= 0)
\r
538 /* Function prototypes */
\r
541 /* Global variables */
\r
543 static db_t *hashtab[1];
\r
549 /* db_fetch() - Query the hash and return a struct that contains the
\r
550 key and the pointer. The calling function should not look beyond
\r
558 for (db_ptr = hashtab[0]; db_ptr != NULL; db_ptr = db_ptr->next)
\r
560 if (strcmp (s, db_ptr->key) == 0)
\r
571 /* db_insert() - Inserts a key,value pair into the hash. If the key
\r
572 already exists in the hash, the new value is NOT inserted. */
\r
575 db_insert (char *key, char *value)
\r
579 if ((db_ptr = db_fetch (key)) == NULL)
\r
583 db_ptr = (db_t *) malloc (sizeof (*db_ptr));
\r
585 if (db_ptr == NULL || (db_ptr->key = strdup (key)) == NULL)
\r
590 /* insert the key,value into the hash. */
\r
592 db_ptr->next = hashtab[0];
\r
593 hashtab[0] = db_ptr;
\r
598 /* already there */
\r
600 free ((void *) db_ptr->value);
\r
603 if ((db_ptr ->value = strdup (value)) == NULL)
\r
615 #endif /* NOCATS */
\r