Andrei,
Since the perplex/re2c/lemon setup is a bit obtuse from a build system
perspective (which is my fault primarily) I've taken your patch and
adapted it to give you what should be a minimal working setup. The
attached patch, applied to the top level of a clean BRL-CAD trunk
checkout, should result in a src/conv/csg setup that will build.
Applying it to a tree with your existing csg work won't work - it must
be applied to a clean checkout. Study it carefully to see if it makes
sense, and note the changes I made to the CMakeLists.txt file and the
perplex/lemon inputs. If you want to see the details of what commands
it is running to build the various intermediate files, use make
VERBOSE=1 to build.
>From this starting point, if you want to pursue this approach a bit
further, the next step is to make this do something simple. I haven't
altered any of the logic - this is just to try to get you over the
build system hurdles and started with the important bit - the csg
logic. Don't try to preserve all the complexities of what is in the
perplex and lemon files now. Sean's suggestion of a simple adder
would be a good starting point.
CY
Index: src/conv/CMakeLists.txt
===================================================================
--- src/conv/CMakeLists.txt (revision 65039)
+++ src/conv/CMakeLists.txt (working copy)
@@ -12,6 +12,7 @@
add_subdirectory(3dm)
add_subdirectory(gcv)
add_subdirectory(step)
+add_subdirectory(csg)
add_subdirectory(iges)
add_subdirectory(intaval)
Index: src/conv/csg/CMakeLists.txt
===================================================================
--- src/conv/csg/CMakeLists.txt (revision 0)
+++ src/conv/csg/CMakeLists.txt (working copy)
@@ -0,0 +1,36 @@
+set(CSG_INCLUDE_DIRS
+ ${GCV_INCLUDE_DIRS}
+ ${BU_INCLUDE_DIRS}
+ )
+BRLCAD_INCLUDE_DIRS(CSG_INCLUDE_DIRS)
+
+# Also want local dirs
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+
+PERPLEX_TARGET(csg_scanner csg_scanner.perplex
+ ${CMAKE_CURRENT_BINARY_DIR}/csg_scanner.c
+ ${CMAKE_CURRENT_BINARY_DIR}/csg_scanner.h)
+LEMON_TARGET(csg_parser csg_parser.lemon
+ ${CMAKE_CURRENT_BINARY_DIR}/csg_parser.c
+ ${CMAKE_CURRENT_BINARY_DIR}/csg_parser.h)
+ADD_PERPLEX_LEMON_DEPENDENCY(csg_scanner csg_parser)
+
+set(CSG_SRCS
+ csg.c
+ ${CMAKE_CURRENT_BINARY_DIR}/csg_scanner.c
+ ${CMAKE_CURRENT_BINARY_DIR}/csg_parser.c
+ )
+
+BRLCAD_ADDEXEC(csg "${CSG_SRCS}" "libgcv;libbu" NO_INSTALL)
+
+CMAKEFILES(csg.h)
+
+# Local Variables:
+# tab-width: 8
+# mode: cmake
+# indent-tabs-mode: t
+# End:
+# ex: shiftwidth=2 tabstop=8
Property changes on: src/conv/csg/CMakeLists.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: src/conv/csg/csg.c
===================================================================
--- src/conv/csg/csg.c (revision 0)
+++ src/conv/csg/csg.c (working copy)
@@ -0,0 +1,84 @@
+/* D O M 2 D O X . C
+ * BRL-CAD
+ *
+ * Copyright (c) 2013 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file csg.c
+ *
+ * Brief description
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "csg.h"
+
+static void *
+parse_alloc(size_t size)
+{
+ return bu_malloc(size, "parse_alloc");
+}
+
+int
+main(int argc, char *argv[])
+{
+ FILE *inputFile, *outputFile;
+ void *parser;
+ int tokenID;
+ perplex_t scanner;
+ token_t *tokenData;
+ app_data_t appData;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s input output", argv[0]);
+ exit(1);
+ }
+
+ inputFile = fopen(argv[1], "r");
+ outputFile = fopen(argv[2], "w");
+
+ scanner = perplexFileScanner(inputFile);
+ perplexSetExtra(scanner, &appData);
+ appData.outfile = outputFile;
+ appData.doc_comment = 0;
+ appData.tag_text = 0;
+ appData.example_text = 0;
+ appData.return_text = 0;
+ bu_vls_init(&appData.description);
+ bu_vls_init(&appData.tags);
+
+ parser = ParseAlloc(parse_alloc);
+
+ BU_GET(tokenData, token_t);
+ bu_vls_init(&tokenData->value);
+ appData.tokenData = tokenData;
+
+ while ((tokenID = yylex(scanner)) != YYEOF) {
+ Parse(parser, tokenID, tokenData, &appData);
+ BU_GET(tokenData, token_t);
+ bu_vls_init(&tokenData->value);
+ appData.tokenData = tokenData;
+ }
+ Parse(parser, 0, tokenData, &appData);
+
+ ParseFree(parser, free);
+ perplexFree(scanner);
+ fclose(inputFile);
+ fclose(outputFile);
+
+ return 0;
+}
Property changes on: src/conv/csg/csg.c
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/conv/csg/csg.h
===================================================================
--- src/conv/csg/csg.h (revision 0)
+++ src/conv/csg/csg.h (working copy)
@@ -0,0 +1,73 @@
+/* D O M 2 D O X . H
+ * BRL-CAD
+ *
+ * Copyright (c) 2013 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file csg.h
+ *
+ * Brief description
+ *
+ */
+
+#ifndef ON2JAVA_H
+#define ON2JAVA_H
+
+#include "common.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "bu.h"
+
+typedef struct {
+ struct bu_vls value;
+} token_t;
+
+typedef struct {
+ token_t *tokenData;
+ FILE *outfile;
+ int comment_type;
+ int doc_comment;
+ int tag_text;
+ int example_text;
+ int return_text;
+ struct bu_vls description;
+ struct bu_vls tags;
+} app_data_t;
+
+/* lemon prototypes */
+void *ParseAlloc(void *(*mallocProc)(size_t));
+void ParseFree(void *parser, void (*freeProc)(void *));
+void Parse(void *yyp, int yymajor, token_t *tokenData, app_data_t *appData);
+void ParseTrace(FILE *fp, char *s);
+
+/* definitions generated by lemon */
+#include "csg_parser.h"
+
+#define PERPLEX_ON_ENTER \
+ app_data_t *appData = (app_data_t *)yyextra; \
+ token_t *tokenData = appData->tokenData;
+
+/* definitions generated by perplex */
+#include "csg_scanner.h"
+
+/* utils */
+#define END_EXAMPLE \
+if (appData->example_text) { \
+ bu_vls_strcat(&appData->description, "\n\\endcode\n\n"); \
+ appData->example_text = 0; \
+}
+
+#endif
Property changes on: src/conv/csg/csg.h
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/conv/csg/csg_parser.lemon
===================================================================
--- src/conv/csg/csg_parser.lemon (revision 0)
+++ src/conv/csg/csg_parser.lemon (working copy)
@@ -0,0 +1,223 @@
+/* C S G _ P A R S E R . L E M O N
+ * BRL-CAD
+ *
+ * Copyright (c) 2013 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+
+%include {
+#include <assert.h>
+#include <string.h>
+#include "csg.h"
+
+#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) && !defined(__clang__)
+# pragma GCC diagnostic ignored "-Wunused-variable"
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wunused-variable"
+# pragma clang diagnostic ignored "-Wunused-parameter"
+#endif
+
+}
+
+%token_type {token_t *}
+%extra_argument {app_data_t *appData}
+
+%right CODE_TEXT COMMENT_TEXT PARAM_TEXT.
+%right CPP_COMMENT_START C_COMMENT_START.
+
+start_symbol ::= source.
+
+source ::= /* empty */.
+source ::= source block.
+
+block ::= code.
+block ::= doc_comment.
+
+code ::= code_text. [CODE_TEXT]
+
+doc_comment ::= c_doc_comment.
+{
+ END_EXAMPLE;
+ appData->return_text = 0;
+ if (appData->doc_comment) {
+ fprintf(appData->outfile, "/**");
+ fprintf(appData->outfile, "%s", bu_vls_addr(&appData->description));
+ fprintf(appData->outfile, "%s\n", bu_vls_addr(&appData->tags));
+ fprintf(appData->outfile, "*/\n");
+ }
+ appData->doc_comment = 0;
+ bu_vls_trunc(&appData->description, 0);
+ bu_vls_trunc(&appData->tags, 0);
+}
+
+doc_comment ::= cpp_doc_comment. [CPP_COMMENT_START]
+{
+ END_EXAMPLE;
+ appData->return_text = 0;
+ if (appData->doc_comment) {
+ fprintf(appData->outfile, "/**");
+ fprintf(appData->outfile, "%s", bu_vls_addr(&appData->description));
+ fprintf(appData->outfile, "%s\n", bu_vls_addr(&appData->tags));
+ fprintf(appData->outfile, "*/\n");
+ }
+ appData->doc_comment = 0;
+ bu_vls_trunc(&appData->description, 0);
+ bu_vls_trunc(&appData->tags, 0);
+}
+
+c_doc_comment ::= C_COMMENT_START C_COMMENT_END.
+c_doc_comment ::= C_COMMENT_START doc_text C_COMMENT_END.
+
+cpp_doc_comment ::= cpp_doc_line.
+cpp_doc_comment ::= cpp_doc_comment cpp_doc_line.
+
+cpp_doc_line ::= CPP_COMMENT_START CPP_COMMENT_END.
+cpp_doc_line ::= CPP_COMMENT_START doc_text CPP_COMMENT_END.
+{
+ size_t len = bu_vls_strlen(&appData->description);
+
+ if (len == 0 || bu_vls_addr(&appData->description)[len - 1] != '\n') {
+ bu_vls_putc(&appData->description, '\n');
+ }
+}
+
+doc_text ::= doc_component.
+doc_text ::= doc_text doc_component.
+
+doc_component ::= comment_text. [COMMENT_TEXT]
+doc_component ::= doc_specific_text.
+{
+ appData->doc_comment = 1;
+}
+
+doc_specific_text ::= DESCRIPTION_START.
+{
+ appData->tag_text = 0;
+ appData->return_text = 0;
+ END_EXAMPLE;
+}
+
+doc_specific_text ::= EXAMPLE_START.
+{
+ bu_vls_strcat(&appData->description, "\n###Example\n\n\\code");
+ appData->tag_text = 0;
+ appData->return_text = 0;
+ appData->example_text = 1;
+}
+
+doc_specific_text ::= REMARKS_START.
+{
+ END_EXAMPLE;
+ bu_vls_strcat(&appData->description, "\n###Note\n");
+ appData->tag_text = 0;
+ appData->return_text = 0;
+}
+
+doc_specific_text ::= PARAMS_START.
+{
+ appData->tag_text = 0;
+ appData->return_text = 0;
+ END_EXAMPLE;
+}
+
+doc_specific_text ::= RETURNS_START.
+{
+ END_EXAMPLE;
+ bu_vls_strcat(&appData->tags, "@return ");
+ appData->tag_text = 1;
+ appData->return_text = 1;
+}
+
+doc_specific_text ::= SEE_ALSO_START.
+{
+ END_EXAMPLE;
+ bu_vls_strcat(&appData->tags, "@see ");
+ appData->tag_text = 1;
+ appData->return_text = 0;
+}
+
+doc_specific_text ::= param_name.
+doc_specific_text ::= param_text. [PARAM_TEXT]
+
+param_name ::= PARAM_NAME(A).
+{
+ bu_vls_printf(&appData->tags, "\n@param %s ", bu_vls_addr(&A->value));
+ bu_vls_free(&A->value);
+ BU_PUT(A, token_t);
+}
+
+param_text ::= param_text_fragment.
+param_text ::= param_text param_text_fragment.
+
+param_text_fragment ::= PARAM_TEXT(A).
+{
+ bu_vls_strcat(&appData->tags, bu_vls_addr(&A->value));
+ bu_vls_free(&A->value);
+ BU_PUT(A, token_t);
+}
+
+code_text ::= code_text_fragment.
+code_text ::= code_text code_text_fragment.
+code_text_fragment ::= CODE_TEXT(A). {
+ END_EXAMPLE;
+ fprintf(appData->outfile, "%s", bu_vls_addr(&A->value));
+ bu_vls_free(&A->value);
+ BU_PUT(A, token_t);
+}
+
+comment_text ::= comment_text_fragment.
+comment_text ::= comment_text comment_text_fragment.
+comment_text_fragment ::= COMMENT_TEXT(A). {
+ if (appData->tag_text) {
+ if (appData->return_text) {
+ size_t i, len = bu_vls_strlen(&A->value);
+ char *frag = bu_vls_addr(&A->value);
+ struct bu_vls tmp;
+ bu_vls_init(&tmp);
+
+ /* turn newlines into line breaks */
+ for (i = 0; i < len; ++i) {
+ if (frag[i] == '\n') {
+ bu_vls_strcat(&tmp, "<br />");
+ } else {
+ bu_vls_putc(&tmp, frag[i]);
+ }
+ }
+ bu_vls_vlscat(&appData->tags, &tmp);
+ bu_vls_free(&tmp);
+ } else {
+ bu_vls_strcat(&appData->tags, bu_vls_addr(&A->value));
+ }
+ } else {
+ if (bu_vls_strlen(&appData->description) == 0) {
+ size_t i, len = bu_vls_strlen(&A->value);
+ char *frag = bu_vls_addr(&A->value);
+
+ /* omit leading ws from description */
+ i = strspn(frag, " \t");
+ if (i < len) {
+ bu_vls_strcat(&appData->description, &frag[i]);
+ }
+ } else {
+ bu_vls_strcat(&appData->description, bu_vls_addr(&A->value));
+ }
+ }
+ bu_vls_free(&A->value);
+ BU_PUT(A, token_t);
+}
+
Index: src/conv/csg/csg_scanner.perplex
===================================================================
--- src/conv/csg/csg_scanner.perplex (revision 0)
+++ src/conv/csg/csg_scanner.perplex (working copy)
@@ -0,0 +1,220 @@
+/* D O M 2 D O X _ S C A N N E R . P E R P L E X
+ * BRL-CAD
+ *
+ * Copyright (c) 2013 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+
+/* perplex input file */
+#include "csg.h"
+
+/* condition states */
+enum {INITIAL, code, c_comment, cpp_comment, param_text};
+
+%%
+<> => code { continue; }
+
+cpp_comment_lead = '/''/'+;
+c_comment_lead = '/'?'*'+;
+c_comment_end = '*'+'/';
+optional_ws = [ \t]*;
+comment_lead = ((cpp_comment_lead)|(c_comment_lead));
+
+<code> {
+(optional_ws)(cpp_comment_lead) {
+ YYSETCONDITION(cpp_comment);
+ appData->comment_type = cpp_comment;
+ return CPP_COMMENT_START;
+}
+(optional_ws)'/''*'+ {
+ YYSETCONDITION(c_comment);
+ appData->comment_type = c_comment;
+ return C_COMMENT_START;
+}
+[^] {
+ bu_vls_putc(&tokenData->value, yytext[0]);
+ return CODE_TEXT;
+}
+}
+
+<c_comment> {
+'\n'(optional_ws)(c_comment_end)(optional_ws) {
+ YYSETCONDITION(code);
+ return C_COMMENT_END;
+}
+'\n'(optional_ws) {
+ bu_vls_putc(&tokenData->value, '\n');
+ return COMMENT_TEXT;
+}
+(optional_ws)(c_comment_end)(optional_ws) {
+ YYSETCONDITION(code);
+ return C_COMMENT_END;
+}
+}
+
+<cpp_comment> {
+'\n'(optional_ws)(cpp_comment_lead)(optional_ws) {
+ /* remove leads from lines */
+ bu_vls_putc(&tokenData->value, '\n');
+ return COMMENT_TEXT;
+}
+'\n'(optional_ws) {
+ YYSETCONDITION(code);
+ return CPP_COMMENT_END;
+}
+}
+
+<c_comment,cpp_comment> {
+'\n'(optional_ws)(c_comment_lead)(optional_ws) {
+ if (YYGETCONDITION == cpp_comment) {
+ YYSETCONDITION(code);
+ return CPP_COMMENT_END;
+ }
+ /* remove leads from lines */
+ bu_vls_putc(&tokenData->value, '\n');
+ return COMMENT_TEXT;
+}
+[ \t]+ {
+ /* condense ws */
+ bu_vls_putc(&tokenData->value, ' ');
+ return COMMENT_TEXT;
+}
+[^] {
+ bu_vls_putc(&tokenData->value, yytext[0]);
+ return COMMENT_TEXT;
+}
+}
+
+<c_comment,cpp_comment,param_text> {
+(optional_ws)(comment_lead)?(optional_ws)"Description"':'?(optional_ws) {
+ if (YYGETCONDITION == param_text) {
+ YYSETCONDITION(appData->comment_type);
+ }
+ return DESCRIPTION_START;
+}
+(optional_ws)(comment_lead)?(optional_ws)"Example"':'?(optional_ws) {
+ if (YYGETCONDITION == param_text) {
+ YYSETCONDITION(appData->comment_type);
+ }
+ return EXAMPLE_START;
+}
+(optional_ws)(comment_lead)?(optional_ws)"Remarks"':'?(optional_ws) {
+ if (YYGETCONDITION == param_text) {
+ YYSETCONDITION(appData->comment_type);
+ }
+ return REMARKS_START;
+}
+(optional_ws)(comment_lead)?(optional_ws)"Param"'e'?"ters"[:;]?(optional_ws) {
+ YYSETCONDITION(param_text);
+ return PARAMS_START;
+}
+(optional_ws)(comment_lead)?(optional_ws)("Returns"|"Result")':'(optional_ws) {
+ if (YYGETCONDITION == param_text) {
+ YYSETCONDITION(appData->comment_type);
+ }
+ return RETURNS_START;
+}
+(optional_ws)(comment_lead)?(optional_ws)"See Also"':'?(optional_ws) {
+ if (YYGETCONDITION == param_text) {
+ YYSETCONDITION(appData->comment_type);
+ }
+ return SEE_ALSO_START;
+}
+}
+
+<param_text> {
+'\n'(optional_ws)(comment_lead)?(optional_ws)[_a-zA-Z][_a-zA-Z0-9]*[ \t]*"-" {
+ size_t i, start, end;
+
+ /* trim everything but the actual name */
+ start = end = 0;
+ for (i = 0; start == 0 && i < strlen(yytext); ++i) {
+ switch (yytext[i]) {
+ case ' ':
+ case '\t':
+ case '/':
+ case '*':
+ break;
+ default:
+ start = i;
+ }
+ }
+ for (i = strlen(yytext) - 1; end == 0 && i >= start; --i) {
+ switch (yytext[i]) {
+ case ' ':
+ case '\t':
+ case '-':
+ break;
+ default:
+ end = i;
+ }
+ }
+ bu_vls_putc(&tokenData->value, '\n');
+ bu_vls_strncat(&tokenData->value, &yytext[start], end - start + 1);
+
+ return PARAM_NAME;
+}
+'\n'(optional_ws)(comment_lead)(optional_ws) {
+ int i, start, end;
+
+ /* trim everything but the indent ws */
+ end = strlen(yytext);
+ start = 0;
+ for (i = end - 1; start == 0 && i >= 0; --i) {
+ switch (yytext[i]) {
+ case ' ':
+ case '\t':
+ break;
+ default:
+ start = i + 1;
+ }
+ }
+ bu_vls_putc(&tokenData->value, '\n');
+ bu_vls_strncat(&tokenData->value, &yytext[start], end - start + 1);
+
+ return PARAM_TEXT;
+}
+'\n'(optional_ws)(c_comment_end)(optional_ws) {
+ if (appData->comment_type == c_comment) {
+ YYSETCONDITION(code);
+ return C_COMMENT_END;
+ }
+ bu_vls_strcat(&tokenData->value, yytext);
+ return PARAM_TEXT;
+}
+'\n'(optional_ws) {
+ if (appData->comment_type == cpp_comment) {
+ /* in a cpp style comment, a newline not followed by another cpp
+ * comment line ends the comment and the parameter text
+ */
+ YYSETCONDITION(code);
+ return CPP_COMMENT_END;
+ }
+ bu_vls_putc(&tokenData->value, '\n');
+ return PARAM_TEXT;
+}
+(optional_ws)(c_comment_end) {
+ if (appData->comment_type == c_comment) {
+ YYSETCONDITION(code);
+ return C_COMMENT_END;
+ }
+}
+[^] {
+ bu_vls_putc(&tokenData->value, yytext[0]);
+
+ return PARAM_TEXT;
+}
+}
------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
BRL-CAD Developer mailing list
brlcad-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/brlcad-devel