source: tags/ms_r16q2/CONVERTALN/util.cxx

Last change on this file was 14586, checked in by westram, 9 years ago
  • fix truncated error-messages
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1#include <BufferedFileReader.h>
2#include "fun.h"
3#include "defs.h"
4#include "global.h"
5#include "reader.h"
6
7#include <cstdarg>
8#include <cerrno>
9
10bool scan_token(char *to, const char *from) { // __ATTR__USERESULT
11    return sscanf(from, "%s", to) == 1;
12}
13
14void scan_token_or_die(char *to, const char *from) {
15    if (!scan_token(to, from)) {
16        throw_error(88, "expected to see a token here");
17    }
18}
19void scan_token_or_die(char *to, Reader& reader, int offset) {
20    scan_token_or_die(to, reader.line()+offset);
21}
22
23void throw_error(int error_num, const char *error_message) { // __ATTR__NORETURN
24    throw Convaln_exception(error_num, error_message);
25}
26
27char *strf(const char *format, ...) { // __ATTR__FORMAT(1)
28    va_list parg;
29    va_start(parg, format);
30
31    const int BUFSIZE = 1000;
32    char      buffer[BUFSIZE];
33    int       printed = vsprintf(buffer, format, parg);
34    ca_assert(printed <= BUFSIZE);
35
36    va_end(parg);
37
38    return strndup(buffer, printed);
39}
40
41void throw_errorf(int error_num, const char *error_messagef, ...) { // __ATTR__FORMAT(2) __ATTR__NORETURN
42    va_list parg;
43    va_start(parg, error_messagef);
44
45    const int   BUFSIZE = 1000;
46    static char buffer[BUFSIZE];
47    int         printed = vsprintf(buffer, error_messagef, parg);
48
49    va_end(parg);
50
51    if (printed >= BUFSIZE) {
52        throw_errorf(998, "Internal buffer overflow (while formatting error #%i '%s')", error_num, error_messagef);
53    }
54    throw_error(error_num, buffer);
55}
56
57// --------------------------------------------------------------------------------
58
59bool Warnings::show_warnings = true;
60
61void warning(int warning_num, const char *warning_message) {
62    // print out warning_message and continue execution.
63    if (Warnings::shown())
64        fprintf(stderr, "WARNING(%d): %s\n", warning_num, warning_message);
65}
66void warningf(int warning_num, const char *warning_messagef, ...) { // __ATTR__FORMAT(2)
67    if (Warnings::shown()) {
68        va_list parg;
69        va_start(parg, warning_messagef);
70
71        const int   BUFSIZE = 1000;
72        static char buffer[BUFSIZE];
73        int         printed = vsprintf(buffer, warning_messagef, parg);
74
75        va_end(parg);
76
77        if (printed >= BUFSIZE) {
78            throw_errorf(997, "Internal buffer overflow (while formatting warning #%i '%s')", warning_num, warning_messagef);
79        }
80        warning(warning_num, buffer);
81    }
82}
83
84char *Reallocspace(void *block, unsigned int size) {
85    // Realloc a continue space, expand or shrink the original space.
86    char *temp;
87
88    if (size <= 0) {
89        free(block);
90        return NULL;
91    }
92
93    if (block == NULL) {
94        temp = (char *)calloc(1, size);
95    }
96    else {
97        temp = (char *)realloc(block, size);
98    }
99    if (!temp) throw_error(999, "Run out of memory (Reallocspace)");
100    return temp;
101}
102
103int Skip_white_space(const char *line, int index) {
104    // Skip white space from (index)th char of Str line.
105
106    while (line[index] == ' ' || line[index] == '\t')
107        ++index;
108    return (index);
109}
110
111void Getstr(char *line, int linenum) {
112    // Get input Str from terminal.
113    char c;
114    int  indi = 0;
115
116    for (; (c = getchar()) != '\n' && indi < (linenum - 1); line[indi++] = c) {}
117
118    line[indi] = '\0';
119}
120
121inline void append_known_len(char*& string1, int len1, const char *string2, int len2) {
122    ca_assert(len2); // else no need to call, string1 already correct
123    int newlen      = len1+len2;
124    string1         = Reallocspace(string1, newlen+1);
125    memcpy(string1+len1, string2, len2);
126    string1[newlen] = 0;
127}
128
129void terminate_with(char*& str, char ch) {
130    // append 'ch' to end of 'str' (before \n)
131    // - if it's not already there and
132    // - 'str' contains more than just '\n'
133
134    int len = str0len(str);
135    if (!len) return;
136    ca_assert(str[len-1] == '\n');
137    if (len == 1) return;
138    if (str[len-2] == ch) return;
139
140    char temp[] = { ch, '\n' };
141    append_known_len(str, len-1, temp, 2);
142}
143
144void skip_eolnl_and_append(char*& string1, const char *string2) {
145    int len1 = str0len(string1);
146    if (len1 && string1[len1-1] == '\n') len1--;
147    int len2 = str0len(string2);
148    if (len2) append_known_len(string1, len1, string2, len2);
149    else { string1[len1] = 0; }
150}
151
152void skip_eolnl_and_append_spaced(char*& string1, const char *string2) {
153    int len1 = str0len(string1);
154    if (len1 && string1[len1-1] == '\n') string1[len1-1] = ' ';
155    append_known_len(string1, len1, string2, str0len(string2));
156}
157
158void Append(char*& string1, const char *string2) {
159    int len2 = str0len(string2);
160    if (len2) append_known_len(string1, str0len(string1), string2, len2);
161}
162void Append(char*& string1, char ch) {
163    append_known_len(string1, str0len(string1), &ch, 1);
164}
165
166void upcase(char *str) {
167    // Capitalize all char in the str.
168    if (!str) return;
169    for (int i = 0; str[i]; ++i) str[i] = toupper(str[i]);
170}
171
172int fputs_len(const char *str, int len, Writer& write) {
173    // like fputs(), but does not print more than 'len' characters
174    // returns number of chars written or throws write error
175    for (int i = 0; i<len; ++i) {
176        if (!str[i]) return i;
177        write.out(str[i]);
178    }
179    return len;
180}
181
182// -------------------------
183//      pattern matching
184
185enum FindMode { FIND_START, FIND_SKIP_OVER };
186
187static int findPattern(const char *text, const char *pattern, FindMode mode) {
188    // Return offset of 'pattern' in 'text' or -1
189    // (compares case insensitive)
190    // return position after found 'pattern' in 'endPtr'
191
192    if (text && pattern) {
193        for (int t = 0; text[t]; ++t) {
194            bool mismatch = false;
195
196            int p = 0;
197            for (; !mismatch && pattern[p]; ++p) {
198                mismatch = tolower(text[t+p]) != tolower(pattern[p]);
199            }
200            if (!mismatch) {
201                switch (mode) {
202                    case FIND_START: return t;
203                    case FIND_SKIP_OVER: return t+p;
204                }
205                ca_assert(0);
206            }
207        }
208    }
209    return -1;
210}
211
212static int findMultipattern(const char *str, const char** const& pattern, char expect_behind, FindMode mode) {
213    // search 'str' for the occurrence of any 'pattern'
214    // if 'expect_behind' != 0 -> expect that char behind the found pattern
215
216    int offset = -1;
217
218    if (str) {
219        FindMode use = expect_behind ? FIND_SKIP_OVER : mode;
220
221        int p;
222        for (p = 0; offset == -1 && pattern[p]; ++p) {
223            offset = findPattern(str, pattern[p], use);
224        }
225
226        if (offset != -1) {
227            if (expect_behind) {
228                if (str[offset] != expect_behind) { // mismatch
229                    offset = findMultipattern(str+offset, pattern, expect_behind, mode);
230                }
231                else {
232                    switch (mode) {
233                        case FIND_START:
234                            offset -= str0len(pattern[p]);
235                            ca_assert(offset >= 0);
236                            break;
237                        case FIND_SKIP_OVER:
238                            offset++;
239                            break;
240                    }
241                }
242            }
243        }
244    }
245    return offset;
246}
247
248static int findSubspecies(const char *str, char expect_behind, FindMode mode) {
249    const char *subspecies_pattern[] = { "subspecies", "sub-species", "subsp.", NULL };
250    return findMultipattern(str, subspecies_pattern, expect_behind, mode);
251}
252
253static int findStrain(const char *str, char expect_behind, FindMode mode) {
254    const char *strain_pattern[] = { "strain", "str.", NULL };
255    return findMultipattern(str, strain_pattern, expect_behind, mode);
256}
257
258int find_pattern(const char *text, const char *pattern) { return findPattern(text, pattern, FIND_START); }
259int skip_pattern(const char *text, const char *pattern) { return findPattern(text, pattern, FIND_SKIP_OVER); }
260
261int find_subspecies(const char *str, char expect_behind) { return findSubspecies(str, expect_behind, FIND_START); }
262int skip_subspecies(const char *str, char expect_behind) { return findSubspecies(str, expect_behind, FIND_SKIP_OVER); }
263
264int find_strain(const char *str, char expect_behind) { return findStrain(str, expect_behind, FIND_START); }
265int skip_strain(const char *str, char expect_behind) { return findStrain(str, expect_behind, FIND_SKIP_OVER); }
266
267const char *stristr(const char *str, const char *substring) {
268    int offset = find_pattern(str, substring);
269    return offset >= 0 ? str+offset : NULL;
270}
271
272int ___lookup_keyword(const char *keyword, const char * const *lookup_table, int lookup_table_size) {
273    // returns the index [0..n-1] of 'keyword' in lookup_table
274    // or -1 if not found.
275
276    for (int i = 0; i<lookup_table_size; ++i) {
277        if (str_equal(keyword, lookup_table[i])) return i;
278    }
279    return -1;
280}
281
282int parse_key_word(const char *line, char *key, const char *separator) {
283    // Copy keyword starting at position 'index' of 'line' delimited by 'separator' into 'key'.
284    // Do not copy more than 'TOKENSIZE-1' characters.
285    // Returns length of keyword.
286
287    int k = 0;
288    if (line) {
289        while (k<(TOKENSIZE-1) && line[k] && !occurs_in(line[k], separator)) {
290            key[k] = line[k];
291            ++k;
292        }
293    }
294    key[k] = 0;
295    return k;
296}
297
298// ----------------------
299//      FormattedFile
300
301FormattedFile::FormattedFile(const char *Name, Format Type)
302    : name_(strdup(Name)),
303      type_(Type)
304{}
305FormattedFile::~FormattedFile() {
306    free(name_);
307}
308
309void FormattedFile::init(const char *Name, Format Type) {
310    ca_assert(!name_); // do not init twice
311    ca_assert(Name);
312    ca_assert(Type != UNKNOWN);
313
314    name_ = nulldup(Name);
315    type_ = Type;
316}
317
Note: See TracBrowser for help on using the repository browser.