2 * Copyright (C) 1989-95 GROUPE BULL
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 * Except as contained in this notice, the name of GROUPE BULL shall not be
22 * used in advertising or otherwise to promote the sale, use or other dealings
23 * in this Software without prior written authorization from GROUPE BULL.
26 /*****************************************************************************\
32 * Developed by Arnaud Le Hors *
33 \*****************************************************************************/
35 /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
39 /* Official version number */
40 static char *RCS_Version = "$XpmVersion: 3.4k $";
42 /* Internal version number */
43 static char *RCS_Id = "Id: xpm.shar,v 3.71 1998/03/19 19:47:14 lehors Exp $";
53 #define Getc(data, file) getc(file)
54 #define Ungetc(data, c, file) ungetc(c, file)
58 ParseComment(xpmData *data)
60 if (data->type == XPMBUFFER) {
62 register unsigned int n = 0;
69 /* skip the string beginning comment */
76 } while (c == *s2 && *s2 != '\0' && c);
79 /* this wasn't the beginning of a comment */
84 data->Comment[0] = *s;
90 while (*s != *s2 && c) {
92 if (n == XPMMAXCMTLEN - 1) { /* forget it */
99 data->CommentLength = n;
102 if (n == XPMMAXCMTLEN - 1) { /* forget it */
109 } while (c == *s2 && *s2 != '\0' && c);
111 /* this is the end of the comment */
118 FILE *file = data->stream.file;
120 register unsigned int n = 0, a;
127 /* skip the string beginning comment */
130 c = Getc(data, file);
134 } while (c == *s2 && *s2 != '\0' && c != EOF);
137 /* this wasn't the beginning of a comment */
138 /* put characters back in the order that we got them */
139 for (a = n; a > 0; a--, s--)
140 Ungetc(data, *s, file);
144 data->Comment[0] = *s;
150 while (*s != *s2 && c != EOF) {
151 c = Getc(data, file);
152 if (n == XPMMAXCMTLEN - 1) { /* forget it */
159 data->CommentLength = n;
161 c = Getc(data, file);
162 if (n == XPMMAXCMTLEN - 1) { /* forget it */
169 } while (c == *s2 && *s2 != '\0' && c != EOF);
171 /* this is the end of the comment */
173 Ungetc(data, *s, file);
181 * skip to the end of the current string and the beginning of the next one
184 xpmNextString(xpmData *data)
187 data->cptr = (data->stream.data)[++data->line];
188 else if (data->type == XPMBUFFER) {
191 /* get to the end of the current string */
193 while ((c = *data->cptr++) && c != data->Eos);
196 * then get to the beginning of the next string looking for possible
200 while ((c = *data->cptr++) && c != data->Bos)
201 if (data->Bcmt && c == data->Bcmt[0])
203 } else if (data->Bcmt) { /* XPM2 natural */
204 while ((c = *data->cptr++) == data->Bcmt[0])
210 FILE *file = data->stream.file;
212 /* get to the end of the current string */
214 while ((c = Getc(data, file)) != data->Eos && c != EOF);
217 * then get to the beginning of the next string looking for possible
221 while ((c = Getc(data, file)) != data->Bos && c != EOF)
222 if (data->Bcmt && c == data->Bcmt[0])
225 } else if (data->Bcmt) { /* XPM2 natural */
226 while ((c = Getc(data, file)) == data->Bcmt[0])
228 Ungetc(data, c, file);
236 * skip whitespace and return the following word
244 register unsigned int n = 0;
247 if (!data->type || data->type == XPMBUFFER) {
248 while (isspace(c = *data->cptr) && c != data->Eos)
254 } while (!isspace(c) && c != data->Eos && n < buflen);
258 FILE *file = data->stream.file;
260 while ((c = Getc(data, file)) != EOF && isspace(c) && c != data->Eos);
261 while (!isspace(c) && c != data->Eos && c != EOF && n < buflen) {
264 c = Getc(data, file);
266 Ungetc(data, c, file);
268 return (n); /* this returns bytes read + 1 */
272 * skip whitespace and compute the following unsigned int,
273 * returns 1 if one is found and 0 if not
278 unsigned int *ui_return)
283 l = xpmNextWord(data, buf, BUFSIZ);
284 return xpmatoui(buf, l, ui_return);
288 * return end of string - WARNING: malloc!
296 unsigned int i, n = 0;
298 char *p = NULL, *q, buf[BUFSIZ];
300 if (!data->type || data->type == XPMBUFFER) {
302 char *start = data->cptr;
303 while ((c = *data->cptr) && c != data->Eos)
305 n = data->cptr - start + 1;
306 p = (char *) XpmMalloc(n);
308 return (XpmNoMemory);
309 strncpy(p, start, n);
310 if (data->type) /* XPMBUFFER */
314 FILE *file = data->stream.file;
316 if ((c = Getc(data, file)) == EOF)
317 return (XpmFileInvalid);
321 p = (char *) XpmMalloc(1);
322 while (c != data->Eos && c != EOF) {
324 /* get to the end of the buffer */
325 /* malloc needed memory */
326 q = (char *) XpmRealloc(p, n + i);
329 return (XpmNoMemory);
333 /* and copy what we already have */
341 c = Getc(data, file);
345 return (XpmFileInvalid);
348 /* malloc needed memory */
349 q = (char *) XpmRealloc(p, n + i + 1);
352 return (XpmNoMemory);
356 /* and copy the buffer */
364 Ungetc(data, c, file);
372 * get the current comment line
381 else if (data->CommentLength != 0 && data->CommentLength < UINT_MAX - 1) {
382 if( (*cmt = (char *) XpmMalloc(data->CommentLength + 1)) == NULL)
384 strncpy(*cmt, data->Comment, data->CommentLength);
385 (*cmt)[data->CommentLength] = '\0';
386 data->CommentLength = 0;
392 xpmDataType xpmDataTypes[] =
394 {"", "!", "\n", '\0', '\n', "", "", "", ""}, /* Natural type */
395 {"C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n"},
396 {"Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n"},
397 {NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL}
404 xpmParseHeader(xpmData *data)
406 char buf[BUFSIZ+1] = {0};
412 data->Bcmt = data->Ecmt = NULL;
413 l = xpmNextWord(data, buf, BUFSIZ);
414 if (l == 7 && !strncmp("#define", buf, 7)) {
415 /* this maybe an XPM 1 file */
418 l = xpmNextWord(data, buf, BUFSIZ);
420 return (XpmFileInvalid);
422 ptr = strrchr(buf, '_');
423 if (!ptr || strncmp("_format", ptr, l - (ptr - buf)))
424 return XpmFileInvalid;
425 /* this is definitely an XPM 1 file */
427 n = 1; /* handle XPM1 as mainly XPM2 C */
431 * skip the first word, get the second one, and see if this is
434 l = xpmNextWord(data, buf, BUFSIZ);
435 if ((l == 3 && !strncmp("XPM", buf, 3)) ||
436 (l == 4 && !strncmp("XPM2", buf, 4))) {
438 n = 1; /* handle XPM as XPM2 C */
440 /* get the type key word */
441 l = xpmNextWord(data, buf, BUFSIZ);
444 * get infos about this type
446 while (xpmDataTypes[n].type
447 && strncmp(xpmDataTypes[n].type, buf, l))
452 /* nope this is not an XPM file */
453 return XpmFileInvalid;
455 if (xpmDataTypes[n].type) {
456 if (n == 0) { /* natural type */
457 data->Bcmt = xpmDataTypes[n].Bcmt;
458 data->Ecmt = xpmDataTypes[n].Ecmt;
459 xpmNextString(data); /* skip the end of the headerline */
460 data->Bos = xpmDataTypes[n].Bos;
461 data->Eos = xpmDataTypes[n].Eos;
463 data->Bcmt = xpmDataTypes[n].Bcmt;
464 data->Ecmt = xpmDataTypes[n].Ecmt;
465 if (!data->format) { /* XPM 2 or 3 */
466 data->Bos = xpmDataTypes[n].Bos;
468 /* get to the beginning of the first string */
470 data->Eos = xpmDataTypes[n].Eos;
471 } else /* XPM 1 skip end of line */
475 /* we don't know about that type of XPM file... */
476 return XpmFileInvalid;