--- /dev/null
+// libmormegil/stlfgets.hh
+//
+// In jurisdictions where this file would be adjuged to contain copyrightable
+// material, it is copyright 2011 Martin Read, and released to the public
+// under the terms of the Creative Commons Public Domain Dedication (cc-0).
+// It is provided without any warranty, express or implied.
+
+#include <stdio.h>
+#include <string>
+
+namespace libmormegil
+{
+ std::string *tagify(const char *name, const char *prefix);
+ // By default, the generated path is not namespaced. Please note that this
+ // function has no bounds checks and no return value; it's your job to pass
+ // it sensible strings and FILE * objects, and to close them when you're
+ // done. It has default arguments for damage limitation.
+ void emit_chebyshev_spiral(FILE *srcfile = stdout, FILE *hdrfile = stdout, unsigned int radius = 10,
+ const char *macrotag = "cheby_spiral", const char *nmsp = 0);
+}
+
+// vim:ts=8:sw=4:expandtab:fo=croq
--- /dev/null
+.TH "LIBMORMEGIL::EMIT_CHEBYSHEV_SPIRAL" 3 "April 26, 2011" "libmormegil Version 2.0" "libmormegil User Manual"
+.SH NAME
+libmormegil::emit_chebyshev_spiral \- print out source and header files for a chebyshev-metric spiral
+.SH SYNOPSIS
+#include <libmormegil/srcgen-parts.hh>
+
+void libmormegil::emit_chebyshev_spiral(FILE *srcfile, FILE *hdrfile, unsigned int radius, const char *macrotag, const char *nmsp);
+
+.SH DESCRIPTION
+
+.I libmormegil::emit_chebyshev_spiral
+prints a C++ source file via the \fIFILE\fP object pointed to by \fIsrcfile\fP
+and a C++ header file via the \fIFILE\fP object point to by \fIhdrfile\fP.
+
+These output files describe the steps of a discrete spiral of radius
+.I radius
+under a Chebyshev metric, formatted as an array of (2 * radius + 1)^2 objects
+of type \fIlibmormegil::Offset\fP. The array is named \fIcheby_spiral\fP and
+can optionally be placed into a C++ namespace by passing a non-null pointer to
+a non-empty C-style string as the argument \fInmsp\fP (which is null by
+default). The character string pointed to by \fImacrotag\fP (default:
+"cheby_spiral") is used as part of the include-guard macro string in the
+emitted header file.
+
+.SH CAVEATS
+
+Does not check its inputs. The caller has responsiblity for managing the
+objects pointed to by \fIsrcfile\fP and \fIhdrfile\fP, and for sanitizing the
+strings passed as \fImacrotag\fP and \fInmsp\fP.
+
+If you find yourself wanting a spiral larger than radius 20 or so, you may want
+to re-evaluate the algorithm you were going to use it with.
+
+.SH AUTHOR
+Martin Read <mpread@chiark.greenend.org.uk>
+
+.SH SEE ALSO
+
+libmormegil(3)
--- /dev/null
+.TH "LIBMORMEGIL::TAGIFY" 3 "April 26, 2011" "libmormegil Version 2.0" "libmormegil User Manual"
+.SH NAME
+libmormegil::tagify \- generate a "tag" string from a name and a prefix
+.SH SYNOPSIS
+#include <libmormegil/srcgen-parts.hh>
+
+std::string * libmormegil::tagify(const char *name, const char *prefix);
+
+.SH DESCRIPTION
+
+.I libmormegil::tagify
+allocates a new \fIstd::string\fP object created from the C-style string
+pointed to by \fIprefix\fP, then appends the characters of \fIname\fP in
+order, transformed as follows:
+
+.IP * 4
+Values outside the range 33-126 are replaced with underscore (ASCII 0x5F)
+.IP * 4
+Decimal digits are unchanged.
+.IP * 4
+Lower-case 'i' (ASCII 0x69) is replaced with upper-case 'I' (ASCII 0x49)
+.IP * 4
+All other characters for which \fIisalpha(3)\fP returns nonzero are replaced
+the result of passing them to \fItoupper(3)\fP.
+.IP * 4
+Any characters not covered by the above are replaced with underscore (ASCII
+0x5F).
+
+.SH CAVEATS
+
+While this function makes a vague attempt to deal with 8-bit encodings, and to
+limit backscatter from the Unicode committee's questionable decisions regarding
+case transformations of the letters I and İ (which mean that if you have mixed
+Turkish and non-Turkish Latin-alphabet text, you cannot safely perform case
+transformations or case-insensitive comparisons!), the tags generated from
+UTF-8 input will not be usable as identifiers in \fIstandards-compliant\fP C or
+C++ programs, as they will contain multiple adjacent underscores.
+
+.SH AUTHOR
+Martin Read <mpread@chiark.greenend.org.uk>
+
+.SH SEE ALSO
+
+libmormegil(3)
--- /dev/null
+// srcgen-parts.cc
+//
+// Copyright 2011 Martin Read. 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. Neither the name of the author nor the names of any other contributors
+// may be used to endorse or promote products derived from this software
+// without their specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR 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.
+
+#include <string.h>
+#include <stdio.h>
+#include <string>
+#include <ctype.h>
+#include <errno.h>
+#include <libmormegil/srcgen-parts.hh>
+
+std::string *libmormegil::tagify(const char *__restrict__ name, const char *__restrict__ prefix)
+{
+ int i;
+ int len = strlen(name);
+ std::string *foo = new std::string(prefix);
+ for (i = 0; i < len; ++i)
+ {
+ if (isalpha(name[i]))
+ {
+ (*foo) += toupper(name[i]);
+ }
+ else if (isdigit(name[i]))
+ {
+ (*foo) += name[i];
+ }
+ else
+ {
+ (*foo) += '_';
+ }
+ }
+ return foo;
+}
+
+enum Edge
+{
+ North_edge, East_edge, South_edge, West_edge
+};
+
+// This next function is used to generate a sequential lookup table for radial effects.
+void libmormegil::emit_chebyshev_spiral(FILE *srcfile, FILE *hdrfile, unsigned int radius,
+ const char *__restrict__ macrotag, const char *__restrict__ nmsp)
+{
+ fputs("/* This file is automatically generated. DO NOT EDIT! */\n\n", srcfile);
+ fputs("/* This file is automatically generated. DO NOT EDIT! */\n\n", hdrfile);
+ fprintf(srcfile, "#define %s_cc\n", macrotag);
+ fprintf(hdrfile, "#ifndef inc_%s_hh\n#define inc_%s_hh\n#include <libmormegil/Coord.hh>\n", macrotag, macrotag);
+ if (nmsp && *nmsp)
+ {
+ fprintf(srcfile, "libmormegil::Offset %s::cheby_spiral[%d * %d] = \n{\n", nmsp,
+ (radius * 2 + 1), (radius * 2 + 1));
+ fprintf(hdrfile, "namespace %s\n{\n ", nmsp);
+ }
+ else
+ {
+ fprintf(srcfile, "libmormegil::Offset cheby_spiral[%d * %d] = \n{\n", nmsp,
+ (radius * 2 + 1), (radius * 2 + 1));
+ }
+ fprintf(hdrfile, "extern libmormegil::Offset cheby_spiral[%d * %d];\n",
+ (radius * 2 + 1), (radius * 2 + 1));
+ int i;
+ int cur_radius = 0;
+ int cur_y = 0;
+ int cur_x = 0;
+ Edge cur_edge = North_edge;
+ for (i = 0; i < ((radius * 2 + 1) * (radius * 2 + 1)); ++i)
+ {
+ fprintf(srcfile, "{ %d, %d },\n", cur_y, cur_x);
+ switch (cur_edge)
+ {
+ case North_edge:
+ if (!cur_radius)
+ {
+ --cur_y;
+ ++cur_radius;
+ }
+ else if (cur_x == cur_radius)
+ {
+ cur_edge = East_edge;
+ ++cur_y;
+ }
+ else
+ {
+ ++cur_x;
+ if (cur_x == 0)
+ {
+ ++cur_radius;
+ --cur_y;
+ }
+ }
+ break;
+ case East_edge:
+ if (cur_y == cur_radius)
+ {
+ cur_edge = South_edge;
+ --cur_x;
+ }
+ else
+ {
+ ++cur_y;
+ }
+ break;
+ case South_edge:
+ if (cur_x == -cur_radius)
+ {
+ cur_edge = West_edge;
+ --cur_y;
+ }
+ else
+ {
+ --cur_x;
+ }
+ break;
+ case West_edge:
+ if (cur_y == -cur_radius)
+ {
+ cur_edge = North_edge;
+ ++cur_x;
+ if (cur_x == 0)
+ {
+ ++cur_radius;
+ --cur_y;
+ }
+ }
+ else
+ {
+ --cur_y;
+ }
+ break;
+ }
+ }
+ fprintf(srcfile, "};\n");
+ if (nmsp && *nmsp)
+ {
+ fprintf(hdrfile, "}\n");
+ }
+ fprintf(hdrfile, "#endif\n");
+}
+
+// vim:ts=8:sw=4:expandtab:fo=croq