/* * readdef.c * * Read DLL Binder definition files * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Dynamic Linking System (SDLS) * * SDLS 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. * * SDLS 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 SDLS. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "hashtable.h" #include "error.h" #include "readdef.h" #include "swiv.h" #include "swis.h" #define CHUNKSIZE 40 static char *readdef_token=0; static void addChar(char **buffer,int *length,int *size,char c) { char *p; if (*length==*size) { if (p=realloc(*buffer,*size+CHUNKSIZE),!p) error(NOMEM); *buffer=p; (*size)+=CHUNKSIZE; } (*buffer)[(*length)++]=c; } #define add(c) addChar(&readdef_token,&len,&size,(c)) int cistrcmp(const char *s1,const char *s2) { char c1; char c2; while (*s1 || *s2) { c1=tolower(*(s1++)); c2=tolower(*(s2++)); if (c1!=c2) return (c1-c2); } return (0); } enum { _xxx, _IDENT, _STRING, _BRA, _KET, _EQUAL, _CONST, _EOF }; static char readdef__ungot[2]; static int readdef__ungotc=0; #define GET(fp) (readdef__ungotc ? \ readdef__ungot[--readdef__ungotc] : \ getc(fp)) #define UNGET(c) ((void)((c)==EOF ? \ EOF : \ (readdef__ungot[readdef__ungotc++]=(c)))) static int readdef__getToken(FILE *fp) { int ch; int type=_xxx; int qu; int len=0; int size=0; if (readdef_token) free(readdef_token); readdef_token=0; while (!type) { /* --- Skip whitespace --- */ while (isspace(ch=GET(fp))) /* blank */; switch (ch) { case ';': case '|': case '#': while (ch=GET(fp),ch!='\n' && ch!=EOF) /* blank */; break; case '/': switch (ch=GET(fp)) { case '*': while (ch=GET(fp),ch!='*' || (ch=GET(fp),UNGET(ch),ch!='/')) /* blank */; (void)GET(fp); break; case '/': while (ch=GET(fp),ch!='\n' && ch!=EOF) /* blank */; break; default: UNGET(ch); add('/'); break; } break; case '{': type=_BRA; break; case '}': type=_KET; break; case '=': type=_EQUAL; break; case EOF: type=_EOF; break; case '\'': case '\"': qu=ch; while (ch=GET(fp),1) { if (ch==qu) { ch=GET(fp); if (ch!=qu) { UNGET(ch); break; } } if (ch==EOF) { error(QBFEOF,qu); break; } else if (ch=='\n') { error(QBFNL,qu); break; } add(ch); } add(0); type=_STRING; break; default: add(ch); while (ch=GET(fp),ch!=EOF && !isspace(ch)) add(ch); add(0); UNGET(ch); type=_IDENT; break; } } return (type); } static char *readdef__tokAsString(int type) { switch (type) { case _EOF: return (""); case _BRA: return ("{"); case _KET: return ("}"); case _EQUAL: return ("="); case _CONST: return (""); case _STRING: return (""); case _IDENT: return (readdef_token); } return (0); } static int readdef__getOrderedTable(FILE *fp,hashtable h) { int done=0; int tok; char *name; unsigned int ord; switch (tok=readdef__getToken(fp)) { case _BRA: break; default: error(JUNKNOBRA,readdef__tokAsString(tok)); return (1); break; } tok=readdef__getToken(fp); while (!done) { switch (tok) { case _IDENT: name=readdef_token; readdef_token=0; tok=readdef__getToken(fp); ord=0xFFFFFFFF; if (tok==_EQUAL) { tok=readdef__getToken(fp); if (tok==_IDENT) { sscanf(readdef_token,"%i",&ord); tok=readdef__getToken(fp); } } if (!hash_addWithOrd(h,name,ord)) { error(NOMEM); return (1); } free(name); break; case _KET: done=1; break; default: error(JUNKNOKET,readdef__tokAsString(tok)); return (1); } } return (0); } static int readdef__getTable(FILE *fp,hashtable h) { int done=0; int tok; switch (tok=readdef__getToken(fp)) { case _BRA: break; default: error(JUNKNOBRA,readdef__tokAsString(tok)); return (1); break; } while (!done) { switch (tok=readdef__getToken(fp)) { case _IDENT: if (!hash_add(h,readdef_token)) { error(NOMEM); return (1); } break; case _KET: done=1; break; default: error(JUNKNOKET,readdef__tokAsString(tok)); return (1); } } return (0); } static int readdef__getVersion(FILE *fp,int *v) { int tok; int minor; int major; char *dot; switch (tok=readdef__getToken(fp)) { case _IDENT: dot=strchr(readdef_token,'.'); if (!dot) { sscanf(readdef_token,"%i",&major); *v=major*100; } else { *dot=0; major=atoi(readdef_token); switch (strlen(dot+1)) { case 0: *v=major*100; break; case 1: minor=atoi(dot+1); *v=major*100+minor*10; break; case 2: minor=atoi(dot+1); *v=major*100+minor; break; default: error(BADVER,readdef__tokAsString(tok)); return (1); } } break; default: error(JUNKNOVER,readdef__tokAsString(tok)); return (1); } return (0); } static int readdef__getName(FILE *fp,char *name) { int tok; switch (tok=readdef__getToken(fp)) { case _IDENT: case _STRING: strcpy(name,readdef_token); break; default: error(JUNKNONAME,readdef__tokAsString(tok)); return (1); } return (0); } static int readdef__getCopyright(FILE *fp,char *name) { int tok; char timeBuff[5]; switch (tok=readdef__getToken(fp)) { case _STRING: timeBuff[0]=3; _swi(OS_Word,_inr(0,1),14,timeBuff); _swi(OS_ConvertDateAndTime,_inr(0,3),timeBuff,name,256,readdef_token); break; default: error(JUNKNOCRIGHT,readdef__tokAsString(tok)); return (1); } return (0); } static int readdef__getItem(FILE *fp,readdef_info *info) { int tok; switch (tok=readdef__getToken(fp)) { case _EOF: return (-1); break; case _IDENT: break; default: error(JUNKNOITEM,readdef__tokAsString(tok)); return (1); } if (!cistrcmp(readdef_token,"exports")) return (readdef__getOrderedTable(fp,info->sym)); else if (!cistrcmp(readdef_token,"extentry")) return (readdef__getTable(fp,info->vsym)); else if (!cistrcmp(readdef_token,"objects")) return (readdef__getTable(fp,info->obj)); else if (!cistrcmp(readdef_token,"version")) return (readdef__getVersion(fp,&info->version)); else if (!cistrcmp(readdef_token,"name")) return (readdef__getName(fp,info->name)); else if (!cistrcmp(readdef_token,"author")) return (readdef__getCopyright(fp,info->copyright)); else if (!cistrcmp(readdef_token,"NonAPCS")) { info->flags|=rdFlag_shortEntry; return (0); } else if (!cistrcmp(readdef_token,"OmitNames")) { info->flags|=rdFlag_noNames; return (0); } else { error(BADITEM,readdef_token); return (1); } } int readdef(char *file,readdef_info *info) { FILE *fp=fopen(file,"r"); if (!fp) { error(NOOPENIN,file); return(1); } info->version=-1; *info->name=0; *info->copyright=0; info->errored=0; info->flags=0; while (readdef__getItem(fp,info)!=-1) /* blank */; fclose(fp); return (0); }