From 0c365cfb9ba8d4576613889e6f26b297cc35ac8d Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 17 Sep 2001 01:55:23 +0000 Subject: [PATCH] Finished the proplist code. It's working now, but function names will change for better naming. --- WINGs/WINGs/WUtil.h | 4 + WINGs/proplist.c | 576 ++++++++++++++++++++++++++++++++++++++++++++++++++-- WINGs/wconfig.h | 6 + src/dialog.c | 3 +- 4 files changed, 575 insertions(+), 14 deletions(-) diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h index e2223ad7..c5dc22cd 100644 --- a/WINGs/WINGs/WUtil.h +++ b/WINGs/WINGs/WUtil.h @@ -809,6 +809,10 @@ WMPropList* WMPLShallowCopy(WMPropList *plist); WMPropList* WMPLDuplicate(WMPropList *plist); +WMPropList* WMPLGetWithDescription(char *desc); + +WMPropList* WMPLReadFromFile(char *file); + /*......................................................................*/ WMUserDefaults* WMGetStandardUserDefaults(void); diff --git a/WINGs/proplist.c b/WINGs/proplist.c index c65e6c35..754473af 100644 --- a/WINGs/proplist.c +++ b/WINGs/proplist.c @@ -36,9 +36,27 @@ typedef struct W_PropList { } W_PropList; +typedef struct PLData { + char *ptr; + int pos; + char *filename; + int lineNumber; +} PLData; + + +typedef struct StringBuffer { + char *str; + int size; +} StringBuffer; static unsigned hashPropList(WMPropList *plist); +static WMPropList* getPLString(PLData *pldata); +static WMPropList* getPLQString(PLData *pldata); +static WMPropList* getPLData(PLData *pldata); +static WMPropList* getPLArray(PLData *pldata); +static WMPropList* getPLDictionary(PLData *pldata); +static WMPropList* getPropList(PLData *pldata); @@ -60,6 +78,41 @@ static Bool caseSensitive = True; +#define BUFFERSIZE 8192 +#define BUFFERSIZE_INCREMENT 1024 + + +#if 0 +# define DPUT(s) puts(s) +#else +# define DPUT(s) +#endif + +#define COMPLAIN(pld, msg) wwarning(_("syntax error in %s %s, line %i: %s"),\ + (pld)->filename ? "file" : "PropList",\ + (pld)->filename ? (pld)->filename : "description",\ + (pld)->lineNumber, msg) + +#define ISSTRINGABLE(c) (isalnum(c) || (c)=='.' || (c)=='_' || (c)=='/' \ + || (c)=='+') + +#define CHECK_BUFFER_SIZE(buf, ptr) \ + if ((ptr) >= (buf).size-1) {\ + (buf).size += BUFFERSIZE_INCREMENT;\ + (buf).str = wrealloc((buf).str, (buf).size);\ + } + + +#define inrange(ch, min, max) ((ch)>=(min) && (ch)<=(max)) +#define noquote(ch) (inrange(ch, 'a', 'z') || inrange(ch, 'A', 'Z') || inrange(ch, '0', '9') || ((ch)=='_') || ((ch)=='.') || ((ch)=='$')) +#define charesc(ch) (inrange(ch, 0x07, 0x0c) || ((ch)=='"') || ((ch)=='\\')) +#define numesc(ch) (((ch)<=0x06) || inrange(ch, 0x0d, 0x1f) || ((ch)>0x7e)) +#define ishexdigit(ch) (inrange(ch, 'a', 'f') || inrange(ch, 'A', 'F') || inrange(ch, '0', '9')) +#define char2num(ch) (inrange(ch,'0','9') ? ((ch)-'0') : (inrange(ch,'a','f') ? ((ch)-0x57) : ((ch)-0x37))) +#define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57)) + + + #define MaxHashLength 64 static unsigned @@ -187,8 +240,6 @@ releasePropListByCount(WMPropList *plist, int count) } -#define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57)) - static char* dataDescription(WMPropList *plist) { @@ -233,11 +284,6 @@ stringDescription(WMPropList *plist) /* FIXME: make this work with unichars. */ -#define inrange(ch, min, max) ((ch)>=(min) && (ch)<=(max)) -#define noquote(ch) (inrange(ch, 'a', 'z') || inrange(ch, 'A', 'Z') || inrange(ch, '0', '9') || ((ch)=='_') || ((ch)=='.') || ((ch)=='$')) -#define charesc(ch) (inrange(ch, 0x07, 0x0c) || ((ch)=='"') || ((ch)=='\\')) -#define numesc(ch) (((ch)<=0x06) || inrange(ch, 0x0d, 0x1f) || ((ch)>0x7e)) - quote = 0; sPtr = (char*) str; len = 0; @@ -423,6 +469,423 @@ indentedDescription(WMPropList *plist, int level) } +static INLINE int +getChar(PLData *pldata) +{ + int c; + + c = pldata->ptr[pldata->pos]; + if (c==0) { + return 0; + } + + pldata->pos++; + + if (c == '\n') + pldata->lineNumber++; + + return c; +} + + +static INLINE int +getNonSpaceChar(PLData *pldata) +{ + int c; + + while (1) { + c = pldata->ptr[pldata->pos]; + if (c==0) { + break; + } + pldata->pos++; + if (c == '\n') { + pldata->lineNumber++; + } else if (!isspace(c)) { + break; + } + } + + return c; +} + + +static char* +unescapestr(char *src) +{ + char *dest = wmalloc(strlen(src)+1); + char *sPtr, *dPtr; + char ch; + + + for (sPtr=src, dPtr=dest; *sPtr; sPtr++, dPtr++) { + if(*sPtr != '\\') { + *dPtr = *sPtr; + } else { + ch = *(++sPtr); + if((ch>='0') && (ch<='3')) { + /* assume next 2 chars are octal too */ + *dPtr = ((ch & 07) << 6); + *dPtr |= ((*(++sPtr)&07)<<3); + *dPtr |= *(++sPtr)&07; + } else { + switch(ch) { + case 'a' : *dPtr = '\a'; break; + case 'b' : *dPtr = '\b'; break; + case 't' : *dPtr = '\t'; break; + case 'r' : *dPtr = '\r'; break; + case 'n' : *dPtr = '\n'; break; + case 'v' : *dPtr = '\v'; break; + case 'f' : *dPtr = '\f'; break; + default : *dPtr = *sPtr; + } + } + } + } + + *dPtr = 0; + + return dest; +} + + +static WMPropList* +getPLString(PLData *pldata) +{ + WMPropList *plist; + StringBuffer sBuf; + int ptr = 0; + int c; + + sBuf.str = wmalloc(BUFFERSIZE); + sBuf.size = BUFFERSIZE; + + while (1) { + c = getChar(pldata); + if (ISSTRINGABLE(c)) { + CHECK_BUFFER_SIZE(sBuf, ptr); + sBuf.str[ptr++] = c; + } else { + if (c != 0) { + pldata->pos--; + } + break; + } + } + + sBuf.str[ptr] = 0; + + if (ptr == 0) { + plist = NULL; + } else { + char *tmp = unescapestr(sBuf.str); + plist = WMPLCreateString(tmp); + wfree(tmp); + } + + wfree(sBuf.str); + + return plist; +} + + +static WMPropList* +getPLQString(PLData *pldata) +{ + WMPropList *plist; + int ptr = 0, escaping = 0, ok = 1; + int c; + StringBuffer sBuf; + + sBuf.str = wmalloc(BUFFERSIZE); + sBuf.size = BUFFERSIZE; + + while (1) { + c = getChar(pldata); + if (!escaping) { + if (c == '\\') { + escaping = 1; + continue; + } else if (c == '"') { + break; + } + } else { + CHECK_BUFFER_SIZE(sBuf, ptr); + sBuf.str[ptr++] = '\\'; + escaping = 0; + } + + if (c == 0) { + COMPLAIN(pldata, _("unterminated PropList string")); + ok = 0; + break; + } else { + CHECK_BUFFER_SIZE(sBuf, ptr); + sBuf.str[ptr++] = c; + } + } + + sBuf.str[ptr] = 0; + + if (!ok) { + plist = NULL; + } else { + char *tmp = unescapestr(sBuf.str); + plist = WMPLCreateString(tmp); + wfree(tmp); + } + + wfree(sBuf.str); + + return plist; +} + + +static WMPropList* +getPLData(PLData *pldata) +{ + int ok = 1; + int len = 0; + int c1, c2; + unsigned char buf[BUFFERSIZE], byte; + WMPropList *plist; + WMData *data; + + data = WMCreateDataWithCapacity(0); + + while (1) { + c1 = getNonSpaceChar(pldata); + if (c1 == 0) { + COMPLAIN(pldata, _("unterminated PropList data")); + ok = 0; + break; + } else if (c1=='>') { + break; + } else if (ishexdigit(c1)) { + c2 = getNonSpaceChar(pldata); + if (c2==0 || c2=='>') { + COMPLAIN(pldata, _("unterminated PropList data (missing hexdigit)")); + ok = 0; + break; + } else if (ishexdigit(c2)) { + byte = char2num(c1) << 4; + byte |= char2num(c2); + buf[len++] = byte; + if (len == sizeof(buf)) { + WMAppendDataBytes(data, buf, len); + len = 0; + } + } else { + COMPLAIN(pldata, _("non hexdigit character in PropList data")); + ok = 0; + break; + } + } + } + + if (!ok) { + WMReleaseData(data); + return NULL; + } + + if (len > 0) + WMAppendDataBytes(data, buf, len); + + plist = WMPLCreateData(data); + WMReleaseData(data); + + return plist; +} + + +static WMPropList* +getPLArray(PLData *pldata) +{ + Bool first = True; + int ok=1; + int c; + WMPropList *array, *obj; + + array = WMPLCreateArray(NULL); + + while (1) { + c = getNonSpaceChar(pldata); + if (c == 0) { + COMPLAIN(pldata, _("unterminated PropList array")); + ok = 0; + break; + } else if (c == ')') { + break; + } else if (c == ',') { + /* continue normally */ + } else if (!first) { + COMPLAIN(pldata, _("missing , or unterminated PropList array")); + ok = 0; + break; + } else { + pldata->pos--; + } + first = False; + + obj = getPropList(pldata); + if (!obj) { + COMPLAIN(pldata, _("could not get PropList array element")); + ok = 0; + break; + } + WMPLAddToArray(array, obj); + WMPLRelease(obj); + } + + if (!ok) { + WMPLRelease(array); + array = NULL; + } + + return array; +} + + +static WMPropList* +getPLDictionary(PLData *pldata) +{ + int ok = 1; + int c; + WMPropList *dict, *key, *value; + + dict = WMPLCreateDictionary(NULL, NULL); + + while (1) { + c = getNonSpaceChar(pldata); + if (c==0) { + COMPLAIN(pldata, _("unterminated PropList dictionary")); + ok = 0; + break; + } else if (c=='}') { + break; + } + + DPUT("getting PropList dictionary key"); + if (c == '<') { + key = getPLData(pldata); + } else if (c == '"') { + key = getPLQString(pldata); + } else if (ISSTRINGABLE(c)) { + pldata->pos--; + key = getPLString(pldata); + } else { + if (c == '=') { + COMPLAIN(pldata, _("missing PropList dictionary key")); + } else { + COMPLAIN(pldata, _("missing PropList dictionary entry key " + "or unterminated dictionary")); + } + ok = 0; + break; + } + + if (!key) { + COMPLAIN(pldata, _("error parsing PropList dictionary key")); + ok = 0; + break; + } + + c = getNonSpaceChar(pldata); + if (c != '=') { + WMPLRelease(key); + COMPLAIN(pldata, _("missing = in PropList dictionary entry")); + ok = 0; + break; + } + + DPUT("getting PropList dictionary entry value for key"); + value = getPropList(pldata); + if (!value) { + COMPLAIN(pldata, _("error parsing PropList dictionary entry value")); + WMPLRelease(key); + ok = 0; + break; + } + + c = getNonSpaceChar(pldata); + if (c != ';') { + COMPLAIN(pldata, _("missing ; in PropList dictionary entry")); + WMPLRelease(key); + WMPLRelease(value); + ok = 0; + break; + } + + WMPLPutInDictionary(dict, key, value); + WMPLRelease(key); + WMPLRelease(value); + } + + if (!ok) { + WMPLRelease(dict); + dict = NULL; + } + + return dict; +} + + +static WMPropList* +getPropList(PLData *pldata) +{ + WMPropList *plist; + int c; + + c = getNonSpaceChar(pldata); + + switch(c) { + case 0: + DPUT("End of PropList"); + plist = NULL; + break; + + case '{': + DPUT("Getting PropList dictionary"); + plist = getPLDictionary(pldata); + break; + + case '(': + DPUT("Getting PropList srrsy"); + plist = getPLArray(pldata); + break; + + case '<': + DPUT("Getting PropList data"); + plist = getPLData(pldata); + break; + + case '"': + DPUT("Getting PropList quoted string"); + plist = getPLQString(pldata); + break; + + default: + if (ISSTRINGABLE(c)) { + DPUT("Getting PropList string"); + pldata->pos--; + plist = getPLString(pldata); + } else { + COMPLAIN(pldata, _("was expecting a string, data, array or " + "dictionary. If it's a string, try enclosing " + "it with \".")); + if (c=='#' || c=='/') { + wwarning(_("Comments are not allowed inside WindowMaker owned" + " domain files.")); + } + plist = NULL; + } + break; + } + + return plist; +} + + void WMPLSetCaseSensitive(Bool useCase) { @@ -940,7 +1403,7 @@ Bool WMPLWriteToFile(WMPropList *plist, char *path, Bool atomically) { char *thePath=NULL; - char *description; + char *desc; FILE *theFile; if (atomically) { @@ -981,15 +1444,15 @@ WMPLWriteToFile(WMPropList *plist, char *path, Bool atomically) goto failure; } - description = indentedDescription(plist, 0); + desc = indentedDescription(plist, 0); - if (fprintf(theFile, "%s\n", description) != strlen(description)+1) { + if (fprintf(theFile, "%s\n", desc) != strlen(desc)+1) { wsyserror(_("writing to file: %s failed"), thePath); - wfree(description); + wfree(desc); goto failure; } - wfree(description); + wfree(desc); if (fclose(theFile) != 0) { wsyserror(_("fclose (%s) failed"), thePath); @@ -1110,5 +1573,94 @@ WMPLDuplicate(WMPropList *plist) } +WMPropList* +WMPLGetWithDescription(char *desc) +{ + WMPropList *plist = NULL; + PLData *pldata; + + pldata = (PLData*) wmalloc(sizeof(PLData)); + memset(pldata, 0, sizeof(PLData)); + pldata->ptr = desc; + pldata->lineNumber = 1; + + plist = getPropList(pldata); + + if (getNonSpaceChar(pldata)!=0 && plist) { + COMPLAIN(pldata, _("extra data after end of property list")); + /* + * We can't just ignore garbage after the end of the description + * (especially if the description was read from a file), because + * the "garbage" can be the real data and the real garbage is in + * fact in the beginning of the file (which is now inside plist) + */ + WMPLRelease(plist); + plist = NULL; + } + + wfree(pldata); + + return plist; +} + + +WMPropList* +WMPLReadFromFile(char *file) +{ + WMPropList *plist = NULL; + PLData *pldata; + FILE *f; + struct stat stbuf; + size_t length; + + f = fopen(file, "r"); + if (!f) { + wsyserror(_("could not open domain file %s for reading"), file); + return NULL; + } + + if (stat(file, &stbuf)==0) { + length = (size_t) stbuf.st_size; + } else { + wsyserror(_("could not get size for domain file %s"), file); + fclose(f); + return NULL; + } + + pldata = (PLData*) wmalloc(sizeof(PLData)); + memset(pldata, 0, sizeof(PLData)); + pldata->ptr = (char*) wmalloc(length+1); + pldata->filename = file; + pldata->lineNumber = 1; + + if (fread(pldata->ptr, length, 1, f) != 1) { + wsyserror(_("error reading from file %s"), file); + plist = NULL; + goto cleanup; + } + + pldata->ptr[length] = 0; + + plist = getPropList(pldata); + + if (getNonSpaceChar(pldata)!=0 && plist) { + COMPLAIN(pldata, _("extra data after end of property list")); + /* + * We can't just ignore garbage after the end of the description + * (especially if the description was read from a file), because + * the "garbage" can be the real data and the real garbage is in + * fact in the beginning of the file (which is now inside plist) + */ + WMPLRelease(plist); + plist = NULL; + } + +cleanup: + wfree(pldata->ptr); + wfree(pldata); + fclose(f); + + return plist; +} diff --git a/WINGs/wconfig.h b/WINGs/wconfig.h index 69a942d9..b4495600 100644 --- a/WINGs/wconfig.h +++ b/WINGs/wconfig.h @@ -12,6 +12,12 @@ # define _(text) (text) #endif +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +# define INLINE inline +#else +# define INLINE +#endif + #endif /* WINGS_CONFIG_H_ */ diff --git a/src/dialog.c b/src/dialog.c index 15fb715e..d4502692 100644 --- a/src/dialog.c +++ b/src/dialog.c @@ -1090,8 +1090,7 @@ handleLogoPush(XEvent *event, void *data) "WE GET SIGNAL", "SOMEBODY SET UP US THE BOMB", "ALL YOUR BASE ARE BELONG TO US!", - "Oh My God!!! Larry is back!", - "Hey! What happened with these messages?!?" + "Oh My God!!! Larry is back!" }; -- 2.11.4.GIT