Annotation of embedaddon/tmux/compat/fparseln.c, revision 1.1
1.1 ! misho 1: /* $OpenBSD: fparseln.c,v 1.6 2005/08/02 21:46:23 espie Exp $ */
! 2: /* $NetBSD: fparseln.c,v 1.7 1999/07/02 15:49:12 simonb Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1997 Christos Zoulas. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Christos Zoulas.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: /* OPENBSD ORIGINAL: lib/libutil/fparseln.c */
! 34:
! 35: #include <sys/types.h>
! 36:
! 37: #include <stdio.h>
! 38: #include <string.h>
! 39: #include <stdlib.h>
! 40:
! 41: #include "compat.h"
! 42:
! 43: /*
! 44: * fparseln() specific operation flags.
! 45: */
! 46: #define FPARSELN_UNESCESC 0x01
! 47: #define FPARSELN_UNESCCONT 0x02
! 48: #define FPARSELN_UNESCCOMM 0x04
! 49: #define FPARSELN_UNESCREST 0x08
! 50: #define FPARSELN_UNESCALL 0x0f
! 51:
! 52: static int isescaped(const char *, const char *, int);
! 53:
! 54: /* isescaped():
! 55: * Return true if the character in *p that belongs to a string
! 56: * that starts in *sp, is escaped by the escape character esc.
! 57: */
! 58: static int
! 59: isescaped(const char *sp, const char *p, int esc)
! 60: {
! 61: const char *cp;
! 62: size_t ne;
! 63:
! 64: /* No escape character */
! 65: if (esc == '\0')
! 66: return 1;
! 67:
! 68: /* Count the number of escape characters that precede ours */
! 69: for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)
! 70: continue;
! 71:
! 72: /* Return true if odd number of escape characters */
! 73: return (ne & 1) != 0;
! 74: }
! 75:
! 76:
! 77: /* fparseln():
! 78: * Read a line from a file parsing continuations ending in \
! 79: * and eliminating trailing newlines, or comments starting with
! 80: * the comment char.
! 81: */
! 82: char *
! 83: fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3],
! 84: int flags)
! 85: {
! 86: static const char dstr[3] = { '\\', '\\', '#' };
! 87: char *buf = NULL, *ptr, *cp, esc, con, nl, com;
! 88: size_t s, len = 0;
! 89: int cnt = 1;
! 90:
! 91: if (str == NULL)
! 92: str = dstr;
! 93:
! 94: esc = str[0];
! 95: con = str[1];
! 96: com = str[2];
! 97:
! 98: /*
! 99: * XXX: it would be cool to be able to specify the newline character,
! 100: * but unfortunately, fgetln does not let us
! 101: */
! 102: nl = '\n';
! 103:
! 104: while (cnt) {
! 105: cnt = 0;
! 106:
! 107: if (lineno)
! 108: (*lineno)++;
! 109:
! 110: if ((ptr = fgetln(fp, &s)) == NULL)
! 111: break;
! 112:
! 113: if (s && com) { /* Check and eliminate comments */
! 114: for (cp = ptr; cp < ptr + s; cp++)
! 115: if (*cp == com && !isescaped(ptr, cp, esc)) {
! 116: s = cp - ptr;
! 117: cnt = s == 0 && buf == NULL;
! 118: break;
! 119: }
! 120: }
! 121:
! 122: if (s && nl) { /* Check and eliminate newlines */
! 123: cp = &ptr[s - 1];
! 124:
! 125: if (*cp == nl)
! 126: s--; /* forget newline */
! 127: }
! 128:
! 129: if (s && con) { /* Check and eliminate continuations */
! 130: cp = &ptr[s - 1];
! 131:
! 132: if (*cp == con && !isescaped(ptr, cp, esc)) {
! 133: s--; /* forget escape */
! 134: cnt = 1;
! 135: }
! 136: }
! 137:
! 138: if (s == 0 && buf != NULL)
! 139: continue;
! 140:
! 141: if ((cp = realloc(buf, len + s + 1)) == NULL) {
! 142: free(buf);
! 143: return NULL;
! 144: }
! 145: buf = cp;
! 146:
! 147: (void) memcpy(buf + len, ptr, s);
! 148: len += s;
! 149: buf[len] = '\0';
! 150: }
! 151:
! 152: if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
! 153: strchr(buf, esc) != NULL) {
! 154: ptr = cp = buf;
! 155: while (cp[0] != '\0') {
! 156: int skipesc;
! 157:
! 158: while (cp[0] != '\0' && cp[0] != esc)
! 159: *ptr++ = *cp++;
! 160: if (cp[0] == '\0' || cp[1] == '\0')
! 161: break;
! 162:
! 163: skipesc = 0;
! 164: if (cp[1] == com)
! 165: skipesc += (flags & FPARSELN_UNESCCOMM);
! 166: if (cp[1] == con)
! 167: skipesc += (flags & FPARSELN_UNESCCONT);
! 168: if (cp[1] == esc)
! 169: skipesc += (flags & FPARSELN_UNESCESC);
! 170: if (cp[1] != com && cp[1] != con && cp[1] != esc)
! 171: skipesc = (flags & FPARSELN_UNESCREST);
! 172:
! 173: if (skipesc)
! 174: cp++;
! 175: else
! 176: *ptr++ = *cp++;
! 177: *ptr++ = *cp++;
! 178: }
! 179: *ptr = '\0';
! 180: len = strlen(buf);
! 181: }
! 182:
! 183: if (size)
! 184: *size = len;
! 185: return buf;
! 186: }
! 187:
! 188: #ifdef TEST
! 189:
! 190: int main(int, char **);
! 191:
! 192: int
! 193: main(argc, argv)
! 194: int argc;
! 195: char **argv;
! 196: {
! 197: char *ptr;
! 198: size_t size, line;
! 199:
! 200: line = 0;
! 201: while ((ptr = fparseln(stdin, &size, &line, NULL,
! 202: FPARSELN_UNESCALL)) != NULL)
! 203: printf("line %d (%d) |%s|\n", line, size, ptr);
! 204: return 0;
! 205: }
! 206:
! 207: /*
! 208:
! 209: # This is a test
! 210: line 1
! 211: line 2 \
! 212: line 3 # Comment
! 213: line 4 \# Not comment \\\\
! 214:
! 215: # And a comment \
! 216: line 5 \\\
! 217: line 6
! 218:
! 219: */
! 220:
! 221: #endif /* TEST */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>