PageRenderTime 36ms CodeModel.GetById 20ms app.highlight 13ms RepoModel.GetById 0ms app.codeStats 1ms

/src/data.c

#
C | 481 lines | 355 code | 35 blank | 91 comment | 165 complexity | e5988abe18451e480135a6b247be6c07 MD5 | raw file
  1/*
  2 * Copyright (C) 1989-95 GROUPE BULL
  3 *
  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:
 10 *
 11 * The above copyright notice and this permission notice shall be included in
 12 * all copies or substantial portions of the Software.
 13 *
 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.
 20 *
 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.
 24 */
 25
 26/*****************************************************************************\
 27* data.c:                                                                     *
 28*                                                                             *
 29*  XPM library                                                                *
 30*  IO utilities                                                               *
 31*                                                                             *
 32*  Developed by Arnaud Le Hors                                                *
 33\*****************************************************************************/
 34
 35/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
 36
 37#ifndef CXPMPROG
 38#if 0
 39/* Official version number */
 40static char *RCS_Version = "$XpmVersion: 3.4k $";
 41
 42/* Internal version number */
 43static char *RCS_Id = "Id: xpm.shar,v 3.71 1998/03/19 19:47:14 lehors Exp $";
 44#endif
 45#ifdef HAVE_CONFIG_H
 46#include <config.h>
 47#endif
 48#include "XpmI.h"
 49#endif
 50#include <ctype.h>
 51
 52#ifndef CXPMPROG
 53#define Getc(data, file) getc(file)
 54#define Ungetc(data, c, file) ungetc(c, file)
 55#endif
 56
 57static int
 58ParseComment(xpmData *data)
 59{
 60    if (data->type == XPMBUFFER) {
 61	register char c;
 62	register unsigned int n = 0;
 63	unsigned int notend;
 64	char *s;
 65	const char *s2;
 66
 67	s = data->Comment;
 68	*s = data->Bcmt[0];
 69
 70	/* skip the string beginning comment */
 71	s2 = data->Bcmt;
 72	do {
 73	    c = *data->cptr++;
 74	    *++s = c;
 75	    n++;
 76	    s2++;
 77	} while (c == *s2 && *s2 != '\0' && c);
 78
 79	if (*s2 != '\0') {
 80	    /* this wasn't the beginning of a comment */
 81	    data->cptr -= n;
 82	    return 0;
 83	}
 84	/* store comment */
 85	data->Comment[0] = *s;
 86	s = data->Comment;
 87	notend = 1;
 88	n = 0;
 89	while (notend) {
 90	    s2 = data->Ecmt;
 91	    while (*s != *s2 && c) {
 92		c = *data->cptr++;
 93		if (n == XPMMAXCMTLEN - 1)  { /* forget it */
 94		    s = data->Comment;
 95		    n = 0;
 96		}
 97		*++s = c;
 98		n++;
 99	    }
100	    data->CommentLength = n;
101	    do {
102		c = *data->cptr++;
103		if (n == XPMMAXCMTLEN - 1)  { /* forget it */
104		    s = data->Comment;
105		    n = 0;
106		}
107		*++s = c;
108		n++;
109		s2++;
110	    } while (c == *s2 && *s2 != '\0' && c);
111	    if (*s2 == '\0') {
112		/* this is the end of the comment */
113		notend = 0;
114		data->cptr--;
115	    }
116	}
117	return 0;
118    } else {
119	FILE *file = data->stream.file;
120	register int c;
121	register unsigned int n = 0, a;
122	unsigned int notend;
123	char *s;
124	const char *s2;
125
126	s = data->Comment;
127	*s = data->Bcmt[0];
128
129	/* skip the string beginning comment */
130	s2 = data->Bcmt;
131	do {
132	    c = Getc(data, file);
133	    *++s = c;
134	    n++;
135	    s2++;
136	} while (c == *s2 && *s2 != '\0' && c != EOF);
137
138	if (*s2 != '\0') {
139	    /* this wasn't the beginning of a comment */
140	    /* put characters back in the order that we got them */
141	    for (a = n; a > 0; a--, s--)
142		Ungetc(data, *s, file);
143	    return 0;
144	}
145	/* store comment */
146	data->Comment[0] = *s;
147	s = data->Comment;
148	notend = 1;
149	n = 0;
150	while (notend) {
151	    s2 = data->Ecmt;
152	    while (*s != *s2 && c != EOF) {
153		c = Getc(data, file);
154		if (n == XPMMAXCMTLEN - 1)  { /* forget it */
155		    s = data->Comment;
156		    n = 0;
157		}
158		*++s = c;
159		n++;
160	    }
161	    data->CommentLength = n;
162	    do {
163		c = Getc(data, file);
164		if (n == XPMMAXCMTLEN - 1)  { /* forget it */
165		    s = data->Comment;
166		    n = 0;
167		}
168		*++s = c;
169		n++;
170		s2++;
171	    } while (c == *s2 && *s2 != '\0' && c != EOF);
172	    if (*s2 == '\0') {
173		/* this is the end of the comment */
174		notend = 0;
175		Ungetc(data, *s, file);
176	    }
177	}
178	return 0;
179    }
180}
181
182/*
183 * skip to the end of the current string and the beginning of the next one
184 */
185int
186xpmNextString(xpmData *data)
187{
188    if (!data->type)
189	data->cptr = (data->stream.data)[++data->line];
190    else if (data->type == XPMBUFFER) {
191	register char c;
192
193	/* get to the end of the current string */
194	if (data->Eos)
195	    while ((c = *data->cptr++) && c != data->Eos);
196
197	/*
198	 * then get to the beginning of the next string looking for possible
199	 * comment
200	 */
201	if (data->Bos) {
202	    while ((c = *data->cptr++) && c != data->Bos)
203		if (data->Bcmt && c == data->Bcmt[0])
204		    ParseComment(data);
205	} else if (data->Bcmt) {	/* XPM2 natural */
206	    while ((c = *data->cptr++) == data->Bcmt[0])
207		ParseComment(data);
208	    data->cptr--;
209	}
210    } else {
211	register int c;
212	FILE *file = data->stream.file;
213
214	/* get to the end of the current string */
215	if (data->Eos)
216	    while ((c = Getc(data, file)) != data->Eos && c != EOF);
217
218	/*
219	 * then get to the beginning of the next string looking for possible
220	 * comment
221	 */
222	if (data->Bos) {
223	    while ((c = Getc(data, file)) != data->Bos && c != EOF)
224		if (data->Bcmt && c == data->Bcmt[0])
225		    ParseComment(data);
226
227	} else if (data->Bcmt) {	/* XPM2 natural */
228	    while ((c = Getc(data, file)) == data->Bcmt[0])
229		ParseComment(data);
230	    Ungetc(data, c, file);
231	}
232    }
233    return 0;
234}
235
236
237/*
238 * skip whitespace and return the following word
239 */
240unsigned int
241xpmNextWord(
242    xpmData		*data,
243    char		*buf,
244    unsigned int	 buflen)
245{
246    register unsigned int n = 0;
247    int c;
248
249    if (!data->type || data->type == XPMBUFFER) {
250	while (isspace(c = *data->cptr) && c != data->Eos)
251	    data->cptr++;
252	do {
253	    c = *data->cptr++;
254	    *buf++ = c;
255	    n++;
256	} while (!isspace(c) && c != data->Eos && n < buflen);
257	n--;
258	data->cptr--;
259    } else {
260	FILE *file = data->stream.file;
261
262	while ((c = Getc(data, file)) != EOF && isspace(c) && c != data->Eos);
263	while (!isspace(c) && c != data->Eos && c != EOF && n < buflen) {
264	    *buf++ = c;
265	    n++;
266	    c = Getc(data, file);
267	}
268	Ungetc(data, c, file);
269    }
270    return (n); /* this returns bytes read + 1 */
271}
272
273/*
274 * skip whitespace and compute the following unsigned int,
275 * returns 1 if one is found and 0 if not
276 */
277int
278xpmNextUI(
279    xpmData		*data,
280    unsigned int	*ui_return)
281{
282    char buf[BUFSIZ];
283    int l;
284
285    l = xpmNextWord(data, buf, BUFSIZ);
286    return xpmatoui(buf, l, ui_return);
287}
288
289/*
290 * return end of string - WARNING: malloc!
291 */
292int
293xpmGetString(
294    xpmData		 *data,
295    char		**sptr,
296    unsigned int	 *l)
297{
298    unsigned int i, n = 0;
299    int c;
300    char *p = NULL, *q, buf[BUFSIZ];
301
302    if (!data->type || data->type == XPMBUFFER) {
303	if (data->cptr) {
304	    char *start = data->cptr;
305	    while ((c = *data->cptr) && c != data->Eos)
306		data->cptr++;
307	    n = data->cptr - start + 1;
308	    p = (char *) XpmMalloc(n);
309	    if (!p)
310		return (XpmNoMemory);
311	    strncpy(p, start, n);
312	    if (data->type)		/* XPMBUFFER */
313		p[n - 1] = '\0';
314	}
315    } else {
316	FILE *file = data->stream.file;
317
318	if ((c = Getc(data, file)) == EOF)
319	    return (XpmFileInvalid);
320
321	i = 0;
322	q = buf;
323	p = (char *) XpmMalloc(1);
324	while (c != data->Eos && c != EOF) {
325	    if (i == BUFSIZ) {
326		/* get to the end of the buffer */
327		/* malloc needed memory */
328		q = (char *) XpmRealloc(p, n + i);
329		if (!q) {
330		    XpmFree(p);
331		    return (XpmNoMemory);
332		}
333		p = q;
334		q += n;
335		/* and copy what we already have */
336		strncpy(q, buf, i);
337		n += i;
338		i = 0;
339		q = buf;
340	    }
341	    *q++ = c;
342	    i++;
343	    c = Getc(data, file);
344	}
345	if (c == EOF) {
346	    XpmFree(p);
347	    return (XpmFileInvalid);
348	}
349	if (n + i != 0) {
350	    /* malloc needed memory */
351	    q = (char *) XpmRealloc(p, n + i + 1);
352	    if (!q) {
353		XpmFree(p);
354		return (XpmNoMemory);
355	    }
356	    p = q;
357	    q += n;
358	    /* and copy the buffer */
359	    strncpy(q, buf, i);
360	    n += i;
361	    p[n++] = '\0';
362	} else {
363	    *p = '\0';
364	    n = 1;
365	}
366	Ungetc(data, c, file);
367    }
368    *sptr = p;
369    *l = n;
370    return (XpmSuccess);
371}
372
373/*
374 * get the current comment line
375 */
376int
377xpmGetCmt(
378    xpmData	 *data,
379    char	**cmt)
380{
381    if (!data->type)
382	*cmt = NULL;
383    else if (data->CommentLength != 0 && data->CommentLength < UINT_MAX - 1) {
384	if( (*cmt = (char *) XpmMalloc(data->CommentLength + 1)) == NULL)
385		return XpmNoMemory;
386	strncpy(*cmt, data->Comment, data->CommentLength);
387	(*cmt)[data->CommentLength] = '\0';
388	data->CommentLength = 0;
389    } else
390	*cmt = NULL;
391    return 0;
392}
393
394xpmDataType xpmDataTypes[] =
395{
396    {"", "!", "\n", '\0', '\n', "", "", "", ""},	/* Natural type */
397    {"C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n"},
398    {"Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n"},
399    {NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL}
400};
401
402/*
403 * parse xpm header
404 */
405int
406xpmParseHeader(xpmData *data)
407{
408    char buf[BUFSIZ+1] = {0};
409    int l, n = 0;
410
411    if (data->type) {
412	data->Bos = '\0';
413	data->Eos = '\n';
414	data->Bcmt = data->Ecmt = NULL;
415	l = xpmNextWord(data, buf, BUFSIZ);
416	if (l == 7 && !strncmp("#define", buf, 7)) {
417	    /* this maybe an XPM 1 file */
418	    char *ptr;
419
420	    l = xpmNextWord(data, buf, BUFSIZ);
421	    if (!l)
422		return (XpmFileInvalid);
423	    buf[l] = '\0';
424	    ptr = strrchr(buf, '_');
425	    if (!ptr || strncmp("_format", ptr, l - (ptr - buf)))
426		return XpmFileInvalid;
427	    /* this is definitely an XPM 1 file */
428	    data->format = 1;
429	    n = 1;			/* handle XPM1 as mainly XPM2 C */
430	} else {
431
432	    /*
433	     * skip the first word, get the second one, and see if this is
434	     * XPM 2 or 3
435	     */
436	    l = xpmNextWord(data, buf, BUFSIZ);
437	    if ((l == 3 && !strncmp("XPM", buf, 3)) ||
438		(l == 4 && !strncmp("XPM2", buf, 4))) {
439		if (l == 3)
440		    n = 1;		/* handle XPM as XPM2 C */
441		else {
442		    /* get the type key word */
443		    l = xpmNextWord(data, buf, BUFSIZ);
444
445		    /*
446		     * get infos about this type
447		     */
448		    while (xpmDataTypes[n].type
449			   && strncmp(xpmDataTypes[n].type, buf, l))
450			n++;
451		}
452		data->format = 0;
453	    } else
454		/* nope this is not an XPM file */
455		return XpmFileInvalid;
456	}
457	if (xpmDataTypes[n].type) {
458	    if (n == 0) {		/* natural type */
459		data->Bcmt = xpmDataTypes[n].Bcmt;
460		data->Ecmt = xpmDataTypes[n].Ecmt;
461		xpmNextString(data);	/* skip the end of the headerline */
462		data->Bos = xpmDataTypes[n].Bos;
463		data->Eos = xpmDataTypes[n].Eos;
464	    } else {
465		data->Bcmt = xpmDataTypes[n].Bcmt;
466		data->Ecmt = xpmDataTypes[n].Ecmt;
467		if (!data->format) {	/* XPM 2 or 3 */
468		    data->Bos = xpmDataTypes[n].Bos;
469		    data->Eos = '\0';
470		    /* get to the beginning of the first string */
471		    xpmNextString(data);
472		    data->Eos = xpmDataTypes[n].Eos;
473		} else			/* XPM 1 skip end of line */
474		    xpmNextString(data);
475	    }
476	} else
477	    /* we don't know about that type of XPM file... */
478	    return XpmFileInvalid;
479    }
480    return XpmSuccess;
481}