Silly CVSWeb won't show head revisions if they're deleted. I got
these files by looking at the penultimate revisions.
------------- svn_parse.h
/* svn_parse: shared parsing routines for reading config files
*
* ================================================================
* Copyright (c) 2000 Collab.Net. 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.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement: "This product includes
* software developed by Collab.Net (http://www.Collab.Net/)."
* Alternately, this acknowlegement may appear in the software itself, if
* and wherever such third-party acknowlegements normally appear.
*
* 4. The hosted project names must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact info@collab.net.
*
* 5. Products derived from this software may not use the "Tigris" name
* nor may "Tigris" appear in their names without prior written
* permission of Collab.Net.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 COLLAB.NET OR ITS CONTRIBUTORS 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.
*
* ====================================================================
*
* This software may consist of voluntary contributions made by many
* individuals on behalf of Collab.Net.
*/
#ifndef SVN_PARSE_H
#define SVN_PARSE_H
#include <svn_types.h>
#include <svn_string.h>
#include <svn_error.h>
#include <apr_pools.h>
#include <apr_hash.h>
#include <apr_file_io.h>
#include <ctype.h> /* isspace() */
/*
General Utility -- reads a config file, returns a hash of hashes.
For file format, see `notes/svn-config-files'
*/
svn_error_t * svn_parse (ap_hash_t **returnhash,
const char *filename,
ap_pool_t *pool);
/* Prints a hash, assuming all keys/vals are (svn_string_t *) */
void svn_hash_print (ap_hash_t *hash, FILE *stream);
/* Prints uberhash returned from svn_parse(),
assuming each key is (svn_string_t *)
and each val is printable by svn_hash_print(). */
void svn_uberhash_print (ap_hash_t *uberhash, FILE *stream);
#endif /* SVN_PARSE_H */
/*
* local variables:
* eval: (load-file "../svn-dev.el")
* end: */
------------- svn_parse.c
/* svn_parse: shared parsing routines for reading config files
*
* ================================================================
* Copyright (c) 2000 CollabNet. 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.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement: "This product includes
* software developed by CollabNet (http://www.Collab.Net)."
* Alternately, this acknowlegement may appear in the software itself, if
* and wherever such third-party acknowlegements normally appear.
*
* 4. The hosted project names must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact info@collab.net.
*
* 5. Products derived from this software may not use the "Tigris" name
* nor may "Tigris" appear in their names without prior written
* permission of CollabNet.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 COLLABNET OR ITS CONTRIBUTORS 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.
*
* ====================================================================
*
* This software may consist of voluntary contributions made by many
* individuals on behalf of CollabNet.
*/
#include "svn_parse.h"
/*
NOT EXPORTED.
Input: an open file, a bytestring ptr, and a pool.
Returns: either APR_EOF or APR_SUCCESS, and a filled-in bytestring
containing the next line of the file.
(Note that the same bytestring can be reused in multiple
calls to this routine, because the bytestring is cleared at
the beginning.)
*/
apr_status_t
svn__my_readline (apr_file_t *file, svn_string_t *line, apr_pool_t *pool)
{
char c;
apr_status_t result;
svn_string_setempty (line); /* clear the bytestring first! */
while (1)
{
result = apr_getc (&c, file); /* read a byte from the file */
if (result == APR_EOF) /* file is finished. */
{
return APR_EOF;
}
if (c == '\n') /* line is finished. */
{
/* store the newline in our bytestring (important!) */
svn_string_appendbytes (line, &c, 1);
return APR_SUCCESS;
}
else /* otherwise, just append this byte to the bytestring */
{
svn_string_appendbytes (line, &c, 1);
}
}
}
/*
NOT EXPORTED.
Input: a bytestring, a handle for returning a bytestring, the
starting search offset, search character, and pool
Returns: 1. the offset of the search character (-1 if no match)
2. a newly allocated substring in "substr" (NULL if no match)
* This substring starts at `start' and goes to the offset
* This substring has no whitespace at either end
If used repeatedly, this routine is like a poor man's `split'
(combined with chomp).
*/
int
svn__slurp_to (const svn_string_t *searchstr,
svn_string_t **substr,
const size_t start,
const char sc,
apr_pool_t *pool)
{
int i;
/* Create a new bytestring */
*substr = svn_string_create ("<nobody home>", pool);
svn_string_setempty (*substr);
for (i = start; i < searchstr->len; i++)
{
if (searchstr->data[i] == sc)
{
/* printf ("found character '%c' at offset %d\n", sc, i);*/
svn_string_appendbytes (*substr, /* new substring */
searchstr->data + start,/* start copy */
(i - start)); /* number to copy */
svn_string_strip_whitespace (*substr);
return i;
}
}
/* If we get here, then the bytestring doesn't contain our search
character. This is bogus. */
*substr = NULL;
return -1;
}
/*
svn_parse() (finally)
Input: a filename and pool, pointer to a hash
Output: a pointer to a hash of hashes, all built within the pool
This routine parses a file which conforms to the standard
Subversion config file format (look in notes/).
The hash returned is a mapping from section-names to hash pointers;
each hash contains the keys/vals for each section. All
section-names, keys and vals are stored as svn_string_t pointers.
(These bytestrings are allocated in the same pool as the hashes.)
This routine makes no attempt to understand the sections, keys or
values. :) */
svn_error_t *
svn_parse (apr_hash_t **uberhash, const char *filename, apr_pool_t *pool)
{
apr_hash_t *current_hash; /* the hash we're currently storing vals in */
apr_pool_t *scratchpool;
svn_string_t *currentline;
apr_status_t result;
apr_file_t *file = NULL;
/* Create our uberhash */
*uberhash = apr_make_hash (pool);
/* Open the config file */
result = apr_open (&file,
filename,
APR_READ,
APR_OS_DEFAULT, /*TODO: WHAT IS THIS? */
pool);
if (result != APR_SUCCESS)
{
char *finalmsg; /* TODO: use apr's sprintf() thingie here */
svn_string_t *msg = svn_string_create
("svn_parse(): can't open for reading, file ", pool);
svn_string_appendstr (msg, filename);
return svn_error_create (result, NULL, NULL, pool, msg->data);
}
/* Create a scratch memory pool for buffering our file as we read it */
scratchpool = svn_pool_create (pool);
/* Create a bytestring to hold the current line of file */
currentline = svn_string_create ("<nobody home>", scratchpool);
/* Now start scanning our file, one line at a time */
while (svn__my_readline (file, currentline, scratchpool) != APR_EOF)
{
char c;
size_t offset = svn_string_first_non_whitespace (currentline);
if (offset == currentline->len)
{
/* whole line is whitespace, read next line! */
continue;
}
c = currentline->data[offset]; /* our first non-white character */
switch (c)
{
case '#':
{
/* It's a comment line, so read next line! */
continue;
};
case '[':
{
/* It's a new section! */
/* Create new hash to hold this section's keys/vals */
apr_hash_t *new_section_hash = apr_make_hash (pool);
/* Slurp up the section name */
svn_string_t *new_section;
svn__slurp_to (currentline, /* search current line */
&new_section, /* place new substring here */
offset + 1, /* start searching past the '[' */
']', /* look for this ending character */
pool); /* build our substring in this pool */
if (new_section == NULL) /* couldn't find a ']' ! */
{
policy->warning
(policy->data,
"svn_parse(): skipping malformed line: `%s'",
currentline->data, pool);
break;
}
/* printf ("Found new section: `");
svn_string_print (new_section, stdout, FALSE, FALSE);
printf ("'\n"); */
/* make this new hash the "active" hash for new keys/vals */
current_hash = new_section_hash;
/* store this new hash in our uberhash */
apr_hash_set (*uberhash,
new_section->data, /* key: bytestring */
new_section->len, /* the length of the key */
new_section_hash); /* val: ptr to the new hash */
break;
}
default:
{
/* If it's not a blank line, comment line, or section line,
then it MUST be a key : val line! */
/* Slurp up the key by searching for a colon */
svn_string_t *new_key, *new_val;
size_t local_offset;
local_offset = svn__slurp_to (currentline, /* search line */
&new_key, /* put substring here */
offset, /* start at this offset */
':', /* look for a colon */
pool); /* build substr here */
if (new_key == NULL) /* didn't find a colon! */
{
policy->warning
(policy->data,
"svn_parse(): skipping malformed line: `%s'",
currentline->data);
break;
}
/* Now slurp up the value, starting just past the colon */
svn__slurp_to (currentline,
&new_val,
local_offset + 1,
'\n',
pool);
/* printf ("Key: `");
svn_string_print (new_key, stdout, FALSE, FALSE);
printf ("'\n");
printf ("Val: `");
svn_string_print (new_val, stdout, FALSE, FALSE);
printf ("'\n"); */
/* Should we check for a NULL result from svn__slurp_to?
What are the chances it's not going to find a newline? :)
*/
/* Store key and val in the currently active hash */
apr_hash_set (current_hash,
new_key->data, /* key: bytestring data */
new_key->len, /* length of key */
new_val); /* val: ptr to bytestring */
break;
} /* default: */
} /* switch (c) */
} /* while (readline) */
/* Close the file and free our scratchpool */
result = apr_close (file);
if (result != APR_SUCCESS)
{
policy->warning
(policy->data,
"svn_parse(): can't close file: `%s'", filename->data);
}
apr_destroy_pool (scratchpool);
return SVN_NO_ERROR;
}
/* Convenience Routine: pretty-print an apr_hash_t.
(ASSUMING that all keys and vals are of type (svn_string_t *) )
*/
void
svn_hash_print (apr_hash_t *hash, FILE *stream)
{
apr_hash_index_t *hash_index; /* this represents a hash entry */
void *key, *val;
size_t keylen;
svn_string_t keystring, *valstring;
fprintf (stream, "\n-----> Printing hash:\n");
for (hash_index = apr_hash_first (hash); /* get first hash entry */
hash_index; /* NULL if out of entries */
hash_index = apr_hash_next (hash_index)) /* get next hash entry */
{
/* Retrieve key and val from current hash entry */
apr_hash_this (hash_index, &key, &keylen, &val);
/* Cast things nicely */
keystring.data = key;
keystring.len = keylen;
keystring.blocksize = keylen;
valstring = val;
/* Print them out nicely */
fprintf (stream, "Key: `");
/* TODO: svn_string_print (&keystring, stream, FALSE, FALSE); */
fprintf (stream, "', ");
fprintf (stream, "Val: `");
/* TODO: svn_string_print (valstring, stream, FALSE, FALSE); */
fprintf (stream, "'\n");
}
fprintf (stream, "\n");
}
/* Convenience Routine: pretty-print "uberhash" from svn_parse().
(ASSUMING that all keys are (svn_string_t *),
all vals are (apr_hash_t *) printable by svn_hash_print() )
*/
void
svn_uberhash_print (apr_hash_t *uberhash, FILE *stream)
{
apr_hash_index_t *hash_index; /* this represents a hash entry */
void *key, *val;
size_t keylen;
svn_string_t keystring;
apr_hash_t *valhash;
fprintf (stream, "\n-> Printing Uberhash:\n");
for (hash_index = apr_hash_first (uberhash); /* get first hash entry */
hash_index; /* NULL if out of entries */
hash_index = apr_hash_next (hash_index)) /* get next hash entry */
{
/* Retrieve key and val from current hash entry */
apr_hash_this (hash_index, &key, &keylen, &val);
/* Cast things nicely */
keystring.data = key;
keystring.len = keylen;
keystring.blocksize = keylen;
valhash = val;
/* Print them out nicely */
fprintf (stream, "---> Hashname: `");
/* TODO: svn_string_print (&keystring, stream, FALSE, FALSE); */
fprintf (stream, "'\n");
svn_hash_print (valhash, stream);
}
fprintf (stream, "\nUberhash printing complete.\n\n");
}
/*
* local variables:
* eval: (load-file "../svn-dev.el")
* end: */
------------- parsetest.c
/* Testing svn_parse() */
#include <stdio.h>
#include "svn_parse.h"
int
main ()
{
apr_hash_t *configdata;
apr_pool_t *pool;
svn_error_t *error;
/* Initialize APR (Apache pools) */
if (apr_initialize () != APR_SUCCESS)
{
printf ("apr_initialize() failed.\n");
exit (1);
}
pool = svn_pool_create (NULL);
/* Parse the file "./configfile" */
error =
svn_parse (&configdata, svn_string_create ("configfile", pool), pool);
if (error) {
svn_handle_error (error);
}
/* Print out our configdata uber-hash */
svn_uberhash_print (configdata, stdout);
/* If we were an application using libsvn_svr, we would now pass
this uber-hash to svn_init() to get a `svn_policies_t' structure.
We would then use this structure for all our wrappered filesystem
calls. */
/* Clean up our memory pool and apr */
apr_destroy_pool (pool);
apr_terminate ();
printf ("Test complete, exiting cleanly.\n\n");
return 0;
}
------------- configfile
# This is a sample Subversion config file
# Nicely Formatted Part
[Grades]
Joe : A
Mary : B-
Alice : A+
[Doughnuts]
Powdered : $.39
Chocolate : $1.59 a dozen
# BaDlY FoRMatTed paRT
[foosection]
giraffe : 17
elephant: green
# Yummy section
[unfinished section
[barsection ]
3.14159 :pi
eee : 2.71
ghoti : phish
# Really important section!
syntaxerror
[ bazsection ]
airplane: bahamas
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Oct 21 14:36:33 2006