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
27 #include "src/lib/nyan/kitten.h"
\r
33 struct db_list *next;
\r
38 typedef struct db_list db_t;
\r
40 db_t *db_insert (char *key, char *value);
\r
41 db_t *db_fetch (char *key);
\r
44 /* External functions */
\r
46 int get_line (int file, char *buffer, int size);
\r
49 /* Local prototypes */
\r
51 int catread (char *catfile); /* Reads a catfile into the hash */
\r
52 char *processEscChars(char *line); /* Converts c escape sequences to chars */
\r
56 nl_catd _kitten_catalog = 0; /* _kitten_catalog descriptor, either 0 or 1 */
\r
60 #if defined(__SMALL__) /* it's not very portable ;) */
\r
63 /* assert we are running in small model */
\r
64 /* else pointer below has to be done correctly */
\r
65 char verify_small_pointers[sizeof(void*) == 2 ? 1 : -1];
\r
68 int dos_open(char *filename, int mode);
\r
69 #define open(filename,mode) dos_open(filename,mode)
\r
71 int dos_read(int file, void *ptr, unsigned count);
\r
72 #define read(file, ptr, count) dos_read(file,ptr,count)
\r
74 void dos_close(int file);
\r
75 #define close(file) dos_close(file)
\r
79 #pragma aux dos_open = \
\r
85 parm [dx] [ax] value [ax];
\r
87 #pragma aux dos_read = \
\r
93 parm [bx] [dx] [cx] value [ax];
\r
95 #pragma aux dos_close = \
\r
102 int dos_open(char *filename, int mode)
\r
106 if (mode); /* mode ignored - readonly supported */
\r
109 r.h.al = 0; /* read mode only supoported now !! */
\r
110 r.x.dx = (unsigned)filename;
\r
118 int dos_read(int file, void *ptr, unsigned count)
\r
125 r.x.dx = (unsigned)ptr;
\r
133 void dos_close(int file)
\r
150 pascal kittengets(int set_number, int message_number, char *message)
\r
152 /* get message from a message _kitten_catalog */
\r
154 /* 'message' should really be const, but not when it is returned */
\r
156 /* On success, catgets() returns a pointer to an internal buffer
\r
157 area containing the null-terminated message string. On failure,
\r
158 catgets() returns the value 'message'. */
\r
164 /* fetch the message that goes with the set/message number */
\r
166 sprintf (key, "%d.%d", set_number, message_number);
\r
167 ptr = db_fetch (key);
\r
169 /* printf("\ncatgets %s\n",message); */
\r
173 /* printf("------> %s\n",ptr->value); */
\r
175 return (ptr->value);
\r
184 kittenopen(char *name)
\r
186 /* catopen() returns a message _kitten_catalog descriptor of type nl_catd on
\r
187 success. On failure, it returns -1. */
\r
189 /* 'flag' is completely ignored here. */
\r
191 char catfile[256]; /* full path to the msg _kitten_catalog */
\r
192 char *nlsptr; /* ptr to NLSPATH */
\r
193 char *lang; /* ptr to LANG */
\r
197 /* Open the _kitten_catalog file */
\r
199 /* The value of `_kitten_catalog' will be set based on catread */
\r
201 if (_kitten_catalog)
\r
203 /* Already one open */
\r
205 printf("cat already open\n");
\r
209 /* If the message _kitten_catalog file name contains a directory separator,
\r
210 assume that this is a real path to the _kitten_catalog file. Note that
\r
211 catread will return a true or false value based on its ability
\r
212 to read the catfile. */
\r
214 if (strchr (name, '\\'))
\r
216 /* first approximation: 'name' is a filename */
\r
218 printf("found \\\n");
\r
220 _kitten_catalog = catread (name);
\r
221 return (_kitten_catalog);
\r
224 /* If the message _kitten_catalog file name does not contain a directory
\r
225 separator, then we need to try to locate the message _kitten_catalog on
\r
226 our own. We will use several methods to find it. */
\r
228 /* We will need the value of LANG, and may need a 2-letter abbrev of
\r
229 LANG later on, so get it now. */
\r
231 lang = getenv ("LANG");
\r
235 /* printf("no lang= found\n"); */
\r
237 /* Return failure - we won't be able to locate the cat file */
\r
242 /* step through NLSPATH */
\r
244 nlsptr = getenv ("NLSPATH");
\r
247 if (nlsptr == NULL)
\r
249 /* printf("no NLSPATH= found\n"); */
\r
251 /* Return failure - we won't be able to locate the cat file */
\r
255 /* printf("nlsptr:%s\n",nlsptr); */
\r
259 char *tok = strchr(nlsptr, ';');
\r
263 if (tok == NULL) tok = nlsptr + strlen(nlsptr);
\r
265 /* Try to find the _kitten_catalog file in each path from NLSPATH */
\r
267 /* Rule #1: %NLSPATH%\%LANG%\cat */
\r
269 memcpy(catfile,nlsptr,toklen);
\r
270 sprintf(catfile+toklen,"\\%s\\%s",lang,name);
\r
272 _kitten_catalog = catread (catfile);
\r
273 if (_kitten_catalog)
\r
275 return (_kitten_catalog);
\r
278 /* Rule #2: %NLSPATH%\cat.%LANG% */
\r
280 sprintf(catfile+toklen,"\\%s.%s",name, lang);
\r
282 _kitten_catalog = catread (catfile);
\r
284 if (_kitten_catalog)
\r
286 return (_kitten_catalog);
\r
289 /* Rule #3: if LANG looks to be in format "en-UK" then
\r
290 %NLSPATH%\cat.EN */
\r
292 if (lang[2] == '-')
\r
295 sprintf(catfile+toklen,"\\%s.%s",name,lang);
\r
298 _kitten_catalog = catread (catfile);
\r
299 if (_kitten_catalog)
\r
301 return (_kitten_catalog);
\r
305 /* Grab next tok for the next while iteration */
\r
307 if (*nlsptr) nlsptr++;
\r
311 /* We could not find it. Return failure. */
\r
317 catread (char *catfile)
\r
319 int file; /* pointer to the catfile */
\r
320 char *key; /* part of key-value for hash */
\r
321 char *value; /* part of key-value for hash */
\r
322 char inBuffer[256]; /* the string read from the file */
\r
324 /* Open the catfile for reading */
\r
326 /*printf("catread %s\n",catfile); */
\r
328 file = open (catfile, O_RDONLY | O_TEXT);
\r
331 /* Cannot open the file. Return failure */
\r
332 /* printf("catread: cant read %s\n",catfile); */
\r
336 /*printf("catread %s success\n",catfile);*/
\r
338 /* Read the file into memory */
\r
340 while (get_line (file, inBuffer, sizeof(inBuffer)))
\r
342 /* Break into parts. Entries should be of the form:
\r
343 "1.2:This is a message" */
\r
345 /* A line that starts with '#' is considered a comment, and will
\r
346 be thrown away without reading it. */
\r
348 if (inBuffer[0] == '#') /* comment */
\r
351 if ((key = strchr (inBuffer, ':')) != NULL)
\r
355 value = processEscChars(key+1);
\r
357 db_insert (inBuffer, value);
\r
364 /* Return success */
\r
372 /* close a message _kitten_catalog */
\r
374 _kitten_catalog = 0;
\r
380 * Process strings, converting \n, \t, \v, \b, \r, \f, \\, \ddd, \xdd and \x0dd
\r
381 * to actual chars. (Note: \x is an extension to support hexadecimal)
\r
382 * This method is used to allow the message _kitten_catalog to use c escape sequences.
\r
383 * Modifies the line in-place (always same size or shorter).
\r
384 * Returns a pointer to input string.
\r
387 int mystrtoul(char *src, int base, int size, int *error)
\r
393 for (; size > 0; size--)
\r
398 if (ch >= '0' && ch <= '9') digit = ch - '0';
\r
399 else if (ch >= 'A' && ch <= 'Z') digit = ch - 'A' + 10;
\r
400 else if (ch >= 'a' && ch <= 'z') digit = ch - 'a' + 10;
\r
411 ret = ret * base + digit;
\r
420 char *processEscChars(char *line)
\r
422 register char *src = line, *dst = line;
\r
424 /* used when converting \xdd and \ddd (hex or octal) characters */
\r
427 if (line == NULL) return NULL;
\r
429 /* cycle through copying characters, except when a \ is encountered. */
\r
430 for ( ; *src != '\0'; src++, dst++)
\r
436 src++; /* point to char following slash */
\r
439 case '\\': /* a single slash */
\r
442 case 'n': /* a newline (linefeed) */
\r
445 case 'r': /* a carriage return */
\r
448 case 't': /* a horizontal tab */
\r
451 case 'v': /* a vertical tab */
\r
454 case 'b': /* a backspace */
\r
457 case 'a': /* alert */
\r
460 case 'f': /* formfeed */
\r
463 case 'x': /* extension supporting hex numbers \xdd or \x0dd */
\r
466 ch = mystrtoul(src+1,16,2, &error); /* get value */
\r
467 if (!error) /* store character */
\r
471 else /* error so just store x (loose slash) */
\r
478 default: /* just store letter (loose slash) or handle octal */
\r
482 ch = mystrtoul(src,8,3, &error); /* get value */
\r
483 if (!error) /* store character */
\r
498 /* ensure '\0' terminated */
\r
507 get_line (int file, char *str, int size)
\r
511 /* now, read the string */
\r
513 for ( ; size > 0; )
\r
515 if (read(file,str,1) <= 0)
\r
536 /* Function prototypes */
\r
539 /* Global variables */
\r
541 static db_t *hashtab[1];
\r
547 /* db_fetch() - Query the hash and return a struct that contains the
\r
548 key and the pointer. The calling function should not look beyond
\r
556 for (db_ptr = hashtab[0]; db_ptr != NULL; db_ptr = db_ptr->next)
\r
558 if (strcmp (s, db_ptr->key) == 0)
\r
569 /* db_insert() - Inserts a key,value pair into the hash. If the key
\r
570 already exists in the hash, the new value is NOT inserted. */
\r
573 db_insert (char *key, char *value)
\r
577 if ((db_ptr = db_fetch (key)) == NULL)
\r
581 db_ptr = (db_t *) malloc (sizeof (*db_ptr));
\r
583 if (db_ptr == NULL || (db_ptr->key = strdup (key)) == NULL)
\r
588 /* insert the key,value into the hash. */
\r
590 db_ptr->next = hashtab[0];
\r
591 hashtab[0] = db_ptr;
\r
596 /* already there */
\r
598 free ((void *) db_ptr->value);
\r
601 if ((db_ptr ->value = strdup (value)) == NULL)
\r
613 #endif /* NOCATS */
\r