Added new functions emit_chebyshev_spiral and tagify (dragged in from dungeonbash...
authorfluffymormegil <mpread@chiark.greenend.org.uk>
Tue, 26 Apr 2011 23:17:06 +0000 (00:17 +0100)
committerfluffymormegil <mpread@chiark.greenend.org.uk>
Tue, 26 Apr 2011 23:17:06 +0000 (00:17 +0100)
include/libmormegil/srcgen-parts.hh [new file with mode: 0644]
man/libmormegil::emit_chebyshev_spiral.3 [new file with mode: 0644]
man/libmormegil::tagify.3 [new file with mode: 0644]
src/srcgen-parts.cc [new file with mode: 0644]

diff --git a/include/libmormegil/srcgen-parts.hh b/include/libmormegil/srcgen-parts.hh
new file mode 100644 (file)
index 0000000..b809a7a
--- /dev/null
@@ -0,0 +1,22 @@
+// 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
diff --git a/man/libmormegil::emit_chebyshev_spiral.3 b/man/libmormegil::emit_chebyshev_spiral.3
new file mode 100644 (file)
index 0000000..5439b60
--- /dev/null
@@ -0,0 +1,39 @@
+.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)
diff --git a/man/libmormegil::tagify.3 b/man/libmormegil::tagify.3
new file mode 100644 (file)
index 0000000..3398140
--- /dev/null
@@ -0,0 +1,44 @@
+.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)
diff --git a/src/srcgen-parts.cc b/src/srcgen-parts.cc
new file mode 100644 (file)
index 0000000..3fc9562
--- /dev/null
@@ -0,0 +1,164 @@
+// 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