data.c revision a966c04f
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/* $XFree86: xc/extras/Xpm/lib/data.c,v 1.3 2001/10/28 03:32:10 tsi Exp $ */ 35 36/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ 37 38#ifndef CXPMPROG 39#if 0 40/* Official version number */ 41static char *RCS_Version = "$XpmVersion: 3.4k $"; 42 43/* Internal version number */ 44static char *RCS_Id = "Id: xpm.shar,v 3.71 1998/03/19 19:47:14 lehors Exp $"; 45#endif 46#ifdef HAVE_CONFIG_H 47#include <config.h> 48#endif 49#include "XpmI.h" 50#endif 51#include <ctype.h> 52 53#ifndef CXPMPROG 54#define Getc(data, file) getc(file) 55#define Ungetc(data, c, file) ungetc(c, file) 56#endif 57 58static int 59ParseComment(xpmData *data) 60{ 61 if (data->type == XPMBUFFER) { 62 register char c; 63 register unsigned int n = 0; 64 unsigned int notend; 65 char *s, *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, *s2; 124 125 s = data->Comment; 126 *s = data->Bcmt[0]; 127 128 /* skip the string beginning comment */ 129 s2 = data->Bcmt; 130 do { 131 c = Getc(data, file); 132 *++s = c; 133 n++; 134 s2++; 135 } while (c == *s2 && *s2 != '\0' && c != EOF); 136 137 if (*s2 != '\0') { 138 /* this wasn't the beginning of a comment */ 139 /* put characters back in the order that we got them */ 140 for (a = n; a > 0; a--, s--) 141 Ungetc(data, *s, file); 142 return 0; 143 } 144 /* store comment */ 145 data->Comment[0] = *s; 146 s = data->Comment; 147 notend = 1; 148 n = 0; 149 while (notend) { 150 s2 = data->Ecmt; 151 while (*s != *s2 && c != EOF) { 152 c = Getc(data, file); 153 if (n == XPMMAXCMTLEN - 1) { /* forget it */ 154 s = data->Comment; 155 n = 0; 156 } 157 *++s = c; 158 n++; 159 } 160 data->CommentLength = n; 161 do { 162 c = Getc(data, file); 163 if (n == XPMMAXCMTLEN - 1) { /* forget it */ 164 s = data->Comment; 165 n = 0; 166 } 167 *++s = c; 168 n++; 169 s2++; 170 } while (c == *s2 && *s2 != '\0' && c != EOF); 171 if (*s2 == '\0') { 172 /* this is the end of the comment */ 173 notend = 0; 174 Ungetc(data, *s, file); 175 } 176 } 177 return 0; 178 } 179} 180 181/* 182 * skip to the end of the current string and the beginning of the next one 183 */ 184int 185xpmNextString(data) 186 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(data, buf, buflen) 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(data, ui_return) 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(data, sptr, l) 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(data, cmt) 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(data) 407 xpmData *data; 408{ 409 char buf[BUFSIZ+1] = {0}; 410 int l, n = 0; 411 412 if (data->type) { 413 data->Bos = '\0'; 414 data->Eos = '\n'; 415 data->Bcmt = data->Ecmt = NULL; 416 l = xpmNextWord(data, buf, BUFSIZ); 417 if (l == 7 && !strncmp("#define", buf, 7)) { 418 /* this maybe an XPM 1 file */ 419 char *ptr; 420 421 l = xpmNextWord(data, buf, BUFSIZ); 422 if (!l) 423 return (XpmFileInvalid); 424 buf[l] = '\0'; 425 ptr = strrchr(buf, '_'); 426 if (!ptr || strncmp("_format", ptr, l - (ptr - buf))) 427 return XpmFileInvalid; 428 /* this is definitely an XPM 1 file */ 429 data->format = 1; 430 n = 1; /* handle XPM1 as mainly XPM2 C */ 431 } else { 432 433 /* 434 * skip the first word, get the second one, and see if this is 435 * XPM 2 or 3 436 */ 437 l = xpmNextWord(data, buf, BUFSIZ); 438 if ((l == 3 && !strncmp("XPM", buf, 3)) || 439 (l == 4 && !strncmp("XPM2", buf, 4))) { 440 if (l == 3) 441 n = 1; /* handle XPM as XPM2 C */ 442 else { 443 /* get the type key word */ 444 l = xpmNextWord(data, buf, BUFSIZ); 445 446 /* 447 * get infos about this type 448 */ 449 while (xpmDataTypes[n].type 450 && strncmp(xpmDataTypes[n].type, buf, l)) 451 n++; 452 } 453 data->format = 0; 454 } else 455 /* nope this is not an XPM file */ 456 return XpmFileInvalid; 457 } 458 if (xpmDataTypes[n].type) { 459 if (n == 0) { /* natural type */ 460 data->Bcmt = xpmDataTypes[n].Bcmt; 461 data->Ecmt = xpmDataTypes[n].Ecmt; 462 xpmNextString(data); /* skip the end of the headerline */ 463 data->Bos = xpmDataTypes[n].Bos; 464 data->Eos = xpmDataTypes[n].Eos; 465 } else { 466 data->Bcmt = xpmDataTypes[n].Bcmt; 467 data->Ecmt = xpmDataTypes[n].Ecmt; 468 if (!data->format) { /* XPM 2 or 3 */ 469 data->Bos = xpmDataTypes[n].Bos; 470 data->Eos = '\0'; 471 /* get to the beginning of the first string */ 472 xpmNextString(data); 473 data->Eos = xpmDataTypes[n].Eos; 474 } else /* XPM 1 skip end of line */ 475 xpmNextString(data); 476 } 477 } else 478 /* we don't know about that type of XPM file... */ 479 return XpmFileInvalid; 480 } 481 return XpmSuccess; 482} 483