/* * msgs.c * * Handling of messages files * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Steel library. * * Steel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Steel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Steel. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "os.h" #include "mem.h" #include "werr.h" #include "res.h" #include "msgs.h" /*----- Special types -----------------------------------------------------*/ typedef struct msgs__node { struct msgs__node *left; struct msgs__node *right; char tag[20]; char *message; } msgs__node; /*----- Variables ---------------------------------------------------------*/ #define msgs__HASHSIZE 64 static msgs__node *msgs__all[msgs__HASHSIZE]; /*----- Main code ---------------------------------------------------------*/ /* * int msgs__hash(char *p) * * Use * Hashes the string pointed to by p */ static int msgs__hash(char *p) { unsigned int h=0; unsigned int seed=0x46bc93d5; for (;*p && *p!=':';p++) { h=(h*(*p)) ^ seed ^ h; seed=seed*3141592621ul + 271828189; } return ((int)h & (msgs__HASHSIZE-1)); } /* * void msgs__add(msgs__node *t,msgs__node **p) * * Use * Adds node t to the tree with *p as its root */ static void msgs__add(msgs__node *t,msgs__node **p) { int s; if (*p) { s=strcmp(t->tag,(*p)->tag); if (s>0) msgs__add(t,&(*p)->right); else if (s<0) msgs__add(t,&(*p)->left); } else *p=t; } /* * int msgs__cmp(char *a,char *b) * * Use * Compares a tag-and-default a with a tag b. */ static int msgs__cmp(char *a,char *b) { for (;;) { if ((*a==':' || *a==0) && *b==0) return (0); else if (*a!=*b) return (*a-*b); a++; b++; } } /* * msgs__node *msgs__find(char *tag,msgs__node *t) * * Use * Finds the tag in the tree pointed to by t */ static msgs__node *msgs__find(char *tag,msgs__node *t) { int s; if (!t) return (0); s=msgs__cmp(tag,t->tag); if (s>0) return (msgs__find(tag,t->right)); else if (s<0) return (msgs__find(tag,t->left)); else return (t); } /* * void msgs__insert(msgs__node *t) * * Use * Inserts the given messages structure into the overall messages system. * * Parameters * msgs__node *t == pointer to a filled in messages structure to fit in. */ static void msgs__insert(msgs__node *t) { int i=msgs__hash(t->tag); t->left=t->right=0; msgs__add(t,msgs__all+i); } /* * void msgs_readfile(char *name) * * Use * Loads the messages file given by name into the messages area. */ void msgs_readfile(char *name) { FILE *fp=res_openfile(name,"r"); int c; enum { newline, comment, tag, newalt, message, endoffile } state=newline; msgs__node *t[10]; char *p=0; int len=0; int i; int alts=0; char msg[1024]; if (!fp) return; while (state!=endoffile) { c=getc(fp); switch (state) { case newline: if (c==';' || c=='|' || c=='#') state=comment; else if (c==EOF) state=endoffile; else if (!isspace(c)) { alts=0; t[alts]=mem_alloc(sizeof(msgs__node)); if (!t[alts]) { fclose(fp); werr(FALSE, msgs_lookup("msgsNEM:Not enough memory to read " "messages file '%s'"), name); return; } p=t[alts]->tag; *p++=c; state=tag; } break; case comment: if (c=='\n') state=newline; else if (c==EOF) state=endoffile; break; case newalt: if (c==EOF) { for (i=0;itag; *p++=c; state=tag; } break; case tag: if (c=='\n' || c=='/') { *p++=0; alts++; state=newalt; } else if (c==':') { *p++=0; alts++; len=0; p=msg; state=message; } else if (c==EOF) { for (i=0;i<=alts;i++) mem_free(t[i]); werr(FALSE, msgs_lookup("msgsEOF:Unexpected end of file in " "messages file '%s'"), name); state=endoffile; } else *p++=c; break; case message: if (c==EOF || c=='\n') { *p=0; p=mem_alloc(len+1); if (!p) { fclose(fp); for (i=0;imessage=p; msgs__insert(t[i]); } alts=0; state=(c==EOF ? endoffile : newline); } else { *p++=c; len++; } break; } } fclose(fp); } /* * void msgs_init(void) * * Use * Reads the messages file `Messages' into memory. */ void msgs_init(void) { msgs_readfile("Messages"); } /* * char *msgs_lookup(char *tag) * * Use * Searches the messages for one with a given tag. */ char *msgs_lookup(char *tag) { msgs__node *t=msgs__find(tag,msgs__all[msgs__hash(tag)]); char *p; if (t) return (t->message); p=tag; while (*p) { if (*p++==':') return (p); } return (tag); } /* * void msgs_delete(void) * * Use * Removes all messages from memory. */ static void msgs__delTree(msgs__node *t) { if (!t) return; msgs__delTree(t->left); msgs__delTree(t->right); mem_free(t); return; } void msgs_delete(void) { int i; for (i=0;i