mirror of
https://gitlab.freedesktop.org/libbsd/libbsd.git
synced 2025-04-26 18:11:26 +02:00
Add new fparseln() function
Taken from NetBSD. [guillem@hadrons.org: - Import from NetBSD instead of FreeBSD to get a 3-clause BSD license, instead of a 4-clause one. - Define compatibility macros. - Change library from libc to libbsd and header in man page. - Add copyright information to COPYING. - Add symbol to map file. ] Signed-off-by: Guillem Jover <guillem@hadrons.org>
This commit is contained in:
parent
cb7bc0d85e
commit
ee0489eb2b
3
COPYING
3
COPYING
@ -283,6 +283,9 @@ The rest of the licenses apply to code and/or man pages.
|
|||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
|
Copyright © 1997 Christos Zoulas.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
Copyright © 2002 Niels Provos <provos@citi.umich.edu>
|
Copyright © 2002 Niels Provos <provos@citi.umich.edu>
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
@ -40,8 +40,10 @@
|
|||||||
#define _LIBUTIL_H_
|
#define _LIBUTIL_H_
|
||||||
|
|
||||||
#include <features.h>
|
#include <features.h>
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/* for pidfile.c */
|
/* for pidfile.c */
|
||||||
struct pidfh {
|
struct pidfh {
|
||||||
@ -62,6 +64,8 @@ struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
|
|||||||
int pidfile_write(struct pidfh *pfh);
|
int pidfile_write(struct pidfh *pfh);
|
||||||
int pidfile_close(struct pidfh *pfh);
|
int pidfile_close(struct pidfh *pfh);
|
||||||
int pidfile_remove(struct pidfh *pfh);
|
int pidfile_remove(struct pidfh *pfh);
|
||||||
|
|
||||||
|
char *fparseln(FILE *, size_t *, size_t *, const char[3], int);
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
/* humanize_number(3) */
|
/* humanize_number(3) */
|
||||||
@ -73,4 +77,13 @@ __END_DECLS
|
|||||||
#define HN_GETSCALE 0x10
|
#define HN_GETSCALE 0x10
|
||||||
#define HN_AUTOSCALE 0x20
|
#define HN_AUTOSCALE 0x20
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fparseln() specific operation flags.
|
||||||
|
*/
|
||||||
|
#define FPARSELN_UNESCESC 0x01
|
||||||
|
#define FPARSELN_UNESCCONT 0x02
|
||||||
|
#define FPARSELN_UNESCCOMM 0x04
|
||||||
|
#define FPARSELN_UNESCREST 0x08
|
||||||
|
#define FPARSELN_UNESCALL 0x0f
|
||||||
|
|
||||||
#endif /* !_LIBUTIL_H_ */
|
#endif /* !_LIBUTIL_H_ */
|
||||||
|
@ -26,6 +26,7 @@ dist_man_MANS = \
|
|||||||
fgetln.3 \
|
fgetln.3 \
|
||||||
flopen.3 \
|
flopen.3 \
|
||||||
fmtcheck.3 \
|
fmtcheck.3 \
|
||||||
|
fparseln.3 \
|
||||||
getmode.3 \
|
getmode.3 \
|
||||||
getpeereid.3 \
|
getpeereid.3 \
|
||||||
getprogname.3 \
|
getprogname.3 \
|
||||||
|
149
man/fparseln.3
Normal file
149
man/fparseln.3
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
.\" $NetBSD: fparseln.3,v 1.4 2009/10/21 01:07:45 snj Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1997 Christos Zoulas. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd November 30, 2002
|
||||||
|
.Dt FPARSELN 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm fparseln
|
||||||
|
.Nd return the next logical line from a stream
|
||||||
|
.Sh LIBRARY
|
||||||
|
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
|
||||||
|
.Lb libbsd
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In bsd/stdio.h
|
||||||
|
.Ft "char *"
|
||||||
|
.Fo "fparseln"
|
||||||
|
.Fa "FILE *stream" "size_t *len" "size_t *lineno"
|
||||||
|
.Fa "const char delim[3]" "int flags"
|
||||||
|
.Fc
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn fparseln
|
||||||
|
function
|
||||||
|
returns a pointer to the next logical line from the stream referenced by
|
||||||
|
.Fa stream .
|
||||||
|
This string is
|
||||||
|
.Dv NUL
|
||||||
|
terminated and it is dynamically allocated on each invocation.
|
||||||
|
It is the responsibility of the caller to free the pointer.
|
||||||
|
.Pp
|
||||||
|
By default, if a character is escaped, both it and the preceding escape
|
||||||
|
character will be present in the returned string.
|
||||||
|
Various
|
||||||
|
.Fa flags
|
||||||
|
alter this behaviour.
|
||||||
|
.Pp
|
||||||
|
The meaning of the arguments is as follows:
|
||||||
|
.Bl -tag -width "lineno"
|
||||||
|
.It Fa stream
|
||||||
|
The stream to read from.
|
||||||
|
.It Fa len
|
||||||
|
If not
|
||||||
|
.Dv NULL ,
|
||||||
|
the length of the string is stored in the memory location to which it
|
||||||
|
points.
|
||||||
|
.It Fa lineno
|
||||||
|
If not
|
||||||
|
.Dv NULL ,
|
||||||
|
the value of the memory location to which is pointed to, is incremented
|
||||||
|
by the number of lines actually read from the file.
|
||||||
|
.It Fa delim
|
||||||
|
Contains the escape, continuation, and comment characters.
|
||||||
|
If a character is
|
||||||
|
.Dv NUL
|
||||||
|
then processing for that character is disabled.
|
||||||
|
If
|
||||||
|
.Dv NULL ,
|
||||||
|
all characters default to values specified below.
|
||||||
|
The contents of
|
||||||
|
.Fa delim
|
||||||
|
is as follows:
|
||||||
|
.Bl -tag -width "delim[0]"
|
||||||
|
.It Fa delim[0]
|
||||||
|
The escape character, which defaults to
|
||||||
|
.Cm \e ,
|
||||||
|
is used to remove any special meaning from the next character.
|
||||||
|
.It Fa delim[1]
|
||||||
|
The continuation character, which defaults to
|
||||||
|
.Cm \e ,
|
||||||
|
is used to indicate that the next line should be concatenated with the
|
||||||
|
current one if this character is the last character on the current line
|
||||||
|
and is not escaped.
|
||||||
|
.It Fa delim[2]
|
||||||
|
The comment character, which defaults to
|
||||||
|
.Cm # ,
|
||||||
|
if not escaped indicates the beginning of a comment that extends until the
|
||||||
|
end of the current line.
|
||||||
|
.El
|
||||||
|
.It Fa flags
|
||||||
|
If non-zero, alter the operation of
|
||||||
|
.Fn fparseln .
|
||||||
|
The various flags, which may be
|
||||||
|
.Em or Ns -ed
|
||||||
|
together, are:
|
||||||
|
.Bl -tag -width "FPARSELN_UNESCCOMM"
|
||||||
|
.It Dv FPARSELN_UNESCCOMM
|
||||||
|
Remove escape preceding an escaped comment.
|
||||||
|
.It Dv FPARSELN_UNESCCONT
|
||||||
|
Remove escape preceding an escaped continuation.
|
||||||
|
.It Dv FPARSELN_UNESCESC
|
||||||
|
Remove escape preceding an escaped escape.
|
||||||
|
.It Dv FPARSELN_UNESCREST
|
||||||
|
Remove escape preceding any other character.
|
||||||
|
.It Dv FPARSELN_UNESCALL
|
||||||
|
All of the above.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
.El
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
Upon successful completion a pointer to the parsed line is returned;
|
||||||
|
otherwise,
|
||||||
|
.Dv NULL
|
||||||
|
is returned.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn fparseln
|
||||||
|
function uses internally
|
||||||
|
.Xr fgetln 3 ,
|
||||||
|
so all error conditions that apply to
|
||||||
|
.Xr fgetln 3 ,
|
||||||
|
apply to
|
||||||
|
.Fn fparseln .
|
||||||
|
In addition
|
||||||
|
.Fn fparseln
|
||||||
|
may set
|
||||||
|
.Va errno
|
||||||
|
to
|
||||||
|
.Bq Er ENOMEM
|
||||||
|
and return
|
||||||
|
.Dv NULL
|
||||||
|
if it runs out of memory.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr fgetln 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn fparseln
|
||||||
|
function first appeared in
|
||||||
|
.Nx 1.4 .
|
@ -45,6 +45,7 @@ libbsd_la_SOURCES = \
|
|||||||
fgetln.c \
|
fgetln.c \
|
||||||
flopen.c \
|
flopen.c \
|
||||||
fmtcheck.c \
|
fmtcheck.c \
|
||||||
|
fparseln.c \
|
||||||
fpurge.c \
|
fpurge.c \
|
||||||
getpeereid.c \
|
getpeereid.c \
|
||||||
hash/md5.c \
|
hash/md5.c \
|
||||||
|
230
src/fparseln.c
Normal file
230
src/fparseln.c
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/* $NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1997 Christos Zoulas. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define FLOCKFILE(fp)
|
||||||
|
#define FUNLOCKFILE(fp)
|
||||||
|
#define _DIAGASSERT(t)
|
||||||
|
|
||||||
|
static int isescaped(const char *, const char *, int);
|
||||||
|
|
||||||
|
/* isescaped():
|
||||||
|
* Return true if the character in *p that belongs to a string
|
||||||
|
* that starts in *sp, is escaped by the escape character esc.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
isescaped(const char *sp, const char *p, int esc)
|
||||||
|
{
|
||||||
|
const char *cp;
|
||||||
|
size_t ne;
|
||||||
|
|
||||||
|
_DIAGASSERT(sp != NULL);
|
||||||
|
_DIAGASSERT(p != NULL);
|
||||||
|
|
||||||
|
/* No escape character */
|
||||||
|
if (esc == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Count the number of escape characters that precede ours */
|
||||||
|
for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Return true if odd number of escape characters */
|
||||||
|
return (ne & 1) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* fparseln():
|
||||||
|
* Read a line from a file parsing continuations ending in \
|
||||||
|
* and eliminating trailing newlines, or comments starting with
|
||||||
|
* the comment char.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
|
||||||
|
{
|
||||||
|
static const char dstr[3] = { '\\', '\\', '#' };
|
||||||
|
|
||||||
|
size_t s, len;
|
||||||
|
char *buf;
|
||||||
|
char *ptr, *cp;
|
||||||
|
int cnt;
|
||||||
|
char esc, con, nl, com;
|
||||||
|
|
||||||
|
_DIAGASSERT(fp != NULL);
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
buf = NULL;
|
||||||
|
cnt = 1;
|
||||||
|
|
||||||
|
if (str == NULL)
|
||||||
|
str = dstr;
|
||||||
|
|
||||||
|
esc = str[0];
|
||||||
|
con = str[1];
|
||||||
|
com = str[2];
|
||||||
|
/*
|
||||||
|
* XXX: it would be cool to be able to specify the newline character,
|
||||||
|
* but unfortunately, fgetln does not let us
|
||||||
|
*/
|
||||||
|
nl = '\n';
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
|
|
||||||
|
while (cnt) {
|
||||||
|
cnt = 0;
|
||||||
|
|
||||||
|
if (lineno)
|
||||||
|
(*lineno)++;
|
||||||
|
|
||||||
|
if ((ptr = fgetln(fp, &s)) == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (s && com) { /* Check and eliminate comments */
|
||||||
|
for (cp = ptr; cp < ptr + s; cp++)
|
||||||
|
if (*cp == com && !isescaped(ptr, cp, esc)) {
|
||||||
|
s = cp - ptr;
|
||||||
|
cnt = s == 0 && buf == NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s && nl) { /* Check and eliminate newlines */
|
||||||
|
cp = &ptr[s - 1];
|
||||||
|
|
||||||
|
if (*cp == nl)
|
||||||
|
s--; /* forget newline */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s && con) { /* Check and eliminate continuations */
|
||||||
|
cp = &ptr[s - 1];
|
||||||
|
|
||||||
|
if (*cp == con && !isescaped(ptr, cp, esc)) {
|
||||||
|
s--; /* forget continuation char */
|
||||||
|
cnt = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s == 0) {
|
||||||
|
/*
|
||||||
|
* nothing to add, skip realloc except in case
|
||||||
|
* we need a minimal buf to return an empty line
|
||||||
|
*/
|
||||||
|
if (cnt || buf != NULL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cp = realloc(buf, len + s + 1)) == NULL) {
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf = cp;
|
||||||
|
|
||||||
|
(void) memcpy(buf + len, ptr, s);
|
||||||
|
len += s;
|
||||||
|
buf[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
|
||||||
|
if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
|
||||||
|
strchr(buf, esc) != NULL) {
|
||||||
|
ptr = cp = buf;
|
||||||
|
while (cp[0] != '\0') {
|
||||||
|
int skipesc;
|
||||||
|
|
||||||
|
while (cp[0] != '\0' && cp[0] != esc)
|
||||||
|
*ptr++ = *cp++;
|
||||||
|
if (cp[0] == '\0' || cp[1] == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
skipesc = 0;
|
||||||
|
if (cp[1] == com)
|
||||||
|
skipesc += (flags & FPARSELN_UNESCCOMM);
|
||||||
|
if (cp[1] == con)
|
||||||
|
skipesc += (flags & FPARSELN_UNESCCONT);
|
||||||
|
if (cp[1] == esc)
|
||||||
|
skipesc += (flags & FPARSELN_UNESCESC);
|
||||||
|
if (cp[1] != com && cp[1] != con && cp[1] != esc)
|
||||||
|
skipesc = (flags & FPARSELN_UNESCREST);
|
||||||
|
|
||||||
|
if (skipesc)
|
||||||
|
cp++;
|
||||||
|
else
|
||||||
|
*ptr++ = *cp++;
|
||||||
|
*ptr++ = *cp++;
|
||||||
|
}
|
||||||
|
*ptr = '\0';
|
||||||
|
len = strlen(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
*size = len;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
|
||||||
|
int main(int, char **);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
size_t size, line;
|
||||||
|
|
||||||
|
line = 0;
|
||||||
|
while ((ptr = fparseln(stdin, &size, &line, NULL,
|
||||||
|
FPARSELN_UNESCALL)) != NULL)
|
||||||
|
printf("line %d (%d) |%s|\n", line, size, ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
# This is a test
|
||||||
|
line 1
|
||||||
|
line 2 \
|
||||||
|
line 3 # Comment
|
||||||
|
line 4 \# Not comment \\\\
|
||||||
|
|
||||||
|
# And a comment \
|
||||||
|
line 5 \\\
|
||||||
|
line 6
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* TEST */
|
@ -96,6 +96,8 @@ LIBBSD_0.4 {
|
|||||||
} LIBBSD_0.3;
|
} LIBBSD_0.3;
|
||||||
|
|
||||||
LIBBSD_0.5 {
|
LIBBSD_0.5 {
|
||||||
|
fparseln;
|
||||||
|
|
||||||
strnstr;
|
strnstr;
|
||||||
|
|
||||||
wcslcat;
|
wcslcat;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user