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