source: branches/help/ARBDB/adperl.cxx

Last change on this file was 18303, checked in by westram, 5 years ago
  • enforce destruction order of shell created via GB_shell4perl and GB_test_shell_closed by storing the former in the latter
    • move code from ~GB_shell4perl into close_global_shell.
    • call close_global_shell either from ~GB_shell4perl or from ~GB_test_shell_closed.
    • fixes #508
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : adperl.cxx                                        //
4//   Purpose   : helper functions used by perl interface           //
5//               (see ../PERL2ARB)                                 //
6//                                                                 //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "gb_local.h"
13#include "adperl.h"
14
15// used by perl interface, see ../PERL2ARB/ARB_ext.c@GBP_croak_function
16void (*GBP_croak_function)(const char *message) = NULp;
17
18static void die(const char *with_last_words) {
19    // raise exception in caller (assuming caller is a perl script)
20
21    if (GBP_croak_function) {
22        GBP_croak_function(with_last_words);
23    }
24    else {
25        fputs("Warning: GBP_croak_function undefined. terminating..\n", stderr);
26        GBK_terminate(with_last_words);
27    }
28}
29
30// -------------------------------------------
31//      "generic" enum<->string-conversion
32
33union known_enum {
34    int as_int;
35
36    GB_SEARCH_TYPE    search_type;
37    GB_CASE           case_sensitivity;
38    GB_TYPES          db_type;
39    GB_UNDO_TYPE      undo_type;
40    GB_alignment_type ali_type;
41};
42
43#define ILLEGAL_VALUE (-666)
44
45
46typedef const char *(*enum2string)(known_enum enumValue);
47
48static known_enum next_known_enum_value(known_enum greaterThan, enum2string lookup) {
49    known_enum enumValue, lookupLimit;
50
51    enumValue.as_int   = greaterThan.as_int+1;
52    lookupLimit.as_int = enumValue.as_int+256;
53
54    while (enumValue.as_int <= lookupLimit.as_int) {
55        const char *valueExists = lookup(enumValue);
56        if (valueExists) return enumValue;
57        enumValue.as_int++;
58    }
59
60    enumValue.as_int = ILLEGAL_VALUE;
61    return enumValue;
62}
63
64static known_enum first_known_enum_value(known_enum greaterEqualThan, enum2string lookup) {
65    return (lookup(greaterEqualThan))
66        ? greaterEqualThan
67        : next_known_enum_value(greaterEqualThan, lookup);
68}
69
70static known_enum string2enum(const char *string, enum2string lookup, known_enum start) {
71
72    for (start = first_known_enum_value(start, lookup);
73         start.as_int != ILLEGAL_VALUE;
74         start = next_known_enum_value(start, lookup))
75    {
76        const char *asString = lookup(start);
77        gb_assert(asString);
78        if (strcasecmp(asString, string) == 0) break; // found
79    }
80    return start;
81}
82
83static char *buildAllowedValuesString(known_enum start, enum2string lookup) {
84    char *allowed = NULp;
85
86    for (start = first_known_enum_value(start, lookup);
87         start.as_int != ILLEGAL_VALUE;
88         start = next_known_enum_value(start, lookup))
89    {
90        const char *asString = lookup(start);
91        gb_assert(asString);
92
93        if (allowed) freeset(allowed, GBS_global_string_copy("%s, '%s'", allowed, asString));
94        else allowed = GBS_global_string_copy("'%s'", asString);
95    }
96
97    if (!allowed) allowed = ARB_strdup("none (this is a bug)");
98
99    return allowed;
100}
101
102static known_enum string2enum_or_die(const char *enum_name, const char *string, enum2string lookup, known_enum start) {
103    known_enum found = string2enum(string, lookup, start);
104
105    if (found.as_int == ILLEGAL_VALUE) {
106        char *allowed_values = buildAllowedValuesString(start, lookup);
107        char *usage          = GBS_global_string_copy("Error: value '%s' is not a legal %s\n"
108                                                      "Known %ss are: %s",
109                                                      string, enum_name, enum_name, allowed_values);
110        free(allowed_values);
111        die(usage);
112    }
113
114    return found;
115}
116
117/* --------------------------------------------------------------------------------
118 * conversion declarations for different used enums
119 *
120 * To add a new enum type
121 * - write a function to convert your enum-values into a string (example: GBP_gb_search_types_to_string)
122 * - write a reverse-wrapper                                    (example: GBP_string_to_gb_search_types)
123 *
124 * [Code-Tag: enum_conversion_functions]
125 * see also ../PERLTOOLS/arb_proto_2_xsub.cxx@enum_type_replacement
126 */
127
128// ------------------------
129//      GB_SEARCH_TYPE
130
131const char *GBP_GB_SEARCH_TYPE_2_charPtr(GB_SEARCH_TYPE search_type) {
132    switch (search_type) {
133        case SEARCH_BROTHER:       return "brother";
134        case SEARCH_CHILD:         return "child";
135        case SEARCH_GRANDCHILD:    return "grandchild";
136        case SEARCH_NEXT_BROTHER:  return "next_brother";
137        case SEARCH_CHILD_OF_NEXT: return "child_of_next";
138    }
139
140    return NULp;
141}
142
143GB_SEARCH_TYPE GBP_charPtr_2_GB_SEARCH_TYPE(const char *search_mode) {
144    known_enum start; start.as_int = 0;
145    known_enum found  = string2enum_or_die("search-type", search_mode, CASTSIG(enum2string, GBP_GB_SEARCH_TYPE_2_charPtr), start);
146    return found.search_type;
147}
148
149// ------------------
150//      GB_TYPES
151
152const char *GBP_GB_TYPES_2_charPtr(GB_TYPES type) {
153    switch (type) {
154        case GB_NONE:   return "NONE";
155        case GB_BIT:    return "BIT";
156        case GB_BYTE:   return "BYTE";
157        case GB_INT:    return "INT";
158        case GB_FLOAT:  return "FLOAT";
159        case GB_BITS:   return "BITS";
160        case GB_BYTES:  return "BYTES";
161        case GB_INTS:   return "INTS";
162        case GB_FLOATS: return "FLOATS";
163        case GB_STRING: return "STRING";
164        case GB_DB:     return "CONTAINER";
165
166        default: break;
167    }
168    return NULp;
169}
170
171GB_TYPES GBP_charPtr_2_GB_TYPES(const char *type_name) {
172    known_enum start; start.as_int = 0;
173    known_enum found  = string2enum_or_die("db-type", type_name, CASTSIG(enum2string, GBP_GB_TYPES_2_charPtr), start);
174    return found.db_type;
175}
176
177
178// ----------------------
179//      GB_UNDO_TYPE
180
181const char *GBP_GB_UNDO_TYPE_2_charPtr(GB_UNDO_TYPE undo_type) {
182    switch (undo_type) {
183        case GB_UNDO_UNDO: return "undo";
184        case GB_UNDO_REDO: return "redo";
185
186        case GB_UNDO_NONE:
187        case GB_UNDO_KILL:
188        case GB_UNDO_UNDO_REDO:
189            break;
190    }
191    return NULp;
192}
193
194GB_UNDO_TYPE GBP_charPtr_2_GB_UNDO_TYPE(const char *undo_type) {
195    known_enum start; start.as_int = 0;
196    known_enum found  = string2enum_or_die("undo-type", undo_type, CASTSIG(enum2string, GBP_GB_UNDO_TYPE_2_charPtr), start);
197    return found.undo_type;
198}
199
200
201// -----------------
202//      GB_CASE
203
204const char *GBP_GB_CASE_2_charPtr(GB_CASE sensitivity) {
205    switch (sensitivity) {
206        case GB_IGNORE_CASE:    return "ignore_case";
207        case GB_MIND_CASE:      return "mind_case";
208        case GB_CASE_UNDEFINED: return "case_undef";
209    }
210    return NULp;
211}
212
213GB_CASE GBP_charPtr_2_GB_CASE(const char *sensitivity) {
214    known_enum start; start.as_int = 0;
215    known_enum found  = string2enum_or_die("sensitivity", sensitivity, CASTSIG(enum2string, GBP_GB_CASE_2_charPtr), start);
216    return found.case_sensitivity;
217}
218
219// ---------------------------
220//      GB_alignment_type
221
222const char *GBP_GB_alignment_type_2_charPtr(GB_alignment_type ali_type) {
223    switch (ali_type) {
224        case GB_AT_RNA: return "RNA";
225        case GB_AT_DNA: return "DNA";
226        case GB_AT_AA:  return "AMINO";
227
228        case GB_AT_UNKNOWN: break;
229    }
230    return NULp;
231}
232
233GB_alignment_type GBP_charPtr_2_GB_alignment_type(const char *ali_type) {
234    known_enum start; start.as_int = 0;
235    known_enum found  = string2enum_or_die("alignment-type", ali_type, CASTSIG(enum2string, GBP_GB_alignment_type_2_charPtr), start);
236    return found.ali_type;
237}
238
239// -----------------------------------------
240//      wrap functions moved to CORE lib
241//
242// As long as CORE lib is not xsub'd, we use wrappers for some
243// functions used in perl
244
245GB_ERROR GBC_await_error() {
246    return GB_await_error();
247}
248
249// --------------------
250//      perl panic
251
252void GBP_prepare_to_die() {
253    // called from die() in ../PERL2ARB/ARB.pm@prepare_to_die
254    gb_abort_and_close_all_DBs();
255}
256
Note: See TracBrowser for help on using the repository browser.