1 /*******************************************************************************
2 *
3 * This file is part of the General Hidden Markov Model Library,
4 * GHMM version __VERSION__, see http://ghmm.org
5 *
6 * Filename: ghmm/ghmm/scanner.c
7 * Authors: Frank N�bel
8 *
9 * Copyright (C) 1998-2004 Alexander Schliep
10 * Copyright (C) 1998-2001 ZAIK/ZPR, Universitaet zu Koeln
11 * Copyright (C) 2002-2004 Max-Planck-Institut fuer Molekulare Genetik,
12 * Berlin
13 *
14 * Contact: schliep@ghmm.org
15 *
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Library General Public
18 * License as published by the Free Software Foundation; either
19 * version 2 of the License, or (at your option) any later version.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Library General Public License for more details.
25 *
26 * You should have received a copy of the GNU Library General Public
27 * License along with this library; if not, write to the Free
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 *
31 * This file is version $Revision: 1977 $
32 * from $Date: 2007-11-16 10:49:06 -0500 (Fri, 16 Nov 2007) $
33 * last change by $Author: grunau $.
34 *
35 *******************************************************************************/
36
37 #ifdef HAVE_CONFIG_H
38 # include "../config.h"
39 #endif
40
41 #include "ghmmconfig.h"
42
43 #ifdef GHMM_OBSOLETE
44
45 #include <string.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <ctype.h>
49
50 #include "mprintf.h"
51 #include "mes.h"
52 #include "scanner.h"
53 #include "ghmm_internals.h"
54
55 #define SCANNER_TYPE_CHAR 1
56 #define SCANNER_TYPE_INT 2
57 #define SCANNER_TYPE_DOUBLE 3
58 #define SCANNER_TYPE_EDOUBLE 4
59 #define SCANNER_TYPE_STRING 5
60 #define SCANNER_TYPE_CSTRING 6
61
62 #define m_scanner_isdigit( c ) ( (c)>= '0' && (c) <= '9' )
63 #define m_scanner_isxdigit( c ) \
64 ( m_scanner_isdigit(c) || ((c) >= 'a' && (c) <= 'f') || ((c)>='A' && (c)<= 'F') )
65 #define m_scanner_isalpha( c ) \
66 ( ((c)>='a' && (c)<='z') || ((c)>='A' && (c)<='Z') )
67 #define m_scanner_isxalpha( c )\
68 (m_scanner_isalpha(c)||((c)&0x80 || (c)=='_'))
69
70 /*----------------------------------------------------------------------------*/
scanner_type(char * type,int * size)71 static int scanner_type (char *type, int *size)
72 {
73 if (!strcmp (type, "char")) {
74 *size = sizeof (char);
75 return (SCANNER_TYPE_CHAR);
76 }
77 if (!strcmp (type, "int")) {
78 *size = sizeof (int);
79 return (SCANNER_TYPE_INT);
80 }
81 if (!strcmp (type, "double")) {
82 *size = sizeof (double);
83 return (SCANNER_TYPE_DOUBLE);
84 }
85 if (!strcmp (type, "edouble")) {
86 *size = sizeof (double);
87 return (SCANNER_TYPE_EDOUBLE);
88 }
89 if (!strcmp (type, "string")) {
90 *size = sizeof (char *);
91 return (SCANNER_TYPE_STRING);
92 }
93 if (!strcmp (type, "cstring")) {
94 *size = sizeof (char *);
95 return (SCANNER_TYPE_CSTRING);
96 }
97 *size = 0;
98 return (0);
99 } /* scanner_type */
100
101 /*----------------------------------------------------------------------------*/
scanner_digit(int * val,scanner_t * s,int radix,int expect)102 static int scanner_digit (int *val, scanner_t * s, int radix, int expect)
103 {
104 switch (radix) {
105 case 10:
106 if ('0' <= s->c && s->c <= '9')
107 *val = *val * 10 + s->c - '0';
108 else if (expect) {
109 ighmm_scanner_error (s, "decimal digit expected");
110 return (-1);
111 }
112 else
113 return (1);
114 break;
115 case 16:
116 if (s->c >= '0' && s->c <= '9')
117 *val = *val * 16 + s->c - '0';
118 else if ('A' <= s->c && s->c <= 'F')
119 *val = *val * 16 + s->c - 'A' + 10;
120 else if ('a' <= s->c && s->c <= 'f')
121 *val = *val * 16 + s->c - 'a' + 10;
122 else if (expect) {
123 ighmm_scanner_error (s, "decimal digit expected");
124 return (-1);
125 }
126 else
127 return (1);
128 break;
129 case 2:
130 if (s->c >= '0' && s->c <= '1')
131 *val = *val * 2 + s->c - '0';
132 else if (expect) {
133 ighmm_scanner_error (s, "binary digit expected");
134 return (-1);
135 }
136 else
137 return (1);
138 break;
139 case 8:
140 if (s->c >= '0' && s->c <= '7')
141 *val = *val * 8 + s->c - '0';
142 else if (expect) {
143 ighmm_scanner_error (s, "octal digit expected");
144 return (-1);
145 }
146 else
147 return (1);
148 break;
149 default:
150 return (1);
151 }
152 return (0);
153 } /* scanner_digit */
154
155 /*----------------------------------------------------------------------------*/
scanner_virtual_fgetc(scanner_t * s)156 static int scanner_virtual_fgetc (scanner_t * s)
157 {
158 int c;
159
160 if (!s)
161 return (EOF);
162 c = fgetc (s->fp); /* Don't use the mes-functions here */
163 if (c == EOF)
164 return (c);
165 ungetc (c, s->fp);
166 return (c);
167 } /* scanner_virtual_fgetc */
168
169 /*----------------------------------------------------------------------------*/
scanner_fgetc(scanner_t * s)170 static void scanner_fgetc (scanner_t * s)
171 {
172 int c;
173
174 if (!s)
175 return;
176 c = fgetc (s->fp); /* Don't use the mes-functions here */
177 if (c == EOF) {
178 s->c = 0;
179 s->eof = 1;
180 }
181 else
182 s->c = c;
183 } /* scanner_fgetc */
184
185 /*----------------------------------------------------------------------------*/
scanner_nextchar(scanner_t * s,int expect)186 static int scanner_nextchar (scanner_t * s, int expect)
187 {
188 if (!s || s->err || s->eof)
189 return (0);
190 while (s->pos + 1 >= s->txtlen) {
191 int mes_stat = ighmm_mes_ability (0);
192 int err = ighmm_realloc ((void**)&(s->txt), sizeof(*(s->txt))*(s->txtlen + 256));
193 ighmm_mes_ability (mes_stat);
194
195 if (err) {
196 ighmm_scanner_error (s, "line too long");
197 return (-1);
198 }
199 else
200 s->txtlen += 256;
201 }
202 s->txt[s->pos] = s->c;
203 if (s->c == '\n') {
204 s->pos = 0;
205 s->line++;
206 }
207 else
208 s->pos++;
209 s->txt[s->pos] = 0;
210
211 scanner_fgetc (s);
212 if (s->eof && expect) {
213 ighmm_scanner_error (s, "unexpected end of file");
214 return (-1);
215 }
216 return (0);
217 } /* scanner_nextchar */
218
219 /*----------------------------------------------------------------------------*/
scanner_nextcchar(scanner_t * s)220 static int scanner_nextcchar (scanner_t * s)
221 {
222 if (!s || s->eof || s->err)
223 return (0);
224 if (s)
225 s->esc = 0;
226 if (scanner_nextchar (s, 1))
227 return (-1);
228 if (s->c - '\\')
229 return (0);
230 else {
231 int radix = 0;
232 int digits = 0;
233 int val = 0;
234 if (scanner_nextchar (s, 1))
235 return (-1);
236 s->esc = 1;
237 if ('0' <= s->c && s->c <= '7') {
238 radix = 8;
239 val = s->c - '0';
240 digits = 2;
241 }
242 else {
243 switch (s->c) {
244 case 'a':
245 s->c = '\a';
246 break;
247 case 'b':
248 s->c = '\b';
249 break;
250 case 'f':
251 s->c = '\f';
252 break;
253 case 'n':
254 s->c = '\n';
255 break;
256 case 'r':
257 s->c = '\r';
258 break;
259 case 't':
260 s->c = '\t';
261 break;
262 case 'v':
263 s->c = '\v';
264 break;
265 case '\\':
266 s->c = '\\';
267 break;
268 case '\'':
269 s->c = '\'';
270 break;
271 case '"':
272 s->c = '\"';
273 break;
274 case '?':
275 s->c = '\?';
276 break;
277 case 'd':
278 radix = 10;
279 digits = 3;
280 break;
281 case 'x':
282 radix = 16;
283 digits = 2;
284 break;
285 case '_':
286 radix = 2;
287 digits = 8;
288 break;
289 default:
290 return (0);
291 }
292 if (!radix)
293 return (0);
294 }
295 while (digits--) {
296 if (scanner_nextchar (s, 1))
297 return (-1);
298 if (scanner_digit (&val, s, radix, 1))
299 return (-1);
300 }
301 s->c = val;
302 }
303 return (0);
304 } /* scanner_nextcchar */
305
306 /*----------------------------------------------------------------------------*/
scanner_skipspace(scanner_t * s)307 static int scanner_skipspace (scanner_t * s)
308 {
309 if (s->eof || s->err)
310 return (0);
311 while (!s->eof) {
312 if (s->c == '#') { /* skip comment */
313 do {
314 if (scanner_nextchar (s, 0))
315 return (-1);
316 } while (!s->eof && s->c - '\n');
317 }
318
319 /* New : C-Comment allowed */
320 else if (s->c == '/' && scanner_virtual_fgetc (s) == '*') {
321 do {
322 if (scanner_nextchar (s, 0))
323 return (-1);
324 } while (!s->eof && (s->c - '*' || scanner_virtual_fgetc (s) - '/'));
325 if (!s->eof && scanner_nextchar (s, 0))
326 return (-1);
327 if (!s->eof && scanner_nextchar (s, 0))
328 return (-1);
329 } /* FN: 22.10.97 */
330
331 else if (strchr (" \n\r\t\f\v\b\a", s->c)) {
332 if (scanner_nextchar (s, 0))
333 return (-1);
334 }
335
336 else
337 break;
338 }
339 return (0);
340 } /* scanner_skipspace */
341
342 /*----------------------------------------------------------------------------*/
scanner_get_length(scanner_t * s,double resolution)343 static double scanner_get_length (scanner_t * s, double resolution)
344 {
345 double val = ighmm_scanner_get_double (s);
346
347 if (!s || s->err)
348 return (0);
349 if (s->eof) {
350 ighmm_scanner_error (s, "length expected");
351 return (0);
352 }
353 if (s->c - ';') {
354 if (resolution <= 0.0) {
355 ighmm_scanner_error (s, "resolution not set");
356 return (0);
357 }
358 s->resolution_used = 1;
359 if (ighmm_scanner_get_id (s))
360 return (0);
361 if (!strcmp (s->id, "INCH"))
362 val *= resolution;
363 else if (!strcmp (s->id, "CM"))
364 val *= (resolution / 2.54);
365 else if (!strcmp (s->id, "MM"))
366 val *= (resolution / 25.4);
367 else {
368 ighmm_scanner_error (s, "unknown length unit");
369 return (0);
370 }
371 }
372 return val;
373 } /* scanner_get_length */
374
375
376 /*============================================================================*/
377 /*============================================================================*/
378 /*============================================================================*/
ighmm_scanner_free(scanner_t ** s)379 int ighmm_scanner_free (scanner_t ** s)
380 {
381 # define CUR_PROC "ighmm_scanner_free"
382 mes_check_ptr (s, return (-1));
383 if (!*s)
384 return (0);
385 m_free ((*s)->filename);
386 m_free ((*s)->id);
387 m_free ((*s)->txt);
388 m_fclose ((*s)->fp);
389 m_free (*s);
390 return (0);
391 # undef CUR_PROC
392 } /* ighmm_scanner_free */
393
394 /*============================================================================*/
ighmm_scanner_alloc(const char * filename)395 scanner_t *ighmm_scanner_alloc (const char *filename)
396 {
397 #define CUR_PROC "ighmm_scanner_alloc"
398 scanner_t *s = NULL;
399
400 mes_check_ptr (filename, return (NULL));
401 ARRAY_CALLOC (s, 1);
402
403 s->txtlen = 256;
404 s->idlen = 256;
405 if (!(s->fp = ighmm_mes_fopen (filename, "rt"))) {
406 GHMM_LOG_QUEUED(LCONVERTED);
407 goto STOP;
408 }
409 ARRAY_MALLOC (s->txt, s->txtlen);
410 ARRAY_MALLOC (s->id, s->txtlen);
411 ARRAY_CALLOC (s->filename, strlen (filename) + 1);
412
413 memcpy (s->filename, filename, strlen (filename) + 1);
414 s->line = 1;
415 s->pos = 0;
416 s->c = ' ';
417 s->err = 0;
418
419 /****************/
420 s->resolution_used = 0;
421 s->x_resolution = 0.0;
422 s->y_resolution = 0.0;
423 s->x_scale = 1.0;
424 s->y_scale = 1.0;
425
426 scanner_fgetc (s);
427 if (scanner_skipspace (s))
428 goto STOP;
429 return (s);
430 STOP: /* Label STOP from ARRAY_[CM]ALLOC */
431 ighmm_scanner_free (&s);
432 return (NULL);
433 #undef CUR_PROC
434 } /* ighmm_scanner_alloc */
435
436 /*============================================================================*/
ighmm_scanner_error(scanner_t * s,char * message)437 int ighmm_scanner_error (scanner_t * s, char *message)
438 {
439 int i, j;
440
441 if (!s || s->err)
442 return (0);
443 j = s->pos;
444 while (!s->eof && s->c - '\n' && !scanner_nextchar (s, 0));
445 ighmm_mes_time ();
446 mes_file_win (s->txt);
447 mes_file_win ("\n");
448 for (i = 0; i < j; i++) {
449 if (s->txt[i] - '\t')
450 s->txt[i] = ' ';
451 }
452 s->txt[j] = 0;
453 mes_file_win (s->txt);
454 mes_file_win ("^\n");
455 if (message) {
456 ighmm_mes (MES_FILE_WIN, "Error in file %s, line %d : %s\n",
457 s->filename, s->line + 1, message);
458 }
459 else {
460 ighmm_mes (MES_FILE_WIN, "Syntax error in file %s, line %d\n",
461 s->filename, s->line + 1, message);
462 }
463 s->err = 1;
464 s->c = 0;
465 return (0);
466 } /* ighmm_scanner_error */
467
468 /*============================================================================*/
ighmm_scanner_consume(scanner_t * s,char ch)469 int ighmm_scanner_consume (scanner_t * s, char ch)
470 {
471 if (s->err)
472 return (0);
473 if (s->eof || ch - s->c) {
474 char txt[] = "' ' expected!";
475 txt[1] = ch;
476 ighmm_scanner_error (s, txt);
477 return (-1);
478 }
479 else if (scanner_nextchar (s, 0))
480 return (-1);
481 if (scanner_skipspace (s))
482 return (-1);
483 return (0);
484 } /* ighmm_scanner_consume */
485
486 /*============================================================================*/
487 /* Reads over a block, that's enclosed in '{' and '}'. Other blocks, lying within
488 this one will be skipped */
ighmm_scanner_consume_block(scanner_t * s)489 int ighmm_scanner_consume_block (scanner_t * s)
490 {
491 int open_brackets = 0;
492 if (s->err)
493 return (0);
494 ighmm_scanner_consume (s, '{');
495 if (s->err)
496 return (-1);
497 open_brackets++;
498
499 while (!s->eof && open_brackets) {
500 if (!('{' - s->c))
501 open_brackets++;
502 else if (!('}' - s->c))
503 open_brackets--;
504 if (scanner_nextchar (s, 0))
505 return (-1);
506 if (scanner_skipspace (s))
507 return (-1);
508 }
509 if (open_brackets) {
510 ighmm_scanner_error (s, "Unexpected EOF! '}'expected");
511 return (-1);
512 }
513 return (0);
514 } /* ighmm_scanner_consume_block */
515
516 /*============================================================================*/
ighmm_scanner_get_name(scanner_t * s)517 int ighmm_scanner_get_name (scanner_t * s)
518 {
519 int pos = 0;
520
521 if (!s || s->err)
522 return (0);
523 while (m_scanner_isxalpha (s->c) || m_scanner_isdigit (s->c)) {
524 while (pos + 1 >= s->idlen) {
525 int mes_stat = ighmm_mes_ability (0);
526 int err = ighmm_realloc ((void**)&(s->txt), sizeof(*(s->txt))*(s->txtlen + 256));
527 ighmm_mes_ability (mes_stat);
528 if (err) {
529 ighmm_scanner_error (s, "identifier too long");
530 return (-1);
531 }
532 else
533 s->idlen += 256;
534 }
535 s->id[pos++] = s->c;
536 if (scanner_nextchar (s, 0))
537 return (-1);
538 }
539 if (!pos || m_scanner_isdigit (s->id[0]))
540 ighmm_scanner_error (s, "identifier expected");
541 s->id[pos] = 0;
542 if (scanner_skipspace (s))
543 return (-1);
544 return (0);
545 } /* ighmm_scanner_get_name */
546
547 /*============================================================================*/
ighmm_scanner_get_id(scanner_t * s)548 int ighmm_scanner_get_id (scanner_t * s)
549 {
550 char *str;
551 if (!s || s->err)
552 return (0);
553 if (ighmm_scanner_get_name (s))
554 return (0);
555 str = s->id;
556 while (*str) {
557 if ('a' <= *str && *str <= 'z')
558 *str += 'A' - 'a';
559 str++;
560 }
561 return (0);
562 } /* ighmm_scanner_get_id */
563
564 /*============================================================================*/
ighmm_scanner_get_str(scanner_t * s,int * len,int cmode)565 char *ighmm_scanner_get_str (scanner_t * s, int *len, int cmode)
566 {
567 # define CUR_PROC "scanner_get_string"
568 int i = 0;
569 int maxlen = 128;
570 char *val = NULL;
571
572 if (!s || s->err)
573 return (NULL);
574 if (s->eof || s->c - '"') {
575 ighmm_scanner_error (s, "string expected");
576 goto STOP;
577 }
578 ARRAY_MALLOC (val, maxlen);
579
580 while (!s->eof && s->c == '"') {
581 if (cmode) {
582 if (scanner_nextcchar (s))
583 goto STOP;
584 }
585 else {
586 if (scanner_nextchar (s, 1))
587 goto STOP;
588 }
589 while (s->c - '"' || s->esc) {
590 if (s->eof || ((!s->c || s->c == '\n') && !s->esc)) {
591 ighmm_scanner_error (s, "String not closed");
592 goto STOP;
593 }
594 if (i + 1 == maxlen) {
595 ARRAY_REALLOC (val, maxlen + 128);
596 maxlen += 128;
597 }
598 if (s->c || len)
599 val[i++] = s->c;
600 if (cmode) {
601 if (scanner_nextcchar (s))
602 goto STOP;
603 }
604 else {
605 if (scanner_nextchar (s, 1))
606 goto STOP;
607 }
608 }
609
610 if (ighmm_scanner_consume (s, '"'))
611 goto STOP;
612 if (scanner_skipspace (s))
613 goto STOP;
614 }
615 val[i++] = 0;
616 ARRAY_REALLOC (val, i);
617 if (len)
618 *len = i;
619 return (val);
620
621 STOP: /* Label STOP from ARRAY_[CM]ALLOC */
622 m_free (val);
623 return (NULL);
624 # undef CUR_PROC
625 } /* ighmm_scanner_get_str */
626
627 /*============================================================================*/
ighmm_scanner_get_path(scanner_t * s)628 char *ighmm_scanner_get_path (scanner_t * s)
629 {
630 #define CUR_PROC "ighmm_scanner_get_path"
631 char *res = scanner_get_string (s);
632 char *p;
633 # if defined(_PPC) || defined(_DOS) || defined(_WINDOWS)
634 if (res)
635 for (p = res; *p; p++)
636 if (*p == '/')
637 *p = '\\';
638 # else
639 if (res)
640 for (p = res; *p; p++)
641 if (*p == '\\')
642 *p = '/';
643 # endif
644 return (res);
645 #undef CUR_PROC
646 } /* ighmm_scanner_get_path */
647
648 /*============================================================================*/
ighmm_scanner_get_int(scanner_t * s)649 int ighmm_scanner_get_int (scanner_t * s)
650 {
651 int val = 0;
652 int sign = 0;
653
654 if (!s || s->err)
655 return (0);
656 if (s->eof) {
657 ighmm_scanner_error (s, "integer expected");
658 return (0);
659 }
660
661 if (s->c == '-') {
662 if (scanner_nextchar (s, 1))
663 return (0);
664 sign = 1;
665 }
666 else if (s->c == '+') {
667 if (scanner_nextchar (s, 1))
668 return (0);
669 }
670 if (scanner_skipspace (s))
671 return (0);
672
673 if (s->c == '\'') {
674 if (scanner_nextcchar (s))
675 return (0);
676 val = (unsigned char) (s->c);
677 if (scanner_nextchar (s, 1))
678 return (0);
679 if (s->c - '\'') {
680 if (!s->esc) {
681 ighmm_scanner_error (s, " \' expected");
682 return (0);
683 }
684 val = (unsigned char) '\\';
685 }
686 else if (scanner_nextchar (s, 1))
687 return (0);
688 }
689
690 else if (!m_scanner_isdigit (s->c)) {
691 if (ighmm_scanner_get_id (s))
692 return (0);
693 if (!strcmp (s->id, "TRUE"))
694 return (sign ? 0 : 1);
695 else if (!strcmp (s->id, "FALSE"))
696 return (sign ? 1 : 0);
697 if (!strcmp (s->id, "ON"))
698 return (sign ? 0 : 1);
699 else if (!strcmp (s->id, "OFF"))
700 return (sign ? 1 : 0);
701 ighmm_scanner_error (s, "integer value expected");
702 return (0);
703 }
704
705 else {
706 int radix = 10;
707
708 if (s->c == '0') {
709 if (scanner_nextchar (s, 1))
710 return (0);
711 if (m_scanner_isdigit (s->c)) {
712 val = s->c - '0';
713 if (scanner_nextchar (s, 1))
714 return (0);
715 }
716 else
717 switch (s->c) {
718 case 'x':
719 case 'X':
720 radix = 16;
721 break;
722 case '_':
723 radix = 2;
724 break;
725 case 'o':
726 radix = 8;
727 break;
728 }
729 if (radix - 10) {
730 if (scanner_nextchar (s, 1))
731 return (0);
732 if (scanner_digit (&val, s, radix, 1))
733 return (0);
734 if (scanner_nextchar (s, 1))
735 return (0);
736 }
737 }
738 while (!scanner_digit (&val, s, radix, 0)) {
739 if (scanner_nextchar (s, 1))
740 return (0);
741 }
742 }
743 if (scanner_skipspace (s))
744 return (0);
745 return (sign ? -val : val);
746 # undef CUR_PROC
747 } /* ighmm_scanner_get_int */
748
749
750 /*============================================================================*/
ighmm_scanner_get_double(scanner_t * s)751 double ighmm_scanner_get_double (scanner_t * s)
752 {
753 double val = 0;
754 int sign = 0;
755
756 if (!s || s->err)
757 return (0);
758 if (s->eof) {
759 ighmm_scanner_error (s, "real number expected");
760 return (0);
761 }
762
763 if (s->c == '-') {
764 if (scanner_nextchar (s, 1))
765 return (0);
766 sign = 1;
767 }
768 else if (s->c == '+' && scanner_nextchar (s, 1))
769 return (0);
770
771 if (scanner_skipspace (s))
772 return (0);
773
774 if (!m_scanner_isdigit (s->c) && s->c - '.') {
775 ighmm_scanner_error (s, "real number expected");
776 return (0);
777 }
778 while (m_scanner_isdigit (s->c)) {
779 val = 10 * val + (double) (s->c - '0');
780 if (scanner_nextchar (s, 1))
781 return (0);
782 }
783 if (s->c == '.') {
784 double factor = 1;
785 if (scanner_nextchar (s, 1))
786 return (0);
787 while (m_scanner_isdigit (s->c)) {
788 val = 10 * val + (double) (s->c - '0');
789 if (scanner_nextchar (s, 1))
790 return (0);
791 factor *= 10;
792 }
793 val /= factor;
794 }
795 if (scanner_skipspace (s))
796 return (0);
797 return (sign ? -val : val);
798 } /* ighmm_scanner_get_double */
799
800
801 /*============================================================================*/
ighmm_scanner_get_edouble(scanner_t * s)802 double ighmm_scanner_get_edouble (scanner_t * s)
803 {
804 double val = 0;
805 int sign = 0;
806
807 if (!s || s->err)
808 return (0);
809 if (s->eof) {
810 ighmm_scanner_error (s, "real number expected");
811 return (0);
812 }
813
814 if (s->c == '-') {
815 if (scanner_nextchar (s, 1))
816 return (0);
817 sign = 1;
818 }
819 else if (s->c == '+' && scanner_nextchar (s, 1))
820 return (0);
821
822 if (scanner_skipspace (s))
823 return (0);
824
825 if (!m_scanner_isdigit (s->c) && s->c - '.') {
826 ighmm_scanner_error (s, "real number expected");
827 return (0);
828 }
829 while (m_scanner_isdigit (s->c)) {
830 val = 10 * val + (double) (s->c - '0');
831 if (scanner_nextchar (s, 1))
832 return (0);
833 }
834 if (s->c == '.') {
835 double factor = 1;
836 if (scanner_nextchar (s, 1))
837 return (0);
838 while (m_scanner_isdigit (s->c)) {
839 val = 10 * val + (double) (s->c - '0');
840 if (scanner_nextchar (s, 1))
841 return (0);
842 factor *= 10;
843 }
844 val /= factor;
845 }
846 if (s->c == 'e' || s->c == 'E') {
847 int i;
848 double eval;
849 double efactor = 1;
850 int esign = 0;
851 if (scanner_nextchar (s, 1))
852 return (0);
853 if (s->c == '-') {
854 if (scanner_nextchar (s, 1))
855 return (0);
856 esign = 1;
857 }
858 else if (s->c == '+' && scanner_nextchar (s, 1))
859 return (0);
860 eval = ighmm_scanner_get_int (s);
861 if (eval < 0)
862 return (0);
863 for (i = 0; i < eval; i++)
864 efactor *= 10;
865 if (esign)
866 val /= efactor;
867 else
868 val *= efactor;
869 }
870
871 if (scanner_skipspace (s))
872 return (0);
873 return (sign ? -val : val);
874 } /* ighmm_scanner_get_edouble */
875
876
877 /*============================================================================*/
ighmm_scanner_get_array(scanner_t * s,int * len,char * type)878 void *ighmm_scanner_get_array (scanner_t * s, int *len, char *type)
879 {
880 #define CUR_PROC "ighmm_scanner_get_array"
881 int size = 0;
882 int typ = scanner_type (type, &size);
883 int maxlen = 16 * size;
884 char *val = NULL;
885 int i = 0;
886 char txt[256];
887 int err;
888 int mes_stat;
889
890 if (!s || !type || !len || s->err)
891 goto STOP;
892 if (!typ) {
893 ighmm_scanner_error (s, ighmm_mprintf (txt, sizeof (txt), "unknown type %s ", type));
894 goto STOP;
895 }
896 if (!len || !s || s->err)
897 goto STOP;
898 if (s->eof) {
899 ighmm_scanner_error (s,
900 ighmm_mprintf (txt, sizeof (txt), "%s array expected ", type));
901 goto STOP;
902 }
903 if (s->c == ';') {
904 *len = 0;
905 goto STOP;
906 }
907 mes_stat = ighmm_mes_ability (0);
908 val = ighmm_malloc (sizeof (char *) * maxlen);
909 err = !val;
910 ighmm_mes_ability (mes_stat);
911 if (err) {
912 ighmm_mprintf (txt, sizeof (txt), "Not enough memory to read %s array", type);
913 ighmm_scanner_error (s, txt);
914 goto STOP;
915 }
916
917 while (s->c - ';') {
918 /* Originally:
919 if( i && ighmm_scanner_consume( s, ',' ) ) goto STOP; */
920 /* Changed: read array without seperator now possible */
921 if (s->c == ',')
922 ighmm_scanner_consume (s, ',');
923 switch (typ) {
924 case SCANNER_TYPE_CHAR:
925 val[i] = ighmm_scanner_get_int (s);
926 break;
927 case SCANNER_TYPE_INT:
928 *(int *) (val + i) = ighmm_scanner_get_int (s);
929 break;
930 case SCANNER_TYPE_DOUBLE:
931 *(double *) (val + i) = ighmm_scanner_get_double (s);
932 break;
933 case SCANNER_TYPE_EDOUBLE:
934 *(double *) (val + i) = ighmm_scanner_get_edouble (s);
935 break;
936 case SCANNER_TYPE_STRING:
937 *(char **) (val + i) = scanner_get_string (s);
938 break;
939 case SCANNER_TYPE_CSTRING:
940 *(char **) (val + i) = scanner_get_cstring (s);
941 break;
942 default:
943 goto STOP;
944 }
945 i += size;
946 if (s->err)
947 goto STOP;
948
949 if (i == maxlen) {
950 mes_stat = ighmm_mes_ability (0);
951 err = ighmm_realloc ((void**)&val, sizeof (*val) * (maxlen + 16 * size));
952 ighmm_mes_ability (mes_stat);
953 if (err) {
954 ighmm_mprintf (txt, sizeof (txt), "Not enough memory to read %s array", type);
955 ighmm_scanner_error (s, txt);
956 goto STOP;
957 }
958 maxlen += 16 * size;
959 }
960 }
961 mes_stat = ighmm_mes_ability (0);
962 ighmm_realloc ((void**)&val, sizeof (*val) * i);/* Do'nt worry if this fails!*/
963 ighmm_mes_ability (mes_stat);
964
965 *len = i / size;
966
967 return (val);
968
969 STOP: /* Label STOP from ARRAY_[CM]ALLOC */
970 m_free (val);
971 if (len)
972 *len = 0;
973 return (NULL);
974 # undef CUR_PROC
975 } /* ighmm_scanner_get_array */
976
977
978 /*============================================================================*/
ighmm_scanner_free_array(int * len,void *** arr)979 int ighmm_scanner_free_array (int *len, void ***arr)
980 {
981 # define CUR_PROC "ighmm_scanner_free_array"
982 mes_check_ptr (len, return (-1));
983 mes_check_ptr (arr, return (-1));
984 while ((*len)-- > 0) {
985 m_free ((*arr)[*len]);
986 }
987 free (*arr);
988 *len = 0;
989 return (0);
990 # undef CUR_PROC
991 } /* ighmm_scanner_free_array */
992
993 /*============================================================================*/
ighmm_scanner_get_index(scanner_t * s,int n)994 int ighmm_scanner_get_index (scanner_t * s, int n)
995 {
996 int index = n - 1;
997 if (!s || s->err)
998 return (0);
999 if (s->eof || s->c - '@') {
1000 ighmm_scanner_error (s, "index expected");
1001 return (0);
1002 }
1003 if (ighmm_scanner_consume (s, '@'))
1004 return (0);
1005 index = ighmm_scanner_get_int (s);
1006 if (s->err)
1007 return (0);
1008 if (index >= n)
1009 ighmm_scanner_error (s, "index too high");
1010 if (ighmm_scanner_consume (s, ';'))
1011 return (0);
1012 return (index);
1013 } /* ighmm_scanner_get_index */
1014
1015 /*============================================================================*/
ighmm_scanner_get_resolution(scanner_t * s)1016 double ighmm_scanner_get_resolution (scanner_t * s)
1017 {
1018 double val;
1019
1020 if (!s || s->err)
1021 return (0);
1022 val = ighmm_scanner_get_double (s);
1023 if (s->err)
1024 return (0);
1025 if (ighmm_scanner_get_id (s))
1026 return (0);
1027 if (strcmp (s->id, "DPI")) {
1028 ighmm_scanner_error (s, "dpi expected");
1029 return (0);
1030 }
1031 return (val);
1032 } /* ighmm_scanner_get_resolution */
1033
1034 /*============================================================================*/
ighmm_scanner_get_length_x(scanner_t * s)1035 int ighmm_scanner_get_length_x (scanner_t * s)
1036 {
1037 return (s->x_scale * scanner_get_length (s, s->x_resolution) + 0.5);
1038 } /* ighmm_scanner_get_length_x */
1039
1040 /*============================================================================*/
ighmm_scanner_get_length_y(scanner_t * s)1041 int ighmm_scanner_get_length_y (scanner_t * s)
1042 {
1043 return (s->y_scale * scanner_get_length (s, s->y_resolution) + 0.5);
1044 } /* ighmm_scanner_get_length_y */
1045
1046
1047 #if defined( TEST )
1048 /*============================================================================*/
scanner_tst(void)1049 int scanner_tst (void)
1050 {
1051 # define CUR_PROC "scanner_tst"
1052 scanner_t *s = ighmm_scanner_alloc ("scanner.cfg");
1053 char *char_arr = NULL;
1054 int char_len = 0;
1055 int *int_arr = NULL;
1056 int int_len = 0;
1057 double *double_arr = NULL;
1058 int double_len = 0;
1059 char **string_arr = NULL;
1060 int string_len = 0;
1061 int res = -1;
1062 int i;
1063
1064 if (!s) {
1065 GHMM_LOG_QUEUED(LCONVERTED);
1066 goto STOP;
1067 }
1068
1069 while (!s->err && !s->eof) {
1070 if (ighmm_scanner_get_name (s))
1071 break;
1072 if (ighmm_scanner_consume (s, '='))
1073 break;
1074 else if (!strcmp (s->id, "char")) {
1075 m_free (char_arr);
1076 char_arr = scanner_get_char_array (s, &char_len);
1077 }
1078 else if (!strcmp (s->id, "int")) {
1079 m_free (int_arr);
1080 int_arr = scanner_get_int_array (s, &int_len);
1081 }
1082 else if (!strcmp (s->id, "string")) {
1083 m_free (string_arr);
1084 string_arr = scanner_get_cstring_array (s, &string_len);
1085 }
1086 else if (!strcmp (s->id, "double")) {
1087 m_free (double_arr);
1088 double_arr = scanner_get_double_array (s, &double_len);
1089 }
1090 else
1091 ighmm_scanner_error (s, "unknown identifyer");
1092 if (ighmm_scanner_consume (s, ';'))
1093 break;
1094 }
1095
1096 if (char_arr) {
1097 mes_win ("\nchar:\n");
1098 for (i = 0; i < char_len; i++)
1099 ighmm_mes (MES_WIN, " '%c'\n", char_arr[i]);
1100 }
1101 if (int_arr) {
1102 mes_win ("\nint:\n");
1103 for (i = 0; i < int_len; i++)
1104 ighmm_mes (MES_WIN, " %d\n", int_arr[i]);
1105 }
1106 if (double_arr) {
1107 mes_win ("\ndouble:\n");
1108 for (i = 0; i < double_len; i++)
1109 ighmm_mes (MES_WIN, " %f\n", double_arr[i]);
1110 }
1111 if (string_arr) {
1112 mes_win ("\nstring:\n");
1113 for (i = 0; i < string_len; i++)
1114 ighmm_mes (MES_WIN, " \"%s\"\n", string_arr[i]);
1115 }
1116
1117 res = 0;
1118 STOP:
1119 ighmm_scanner_free (&s);
1120 m_free (char_arr);
1121 m_free (int_arr);
1122 m_free (double_arr);
1123 if (string_arr)
1124 for (i = 0; i < string_len; i++)
1125 m_free (string_arr[i]);
1126 m_free (string_arr);
1127 return (res);
1128 # undef CUR_PROC
1129 } /* scanner_tst */
1130 #endif /* defined( TEST ) */
1131
1132 /*----------------------------------------------------------------------------*/
scanner_free_d_matrix(double *** matrix,long rows)1133 static int scanner_free_d_matrix (double ***matrix, long rows)
1134 {
1135 # define CUR_PROC "scanner_free_d_matrix"
1136 long i;
1137 mes_check_ptr (matrix, return (-1));
1138 if (!*matrix)
1139 return (0);
1140 for (i = 0; i < rows; i++)
1141 m_free ((*matrix)[i]);
1142 m_free (*matrix);
1143 return (0);
1144 # undef CUR_PROC
1145 } /* scanner_free_d_matrix */
1146
1147 /*============================================================================*/
ighmm_scanner_get_d_matrix(scanner_t * s,int * rows,int * cols)1148 double **ighmm_scanner_get_d_matrix (scanner_t * s, int *rows, int *cols)
1149 {
1150 #define CUR_PROC "ighmm_scanner_get_d_matrix"
1151 double **matrix = NULL;
1152 int local_cols = 0;
1153 *rows = *cols = 0;
1154 while (!s->eof && !s->err && s->c - '}') {
1155 (*rows)++;
1156 ARRAY_REALLOC (matrix, *rows);
1157 matrix[*rows - 1] = scanner_get_double_array (s, &local_cols);
1158 ighmm_scanner_consume (s, ';');
1159 if (s->err)
1160 goto STOP;
1161 if (*rows > 1)
1162 if (local_cols != *cols) {
1163 ighmm_scanner_error (s, "rows of variing length in matrix");
1164 goto STOP;
1165 }
1166 *cols = local_cols;
1167 } /* while ... */
1168 return matrix;
1169 STOP: /* Label STOP from ARRAY_[CM]ALLOC */
1170 scanner_free_d_matrix (&matrix, *rows);
1171 return NULL;
1172 #undef CUR_PROC
1173 } /* ighmm_scanner_get_d_matrix */
1174
1175 #endif /* GHMM_OBSOLETE */
1176