source: tags/ms_r16q2/ARBDB/adperl.cxx

Last change on this file was 12888, checked in by westram, 10 years ago
  • fix #603
    • abort all TAs and close all DBs
      • in arb-perl death-handler
      • on exit (i.e. perl scripts will now abort unclosed TAs - not sure whether they did commit b4)
  • 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) = NULL;
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
30GB_shell4perl::~GB_shell4perl() {
31    gb_abort_and_close_all_DBs();
32}
33
34// -------------------------------------------
35//      "generic" enum<->string-conversion
36
37union known_enum {
38    int as_int;
39
40    GB_SEARCH_TYPE    search_type;
41    GB_CASE           case_sensitivity;
42    GB_TYPES          db_type;
43    GB_UNDO_TYPE      undo_type;
44    GB_alignment_type ali_type;
45};
46
47#define ILLEGAL_VALUE (-666)
48
49
50typedef const char *(*enum2string)(known_enum enumValue);
51
52static known_enum next_known_enum_value(known_enum greaterThan, enum2string lookup) {
53    known_enum enumValue, lookupLimit;
54
55    enumValue.as_int   = greaterThan.as_int+1;
56    lookupLimit.as_int = enumValue.as_int+256;
57
58    while (enumValue.as_int <= lookupLimit.as_int) {
59        const char *valueExists = lookup(enumValue);
60        if (valueExists) return enumValue;
61        enumValue.as_int++;
62    }
63
64    enumValue.as_int = ILLEGAL_VALUE;
65    return enumValue;
66}
67
68static known_enum first_known_enum_value(known_enum greaterEqualThan, enum2string lookup) {
69    return (lookup(greaterEqualThan))
70        ? greaterEqualThan
71        : next_known_enum_value(greaterEqualThan, lookup);
72}
73
74static known_enum string2enum(const char *string, enum2string lookup, known_enum start) {
75
76    for (start = first_known_enum_value(start, lookup);
77         start.as_int != ILLEGAL_VALUE;
78         start = next_known_enum_value(start, lookup))
79    {
80        const char *asString = lookup(start);
81        gb_assert(asString);
82        if (strcasecmp(asString, string) == 0) break; // found
83    }
84    return start;
85}
86
87static char *buildAllowedValuesString(known_enum start, enum2string lookup) {
88    char *allowed = NULL;
89
90    for (start = first_known_enum_value(start, lookup);
91         start.as_int != ILLEGAL_VALUE;
92         start = next_known_enum_value(start, lookup))
93    {
94        const char *asString = lookup(start);
95        gb_assert(asString);
96
97        if (allowed) freeset(allowed, GBS_global_string_copy("%s, '%s'", allowed, asString));
98        else allowed = GBS_global_string_copy("'%s'", asString);
99    }
100
101    if (!allowed) allowed = strdup("none (this is a bug)");
102
103    return allowed;
104}
105
106static known_enum string2enum_or_die(const char *enum_name, const char *string, enum2string lookup, known_enum start) {
107    known_enum found = string2enum(string, lookup, start);
108
109    if (found.as_int == ILLEGAL_VALUE) {
110        char *allowed_values = buildAllowedValuesString(start, lookup);
111        char *usage          = GBS_global_string_copy("Error: value '%s' is not a legal %s\n"
112                                                      "Known %ss are: %s",
113                                                      string, enum_name, enum_name, allowed_values);
114        free(allowed_values);
115        die(usage);
116    }
117
118    return found;
119}
120
121/* --------------------------------------------------------------------------------
122 * conversion declarations for different used enums
123 *
124 * To add a new enum type
125 * - write a function to convert your enum-values into a string (example: GBP_gb_search_types_to_string)
126 * - write a reverse-wrapper                                    (example: GBP_string_to_gb_search_types)
127 *
128 * [Code-Tag: enum_conversion_functions]
129 * see also ../PERLTOOLS/arb_proto_2_xsub.cxx@enum_type_replacement
130 */
131
132// ------------------------
133//      GB_SEARCH_TYPE
134
135const char *GBP_GB_SEARCH_TYPE_2_charPtr(GB_SEARCH_TYPE search_type) {
136    switch (search_type) {
137        case SEARCH_BROTHER:       return "brother";
138        case SEARCH_CHILD:         return "child";
139        case SEARCH_GRANDCHILD:    return "grandchild";
140        case SEARCH_NEXT_BROTHER:  return "next_brother";
141        case SEARCH_CHILD_OF_NEXT: return "child_of_next";
142    }
143
144    return NULL;
145}
146
147GB_SEARCH_TYPE GBP_charPtr_2_GB_SEARCH_TYPE(const char *search_mode) {
148    known_enum start; start.as_int = 0;
149    known_enum found  = string2enum_or_die("search-type", search_mode, (enum2string)GBP_GB_SEARCH_TYPE_2_charPtr, start);
150    return found.search_type;
151}
152
153// ------------------
154//      GB_TYPES
155
156const char *GBP_GB_TYPES_2_charPtr(GB_TYPES type) {
157    switch (type) {
158        case GB_NONE:   return "NONE";
159        case GB_BIT:    return "BIT";
160        case GB_BYTE:   return "BYTE";
161        case GB_INT:    return "INT";
162        case GB_FLOAT:  return "FLOAT";
163        case GB_BITS:   return "BITS";
164        case GB_BYTES:  return "BYTES";
165        case GB_INTS:   return "INTS";
166        case GB_FLOATS: return "FLOATS";
167        case GB_STRING: return "STRING";
168        case GB_DB:     return "CONTAINER";
169
170        default: break;
171    }
172    return NULL;
173}
174
175GB_TYPES GBP_charPtr_2_GB_TYPES(const char *type_name) {
176    known_enum start; start.as_int = 0;
177    known_enum found  = string2enum_or_die("db-type", type_name, (enum2string)GBP_GB_TYPES_2_charPtr, start);
178    return found.db_type;
179}
180
181
182// ----------------------
183//      GB_UNDO_TYPE
184
185const char *GBP_GB_UNDO_TYPE_2_charPtr(GB_UNDO_TYPE undo_type) {
186    switch (undo_type) {
187        case GB_UNDO_UNDO: return "undo";
188        case GB_UNDO_REDO: return "redo";
189
190        case GB_UNDO_NONE:
191        case GB_UNDO_KILL:
192        case GB_UNDO_UNDO_REDO:
193            break;
194    }
195    return NULL;
196}
197
198GB_UNDO_TYPE GBP_charPtr_2_GB_UNDO_TYPE(const char *undo_type) {
199    known_enum start; start.as_int = 0;
200    known_enum found  = string2enum_or_die("undo-type", undo_type, (enum2string)GBP_GB_UNDO_TYPE_2_charPtr, start);
201    return found.undo_type;
202}
203
204
205// -----------------
206//      GB_CASE
207
208const char *GBP_GB_CASE_2_charPtr(GB_CASE sensitivity) {
209    switch (sensitivity) {
210        case GB_IGNORE_CASE:    return "ignore_case";
211        case GB_MIND_CASE:      return "mind_case";
212        case GB_CASE_UNDEFINED: return "case_undef";
213    }
214    return NULL;
215}
216
217GB_CASE GBP_charPtr_2_GB_CASE(const char *sensitivity) {
218    known_enum start; start.as_int = 0;
219    known_enum found  = string2enum_or_die("sensitivity", sensitivity, (enum2string)GBP_GB_CASE_2_charPtr, start);
220    return found.case_sensitivity;
221}
222
223// ---------------------------
224//      GB_alignment_type
225
226const char *GBP_GB_alignment_type_2_charPtr(GB_alignment_type ali_type) {
227    switch (ali_type) {
228        case GB_AT_RNA: return "RNA";
229        case GB_AT_DNA: return "DNA";
230        case GB_AT_AA:  return "AMINO";
231
232        case GB_AT_UNKNOWN: break;
233    }
234    return NULL;
235}
236
237GB_alignment_type GBP_charPtr_2_GB_alignment_type(const char *ali_type) {
238    known_enum start; start.as_int = 0;
239    known_enum found  = string2enum_or_die("alignment-type", ali_type, (enum2string)GBP_GB_alignment_type_2_charPtr, start);
240    return found.ali_type;
241}
242
243// -----------------------------------------
244//      wrap functions moved to CORE lib
245//
246// As long as CORE lib is not xsub'd, we use wrappers for some
247// functions used in perl
248
249GB_ERROR GBC_await_error() {
250    return GB_await_error();
251}
252
253// --------------------
254//      perl panic
255
256void GBP_prepare_to_die() {
257    // called from die() in ../PERL2ARB/ARB.pm@prepare_to_die
258    gb_abort_and_close_all_DBs();
259}
Note: See TracBrowser for help on using the repository browser.