~ubuntu-branches/ubuntu/precise/spatialite/precise

« back to all changes in this revision

Viewing changes to libspatialite/src/gaiageo/gg_gml.c

  • Committer: Package Import Robot
  • Author(s): David Paleino, Francesco Paolo Lovergine, David Paleino
  • Date: 2011-11-21 12:10:43 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20111121121043-0g14o2uf0r343a82
Tags: 3.0.0~beta20110817-3
[ Francesco Paolo Lovergine ]
* Fixed linking order for sqlite3 in debian patch 00-systemlibs.patch.
  (closes: #638929)

[ David Paleino ]
* Conditionally disable full EPSG initialization (for srs_init.c)
  on powerpc, and document what projections are available on that
  architecture (Closes: #649302)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
 gg_gml.c -- GML parser/lexer 
 
4
  
 
5
 version 3.0, 2011 July 20
 
6
 
 
7
 Author: Sandro Furieri a.furieri@lqt.it
 
8
 
 
9
 ------------------------------------------------------------------------------
 
10
 
 
11
 Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
12
 
 
13
 The contents of this file are subject to the Mozilla Public License Version
 
14
 1.1 (the "License"); you may not use this file except in compliance with
 
15
 the License. You may obtain a copy of the License at
 
16
 http://www.mozilla.org/MPL/
 
17
 
 
18
Software distributed under the License is distributed on an "AS IS" basis,
 
19
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
20
for the specific language governing rights and limitations under the
 
21
License.
 
22
 
 
23
The Original Code is the SpatiaLite library
 
24
 
 
25
The Initial Developer of the Original Code is Alessandro Furieri
 
26
 
 
27
Portions created by the Initial Developer are Copyright (C) 2011
 
28
the Initial Developer. All Rights Reserved.
 
29
 
 
30
Alternatively, the contents of this file may be used under the terms of
 
31
either the GNU General Public License Version 2 or later (the "GPL"), or
 
32
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
33
in which case the provisions of the GPL or the LGPL are applicable instead
 
34
of those above. If you wish to allow use of your version of this file only
 
35
under the terms of either the GPL or the LGPL, and not to allow others to
 
36
use your version of this file under the terms of the MPL, indicate your
 
37
decision by deleting the provisions above and replace them with the notice
 
38
and other provisions required by the GPL or the LGPL. If you do not delete
 
39
the provisions above, a recipient may use your version of this file under
 
40
the terms of any one of the MPL, the GPL or the LGPL.
 
41
 
 
42
*/
 
43
 
 
44
#include <sys/types.h>
 
45
#include <stdlib.h>
 
46
#include <stdio.h>
 
47
#include <string.h>
 
48
 
 
49
#include <assert.h>
 
50
 
 
51
#ifdef SPL_AMALGAMATION         /* spatialite-amalgamation */
 
52
#include <spatialite/sqlite3.h>
 
53
#else
 
54
#include <sqlite3.h>
 
55
#endif
 
56
 
 
57
#include <spatialite/gaiageo.h>
 
58
 
 
59
int gml_parse_error;
 
60
 
 
61
#define GML_PARSER_OPEN_NODE            1
 
62
#define GML_PARSER_SELF_CLOSED_NODE     2
 
63
#define GML_PARSER_CLOSED_NODE          3
 
64
 
 
65
#define GAIA_GML_UNKNOWN                0
 
66
#define GAIA_GML_POINT                  1
 
67
#define GAIA_GML_LINESTRING             2
 
68
#define GAIA_GML_CURVE                  3
 
69
#define GAIA_GML_POLYGON                4
 
70
#define GAIA_GML_MULTIPOINT             5
 
71
#define GAIA_GML_MULTILINESTRING        6
 
72
#define GAIA_GML_MULTICURVE             7
 
73
#define GAIA_GML_MULTIPOLYGON           8
 
74
#define GAIA_GML_MULTISURFACE           9
 
75
#define GAIA_GML_MULTIGEOMETRY          10
 
76
 
 
77
/*
 
78
** This is a linked-list struct to store all the values for each token.
 
79
*/
 
80
typedef struct gmlFlexTokenStruct
 
81
{
 
82
    char *value;
 
83
    struct gmlFlexTokenStruct *Next;
 
84
} gmlFlexToken;
 
85
 
 
86
typedef struct gml_coord
 
87
{
 
88
    char *Value;
 
89
    struct gml_coord *Next;
 
90
} gmlCoord;
 
91
typedef gmlCoord *gmlCoordPtr;
 
92
 
 
93
typedef struct gml_attr
 
94
{
 
95
    char *Key;
 
96
    char *Value;
 
97
    struct gml_attr *Next;
 
98
} gmlAttr;
 
99
typedef gmlAttr *gmlAttrPtr;
 
100
 
 
101
typedef struct gml_node
 
102
{
 
103
    char *Tag;
 
104
    int Type;
 
105
    int Error;
 
106
    struct gml_attr *Attributes;
 
107
    struct gml_coord *Coordinates;
 
108
    struct gml_node *Next;
 
109
} gmlNode;
 
110
typedef gmlNode *gmlNodePtr;
 
111
 
 
112
typedef struct gml_dynamic_ring
 
113
{
 
114
    gaiaDynamicLinePtr ring;
 
115
    int interior;
 
116
    int has_z;
 
117
    struct gml_dynamic_ring *next;
 
118
} gmlDynamicRing;
 
119
typedef gmlDynamicRing *gmlDynamicRingPtr;
 
120
 
 
121
typedef struct gml_dynamic_polygon
 
122
{
 
123
    struct gml_dynamic_ring *first;
 
124
    struct gml_dynamic_ring *last;
 
125
} gmlDynamicPolygon;
 
126
typedef gmlDynamicPolygon *gmlDynamicPolygonPtr;
 
127
 
 
128
static void
 
129
gml_proj_params (sqlite3 * sqlite, int srid, char *proj_params)
 
130
{
 
131
/* retrives the PROJ params from SPATIAL_SYS_REF table, if possible */
 
132
    char sql[256];
 
133
    char **results;
 
134
    int rows;
 
135
    int columns;
 
136
    int i;
 
137
    int ret;
 
138
    char *errMsg = NULL;
 
139
    *proj_params = '\0';
 
140
    sprintf (sql,
 
141
             "SELECT proj4text FROM spatial_ref_sys WHERE srid = %d", srid);
 
142
    ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
 
143
    if (ret != SQLITE_OK)
 
144
      {
 
145
          fprintf (stderr, "unknown SRID: %d\t<%s>\n", srid, errMsg);
 
146
          sqlite3_free (errMsg);
 
147
          return;
 
148
      }
 
149
    for (i = 1; i <= rows; i++)
 
150
        strcpy (proj_params, results[(i * columns)]);
 
151
    if (*proj_params == '\0')
 
152
        fprintf (stderr, "unknown SRID: %d\n", srid);
 
153
    sqlite3_free_table (results);
 
154
}
 
155
 
 
156
static gmlDynamicPolygonPtr
 
157
gml_alloc_dyn_polygon (void)
 
158
{
 
159
/* creating a dynamic polygon (ring collection) */
 
160
    gmlDynamicPolygonPtr p = malloc (sizeof (gmlDynamicPolygon));
 
161
    p->first = NULL;
 
162
    p->last = NULL;
 
163
    return p;
 
164
}
 
165
 
 
166
static void
 
167
gml_free_dyn_polygon (gmlDynamicPolygonPtr dyn)
 
168
{
 
169
/* deleting a dynamic polygon (ring collection) */
 
170
    gmlDynamicRingPtr r;
 
171
    gmlDynamicRingPtr rn;
 
172
    if (!dyn)
 
173
        return;
 
174
    r = dyn->first;
 
175
    while (r)
 
176
      {
 
177
          rn = r->next;
 
178
          if (r->ring)
 
179
              gaiaFreeDynamicLine (r->ring);
 
180
          free (r);
 
181
          r = rn;
 
182
      }
 
183
    free (dyn);
 
184
}
 
185
 
 
186
static void
 
187
gml_add_polygon_ring (gmlDynamicPolygonPtr dyn_pg, gaiaDynamicLinePtr dyn,
 
188
                      int interior, int has_z)
 
189
{
 
190
/* inserting a further ring into the collection (dynamic polygon) */
 
191
    gmlDynamicRingPtr p = malloc (sizeof (gmlDynamicRing));
 
192
    p->ring = dyn;
 
193
    p->interior = interior;
 
194
    p->has_z = has_z;
 
195
    p->next = NULL;
 
196
    if (dyn_pg->first == NULL)
 
197
        dyn_pg->first = p;
 
198
    if (dyn_pg->last != NULL)
 
199
        dyn_pg->last->next = p;
 
200
    dyn_pg->last = p;
 
201
}
 
202
 
 
203
static void
 
204
gml_freeString (char **ptr)
 
205
{
 
206
/* releasing a string from the lexer */
 
207
    if (*ptr != NULL)
 
208
        free (*ptr);
 
209
    *ptr = NULL;
 
210
}
 
211
 
 
212
static void
 
213
gml_saveString (char **ptr, const char *str)
 
214
{
 
215
/* saving a string from the lexer */
 
216
    int len = strlen (str);
 
217
    gml_freeString (ptr);
 
218
    *ptr = malloc (len + 1);
 
219
    strcpy (*ptr, str);
 
220
}
 
221
 
 
222
static gmlCoordPtr
 
223
gml_coord (void *value)
 
224
{
 
225
/* creating a coord Item */
 
226
    int len;
 
227
    gmlFlexToken *tok = (gmlFlexToken *) value;
 
228
    gmlCoordPtr c = malloc (sizeof (gmlCoord));
 
229
    len = strlen (tok->value);
 
230
    c->Value = malloc (len + 1);
 
231
    strcpy (c->Value, tok->value);
 
232
    c->Next = NULL;
 
233
    return c;
 
234
}
 
235
 
 
236
static void
 
237
gml_freeCoordinate (gmlCoordPtr c)
 
238
{
 
239
/* deleting a GML coordinate */
 
240
    if (c == NULL)
 
241
        return;
 
242
    if (c->Value)
 
243
        free (c->Value);
 
244
    free (c);
 
245
}
 
246
 
 
247
static gmlAttrPtr
 
248
gml_attribute (void *key, void *value)
 
249
{
 
250
/* creating an attribute */
 
251
    int len;
 
252
    gmlFlexToken *k_tok = (gmlFlexToken *) key;
 
253
    gmlFlexToken *v_tok = (gmlFlexToken *) value;
 
254
    gmlAttrPtr a = malloc (sizeof (gmlAttr));
 
255
    len = strlen (k_tok->value);
 
256
    a->Key = malloc (len + 1);
 
257
    strcpy (a->Key, k_tok->value);
 
258
    len = strlen (v_tok->value);
 
259
/* we need to de-quote the string, removing first and last ".." */
 
260
    if (*(v_tok->value + 0) == '"' && *(v_tok->value + len - 1) == '"')
 
261
      {
 
262
          a->Value = malloc (len - 1);
 
263
          memcpy (a->Value, v_tok->value + 1, len - 1);
 
264
          *(a->Value + len - 1) = '\0';
 
265
      }
 
266
    else
 
267
      {
 
268
          a->Value = malloc (len + 1);
 
269
          strcpy (a->Value, v_tok->value);
 
270
      }
 
271
    a->Next = NULL;
 
272
    return a;
 
273
}
 
274
 
 
275
static void
 
276
gml_freeAttribute (gmlAttrPtr a)
 
277
{
 
278
/* deleting a GML attribute */
 
279
    if (a == NULL)
 
280
        return;
 
281
    if (a->Key)
 
282
        free (a->Key);
 
283
    if (a->Value)
 
284
        free (a->Value);
 
285
    free (a);
 
286
}
 
287
 
 
288
static void
 
289
gml_freeNode (gmlNodePtr n)
 
290
{
 
291
/* deleting a GML node */
 
292
    gmlAttrPtr a;
 
293
    gmlAttrPtr an;
 
294
    gmlCoordPtr c;
 
295
    gmlCoordPtr cn;
 
296
    if (n == NULL)
 
297
        return;
 
298
    a = n->Attributes;
 
299
    while (a)
 
300
      {
 
301
          an = a->Next;
 
302
          gml_freeAttribute (a);
 
303
          a = an;
 
304
      }
 
305
    c = n->Coordinates;
 
306
    while (c)
 
307
      {
 
308
          cn = c->Next;
 
309
          gml_freeCoordinate (c);
 
310
          c = cn;
 
311
      }
 
312
    if (n->Tag)
 
313
        free (n->Tag);
 
314
    free (n);
 
315
}
 
316
 
 
317
static void
 
318
gml_freeTree (gmlNodePtr t)
 
319
{
 
320
/* deleting a GML tree */
 
321
    gmlNodePtr n;
 
322
    gmlNodePtr nn;
 
323
    n = t;
 
324
    while (n)
 
325
      {
 
326
          nn = n->Next;
 
327
          gml_freeNode (n);
 
328
          n = nn;
 
329
      }
 
330
}
 
331
 
 
332
static gmlNodePtr
 
333
gml_createNode (void *tag, void *attributes, void *coords)
 
334
{
 
335
/* creating a node */
 
336
    int len;
 
337
    gmlFlexToken *tok = (gmlFlexToken *) tag;
 
338
    gmlNodePtr n = malloc (sizeof (gmlNode));
 
339
    len = strlen (tok->value);
 
340
    n->Tag = malloc (len + 1);
 
341
    strcpy (n->Tag, tok->value);
 
342
    n->Type = GML_PARSER_OPEN_NODE;
 
343
    n->Error = 0;
 
344
    n->Attributes = attributes;
 
345
    n->Coordinates = coords;
 
346
    n->Next = NULL;
 
347
    return n;
 
348
}
 
349
 
 
350
static gmlNodePtr
 
351
gml_createSelfClosedNode (void *tag, void *attributes)
 
352
{
 
353
/* creating a self-closed node */
 
354
    int len;
 
355
    gmlFlexToken *tok = (gmlFlexToken *) tag;
 
356
    gmlNodePtr n = malloc (sizeof (gmlNode));
 
357
    len = strlen (tok->value);
 
358
    n->Tag = malloc (len + 1);
 
359
    strcpy (n->Tag, tok->value);
 
360
    n->Type = GML_PARSER_SELF_CLOSED_NODE;
 
361
    n->Error = 0;
 
362
    n->Attributes = attributes;
 
363
    n->Coordinates = NULL;
 
364
    n->Next = NULL;
 
365
    return n;
 
366
}
 
367
 
 
368
static gmlNodePtr
 
369
gml_closingNode (void *tag)
 
370
{
 
371
/* creating a closing node */
 
372
    int len;
 
373
    gmlFlexToken *tok = (gmlFlexToken *) tag;
 
374
    gmlNodePtr n = malloc (sizeof (gmlNode));
 
375
    len = strlen (tok->value);
 
376
    n->Tag = malloc (len + 1);
 
377
    strcpy (n->Tag, tok->value);
 
378
    n->Type = GML_PARSER_CLOSED_NODE;
 
379
    n->Error = 0;
 
380
    n->Attributes = NULL;
 
381
    n->Coordinates = NULL;
 
382
    n->Next = NULL;
 
383
    return n;
 
384
}
 
385
 
 
386
static int
 
387
gml_cleanup (gmlFlexToken * token)
 
388
{
 
389
    gmlFlexToken *ptok;
 
390
    gmlFlexToken *ptok_n;
 
391
    if (token == NULL)
 
392
        return 0;
 
393
    ptok = token;
 
394
    while (ptok)
 
395
      {
 
396
          ptok_n = ptok->Next;
 
397
          if (ptok->value != NULL)
 
398
              free (ptok->value);
 
399
          free (ptok);
 
400
          ptok = ptok_n;
 
401
      }
 
402
    return 0;
 
403
}
 
404
 
 
405
static void
 
406
gml_xferString (char **p, const char *str)
 
407
{
 
408
/* saving some token */
 
409
    int len;
 
410
    if (str == NULL)
 
411
      {
 
412
          *p = NULL;
 
413
          return;
 
414
      }
 
415
    len = strlen (str);
 
416
    *p = malloc (len + 1);
 
417
    strcpy (*p, str);
 
418
}
 
419
 
 
420
static int
 
421
guessGmlSrid (gmlNodePtr node)
 
422
{
 
423
/* attempting to guess the SRID */
 
424
    int len;
 
425
    gmlAttrPtr attr = node->Attributes;
 
426
    while (attr)
 
427
      {
 
428
          if (strcmp (attr->Key, "srsName") == 0)
 
429
            {
 
430
                len = strlen (attr->Value);
 
431
                if (len > 5)
 
432
                  {
 
433
                      if (strncmp (attr->Value, "EPSG:", 5) == 0)
 
434
                          return atoi (attr->Value + 5);
 
435
                  }
 
436
                if (len > 21)
 
437
                  {
 
438
                      if (strncmp (attr->Value, "urn:ogc:def:crs:EPSG:", 21) ==
 
439
                          0)
 
440
                        {
 
441
                            int i = strlen (attr->Value) - 1;
 
442
                            for (; i >= 0; i--)
 
443
                              {
 
444
                                  if (*(attr->Value + i) == ':')
 
445
                                      return atoi (attr->Value + i + 1);
 
446
                              }
 
447
                        }
 
448
                  }
 
449
            }
 
450
          attr = attr->Next;
 
451
      }
 
452
    return -1;
 
453
}
 
454
 
 
455
static int
 
456
gml_get_srsDimension (gmlNodePtr node)
 
457
{
 
458
/* attempting to establis if there is a Z coordinate */
 
459
    gmlAttrPtr attr = node->Attributes;
 
460
    while (attr)
 
461
      {
 
462
          if (strcmp (attr->Key, "srsDimension") == 0)
 
463
            {
 
464
                if (atoi (attr->Value) == 3)
 
465
                    return 1;
 
466
                else
 
467
                    return 0;
 
468
            }
 
469
          attr = attr->Next;
 
470
      }
 
471
    return 0;
 
472
}
 
473
 
 
474
static int
 
475
guessGmlGeometryType (gmlNodePtr node)
 
476
{
 
477
/* attempting to guess the Geometry Type for a GML node */
 
478
    int type = GAIA_GML_UNKNOWN;
 
479
    if (strcmp (node->Tag, "gml:Point") == 0
 
480
        || strcmp (node->Tag, "Point") == 0)
 
481
        type = GAIA_GML_POINT;
 
482
    if (strcmp (node->Tag, "gml:LineString") == 0
 
483
        || strcmp (node->Tag, "LineString") == 0)
 
484
        type = GAIA_GML_LINESTRING;
 
485
    if (strcmp (node->Tag, "gml:Curve") == 0
 
486
        || strcmp (node->Tag, "Curve") == 0)
 
487
        type = GAIA_GML_CURVE;
 
488
    if (strcmp (node->Tag, "gml:Polygon") == 0
 
489
        || strcmp (node->Tag, "Polygon") == 0)
 
490
        type = GAIA_GML_POLYGON;
 
491
    if (strcmp (node->Tag, "gml:MultiPoint") == 0
 
492
        || strcmp (node->Tag, "MultiPoint") == 0)
 
493
        type = GAIA_GML_MULTIPOINT;
 
494
    if (strcmp (node->Tag, "gml:MultiLineString") == 0
 
495
        || strcmp (node->Tag, "MultiLineString") == 0)
 
496
        type = GAIA_GML_MULTILINESTRING;
 
497
    if (strcmp (node->Tag, "gml:MultiCurve") == 0
 
498
        || strcmp (node->Tag, "MultiCurve") == 0)
 
499
        type = GAIA_GML_MULTICURVE;
 
500
    if (strcmp (node->Tag, "gml:MultiPolygon") == 0
 
501
        || strcmp (node->Tag, "MultiPolygon") == 0)
 
502
        type = GAIA_GML_MULTIPOLYGON;
 
503
    if (strcmp (node->Tag, "gml:MultiSurface") == 0
 
504
        || strcmp (node->Tag, "MultiSurface") == 0)
 
505
        type = GAIA_GML_MULTISURFACE;
 
506
    if (strcmp (node->Tag, "gml:MultiGeometry") == 0
 
507
        || strcmp (node->Tag, "MultiGeometry") == 0)
 
508
        type = GAIA_GML_MULTIGEOMETRY;
 
509
    return type;
 
510
}
 
511
 
 
512
static int
 
513
gml_check_coord (const char *value)
 
514
{
 
515
/* checking a GML coordinate */
 
516
    int decimal = 0;
 
517
    const char *p = value;
 
518
    if (*p == '+' || *p == '-')
 
519
        p++;
 
520
    while (*p != '\0')
 
521
      {
 
522
          if (*p == '.')
 
523
            {
 
524
                if (!decimal)
 
525
                    decimal = 1;
 
526
                else
 
527
                    return 0;
 
528
            }
 
529
          else if (*p >= '0' && *p <= '9')
 
530
              ;
 
531
          else
 
532
              return 0;
 
533
          p++;
 
534
      }
 
535
    return 1;
 
536
}
 
537
 
 
538
static int
 
539
gml_extract_coords (const char *value, double *x, double *y, double *z,
 
540
                    int *count)
 
541
{
 
542
/* extracting GML v2.x coords from a comma-separated string */
 
543
    const char *in = value;
 
544
    char buf[1024];
 
545
    char *out = buf;
 
546
    *out = '\0';
 
547
 
 
548
    while (*in != '\0')
 
549
      {
 
550
          if (*in == ',')
 
551
            {
 
552
                *out = '\0';
 
553
                if (*buf != '\0')
 
554
                  {
 
555
                      if (!gml_check_coord (buf))
 
556
                          return 0;
 
557
                      switch (*count)
 
558
                        {
 
559
                        case 0:
 
560
                            *x = atof (buf);
 
561
                            *count += 1;
 
562
                            break;
 
563
                        case 1:
 
564
                            *y = atof (buf);
 
565
                            *count += 1;
 
566
                            break;
 
567
                        case 2:
 
568
                            *z = atof (buf);
 
569
                            *count += 1;
 
570
                            break;
 
571
                        default:
 
572
                            *count += 1;
 
573
                            break;
 
574
                        };
 
575
                  }
 
576
                in++;
 
577
                out = buf;
 
578
                *out = '\0';
 
579
                continue;
 
580
            }
 
581
          *out++ = *in++;
 
582
      }
 
583
    *out = '\0';
 
584
/* parsing the last item */
 
585
    if (*buf != '\0')
 
586
      {
 
587
          if (!gml_check_coord (buf))
 
588
              return 0;
 
589
          switch (*count)
 
590
            {
 
591
            case 0:
 
592
                *x = atof (buf);
 
593
                *count += 1;
 
594
                break;
 
595
            case 1:
 
596
                *y = atof (buf);
 
597
                *count += 1;
 
598
                break;
 
599
            case 2:
 
600
                *z = atof (buf);
 
601
                *count += 1;
 
602
                break;
 
603
            default:
 
604
                *count += 1;
 
605
                break;
 
606
            };
 
607
      }
 
608
    return 1;
 
609
}
 
610
 
 
611
static int
 
612
gml_parse_point_v2 (gmlCoordPtr coord, double *x, double *y, double *z,
 
613
                    int *has_z)
 
614
{
 
615
/* parsing GML v2.x <gml:coordinates> [Point] */
 
616
    int count = 0;
 
617
    gmlCoordPtr c = coord;
 
618
    while (c)
 
619
      {
 
620
          if (!gml_extract_coords (c->Value, x, y, z, &count))
 
621
              return 0;
 
622
          c = c->Next;
 
623
      }
 
624
    if (count == 2)
 
625
      {
 
626
          *has_z = 0;
 
627
          return 1;
 
628
      }
 
629
    if (count == 3)
 
630
      {
 
631
          *has_z = 1;
 
632
          return 1;
 
633
      }
 
634
    return 0;
 
635
}
 
636
 
 
637
static int
 
638
gml_parse_point_v3 (gmlCoordPtr coord, double *x, double *y, double *z,
 
639
                    int *has_z)
 
640
{
 
641
/* parsing GML v2.x <gml:pos> [Point] */
 
642
    int count = 0;
 
643
    gmlCoordPtr c = coord;
 
644
    while (c)
 
645
      {
 
646
          if (!gml_check_coord (c->Value))
 
647
              return 0;
 
648
          switch (count)
 
649
            {
 
650
            case 0:
 
651
                *x = atof (c->Value);
 
652
                count++;
 
653
                break;
 
654
            case 1:
 
655
                *y = atof (c->Value);
 
656
                count++;
 
657
                break;
 
658
            case 2:
 
659
                *z = atof (c->Value);
 
660
                count++;
 
661
                break;
 
662
            default:
 
663
                count++;
 
664
                break;
 
665
            };
 
666
          c = c->Next;
 
667
      }
 
668
    if (count == 2)
 
669
      {
 
670
          *has_z = 0;
 
671
          return 1;
 
672
      }
 
673
    if (count == 3)
 
674
      {
 
675
          *has_z = 1;
 
676
          return 1;
 
677
      }
 
678
    return 0;
 
679
}
 
680
 
 
681
static int
 
682
gml_parse_point (gaiaGeomCollPtr geom, gmlNodePtr node, int srid,
 
683
                 gmlNodePtr * next)
 
684
{
 
685
/* parsing a <gml:Point> */
 
686
    double x;
 
687
    double y;
 
688
    double z;
 
689
    int has_z;
 
690
    gaiaGeomCollPtr pt;
 
691
    gaiaGeomCollPtr last;
 
692
 
 
693
    if (strcmp (node->Tag, "gml:coordinates") == 0
 
694
        || strcmp (node->Tag, "coordinates") == 0)
 
695
      {
 
696
          /* parsing a GML v.2.x <gml:Point> */
 
697
          if (!gml_parse_point_v2 (node->Coordinates, &x, &y, &z, &has_z))
 
698
              return 0;
 
699
          node = node->Next;
 
700
          if (node == NULL)
 
701
              return 0;
 
702
          if (strcmp (node->Tag, "gml:coordinates") == 0
 
703
              || strcmp (node->Tag, "coordinates") == 0)
 
704
              ;
 
705
          else
 
706
              return 0;
 
707
          node = node->Next;
 
708
          if (node == NULL)
 
709
              return 0;
 
710
          if (strcmp (node->Tag, "gml:Point") == 0
 
711
              || strcmp (node->Tag, "Point") == 0)
 
712
              ;
 
713
          else
 
714
              return 0;
 
715
          *next = node->Next;
 
716
          goto ok;
 
717
      }
 
718
    if (strcmp (node->Tag, "gml:pos") == 0 || strcmp (node->Tag, "pos") == 0)
 
719
      {
 
720
          /* parsing a GML v.3.x <gml:Point> */
 
721
          if (!gml_parse_point_v3 (node->Coordinates, &x, &y, &z, &has_z))
 
722
              return 0;
 
723
          node = node->Next;
 
724
          if (node == NULL)
 
725
              return 0;
 
726
          if (strcmp (node->Tag, "gml:pos") == 0
 
727
              || strcmp (node->Tag, "pos") == 0)
 
728
              ;
 
729
          else
 
730
              return 0;
 
731
          node = node->Next;
 
732
          if (node == NULL)
 
733
              return 0;
 
734
          if (strcmp (node->Tag, "gml:Point") == 0
 
735
              || strcmp (node->Tag, "Point") == 0)
 
736
              ;
 
737
          else
 
738
              return 0;
 
739
          *next = node->Next;
 
740
          goto ok;
 
741
      }
 
742
    return 0;
 
743
 
 
744
  ok:
 
745
/* ok, GML nodes match as expected */
 
746
    if (has_z)
 
747
      {
 
748
          pt = gaiaAllocGeomCollXYZ ();
 
749
          pt->Srid = srid;
 
750
          gaiaAddPointToGeomCollXYZ (pt, x, y, z);
 
751
      }
 
752
    else
 
753
      {
 
754
          pt = gaiaAllocGeomColl ();
 
755
          pt->Srid = srid;
 
756
          gaiaAddPointToGeomColl (pt, x, y);
 
757
      }
 
758
    last = geom;
 
759
    while (1)
 
760
      {
 
761
          /* searching the last Geometry within chain */
 
762
          if (last->Next == NULL)
 
763
              break;
 
764
          last = last->Next;
 
765
      }
 
766
    last->Next = pt;
 
767
    return 1;
 
768
}
 
769
 
 
770
static int
 
771
gml_extract_multi_coord (const char *value, double *x, double *y, double *z,
 
772
                         int *count, int *follow)
 
773
{
 
774
/* extracting GML v2.x coords from a comma-separated string */
 
775
    const char *in = value;
 
776
    char buf[1024];
 
777
    char *out = buf;
 
778
    int last;
 
779
    *out = '\0';
 
780
    while (*in != '\0')
 
781
      {
 
782
          last = *in;
 
783
          if (*in == ',')
 
784
            {
 
785
                *out = '\0';
 
786
                if (*buf != '\0')
 
787
                  {
 
788
                      if (!gml_check_coord (buf))
 
789
                          return 0;
 
790
                      switch (*count)
 
791
                        {
 
792
                        case 0:
 
793
                            *x = atof (buf);
 
794
                            *count += 1;
 
795
                            break;
 
796
                        case 1:
 
797
                            *y = atof (buf);
 
798
                            *count += 1;
 
799
                            break;
 
800
                        case 2:
 
801
                            *z = atof (buf);
 
802
                            *count += 1;
 
803
                            break;
 
804
                        default:
 
805
                            *count += 1;
 
806
                            break;
 
807
                        };
 
808
                  }
 
809
                in++;
 
810
                out = buf;
 
811
                *out = '\0';
 
812
                continue;
 
813
            }
 
814
          *out++ = *in++;
 
815
      }
 
816
    *out = '\0';
 
817
/* parsing the last item */
 
818
    if (*buf != '\0')
 
819
      {
 
820
          if (!gml_check_coord (buf))
 
821
              return 0;
 
822
          switch (*count)
 
823
            {
 
824
            case 0:
 
825
                *x = atof (buf);
 
826
                *count += 1;
 
827
                break;
 
828
            case 1:
 
829
                *y = atof (buf);
 
830
                *count += 1;
 
831
                break;
 
832
            case 2:
 
833
                *z = atof (buf);
 
834
                *count += 1;
 
835
                break;
 
836
            default:
 
837
                *count += 1;
 
838
                break;
 
839
            };
 
840
      }
 
841
    if (last == ',')
 
842
        *follow = 1;
 
843
    else
 
844
        *follow = 0;
 
845
    return 1;
 
846
}
 
847
 
 
848
static int
 
849
gml_extract_multi_coords (gmlCoordPtr coord, double *x, double *y, double *z,
 
850
                          int *count, gmlCoordPtr * next)
 
851
{
 
852
/* extracting GML v2.x coords from a comma-separated string */
 
853
    int follow;
 
854
    gmlCoordPtr c = coord;
 
855
    while (c)
 
856
      {
 
857
          if (!gml_extract_multi_coord (c->Value, x, y, z, count, &follow))
 
858
              return 0;
 
859
          if (!follow && c->Next != NULL)
 
860
            {
 
861
                if (*(c->Next->Value) == ',')
 
862
                    follow = 1;
 
863
            }
 
864
          if (follow)
 
865
              c = c->Next;
 
866
          else
 
867
            {
 
868
                *next = c->Next;
 
869
                break;
 
870
            }
 
871
      }
 
872
    return 1;
 
873
}
 
874
 
 
875
static void
 
876
gml_add_point_to_line (gaiaDynamicLinePtr dyn, double x, double y)
 
877
{
 
878
/* appending a point */
 
879
    gaiaAppendPointToDynamicLine (dyn, x, y);
 
880
}
 
881
 
 
882
static void
 
883
gml_add_point_to_lineZ (gaiaDynamicLinePtr dyn, double x, double y, double z)
 
884
{
 
885
/* appending a point */
 
886
    gaiaAppendPointZToDynamicLine (dyn, x, y, z);
 
887
}
 
888
 
 
889
static int
 
890
gml_parse_coordinates (gmlCoordPtr coord, gaiaDynamicLinePtr dyn, int *has_z)
 
891
{
 
892
/* parsing GML v2.x <gml:coordinates> [Linestring or Ring] */
 
893
    int count = 0;
 
894
    double x;
 
895
    double y;
 
896
    double z;
 
897
    gmlCoordPtr next;
 
898
    gmlCoordPtr c = coord;
 
899
    while (c)
 
900
      {
 
901
          if (!gml_extract_multi_coords (c, &x, &y, &z, &count, &next))
 
902
              return 0;
 
903
          if (count == 2)
 
904
            {
 
905
                *has_z = 0;
 
906
                gml_add_point_to_line (dyn, x, y);
 
907
                count = 0;
 
908
            }
 
909
          else if (count == 3)
 
910
            {
 
911
                gml_add_point_to_lineZ (dyn, x, y, z);
 
912
                count = 0;
 
913
            }
 
914
          else
 
915
              return 0;
 
916
          c = next;
 
917
      }
 
918
    return 1;
 
919
}
 
920
 
 
921
static int
 
922
gml_parse_posList (gmlCoordPtr coord, gaiaDynamicLinePtr dyn, int has_z)
 
923
{
 
924
/* parsing GML v3.x <gml:posList> [Linestring or Ring] */
 
925
    int count = 0;
 
926
    double x;
 
927
    double y;
 
928
    double z;
 
929
    gmlCoordPtr c = coord;
 
930
    while (c)
 
931
      {
 
932
          if (!gml_check_coord (c->Value))
 
933
              return 0;
 
934
          if (!has_z)
 
935
            {
 
936
                switch (count)
 
937
                  {
 
938
                  case 0:
 
939
                      x = atof (c->Value);
 
940
                      count++;
 
941
                      break;
 
942
                  case 1:
 
943
                      y = atof (c->Value);
 
944
                      gml_add_point_to_line (dyn, x, y);
 
945
                      count = 0;
 
946
                      break;
 
947
                  };
 
948
            }
 
949
          else
 
950
            {
 
951
                switch (count)
 
952
                  {
 
953
                  case 0:
 
954
                      x = atof (c->Value);
 
955
                      count++;
 
956
                      break;
 
957
                  case 1:
 
958
                      y = atof (c->Value);
 
959
                      count++;
 
960
                      break;
 
961
                  case 2:
 
962
                      z = atof (c->Value);
 
963
                      gml_add_point_to_lineZ (dyn, x, y, z);
 
964
                      count = 0;
 
965
                      break;
 
966
                  };
 
967
            }
 
968
          c = c->Next;
 
969
      }
 
970
    if (count != 0)
 
971
        return 0;
 
972
    return 1;
 
973
}
 
974
 
 
975
static int
 
976
gml_count_dyn_points (gaiaDynamicLinePtr dyn)
 
977
{
 
978
/* count how many vertices are into sone linestring/ring */
 
979
    int iv = 0;
 
980
    gaiaPointPtr pt = dyn->First;
 
981
    while (pt)
 
982
      {
 
983
          iv++;
 
984
          pt = pt->Next;
 
985
      }
 
986
    return iv;
 
987
}
 
988
 
 
989
static int
 
990
gml_parse_linestring (gaiaGeomCollPtr geom, gmlNodePtr node, int srid,
 
991
                      gmlNodePtr * next)
 
992
{
 
993
/* parsing a <gml:LineString> */
 
994
    gaiaGeomCollPtr ln;
 
995
    gaiaGeomCollPtr last;
 
996
    gaiaLinestringPtr new_ln;
 
997
    gaiaPointPtr pt;
 
998
    gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
 
999
    int iv;
 
1000
    int has_z = 1;
 
1001
    int points = 0;
 
1002
 
 
1003
    if (strcmp (node->Tag, "gml:coordinates") == 0
 
1004
        || strcmp (node->Tag, "coordinates") == 0)
 
1005
      {
 
1006
          /* parsing a GML v.2.x <gml:LineString> */
 
1007
          if (!gml_parse_coordinates (node->Coordinates, dyn, &has_z))
 
1008
              goto error;
 
1009
          node = node->Next;
 
1010
          if (node == NULL)
 
1011
              goto error;
 
1012
          if (strcmp (node->Tag, "gml:coordinates") == 0
 
1013
              || strcmp (node->Tag, "coordinates") == 0)
 
1014
              ;
 
1015
          else
 
1016
              goto error;
 
1017
          node = node->Next;
 
1018
          if (node == NULL)
 
1019
              goto error;
 
1020
          if (strcmp (node->Tag, "gml:LineString") == 0
 
1021
              || strcmp (node->Tag, "LineString") == 0)
 
1022
              ;
 
1023
          else
 
1024
              goto error;
 
1025
          *next = node->Next;
 
1026
          goto ok;
 
1027
      }
 
1028
    if (strcmp (node->Tag, "gml:posList") == 0
 
1029
        || strcmp (node->Tag, "posList") == 0)
 
1030
      {
 
1031
          /* parsing a GML v.3.x <gml:LineString> */
 
1032
          has_z = gml_get_srsDimension (node);
 
1033
          if (!gml_parse_posList (node->Coordinates, dyn, has_z))
 
1034
              goto error;
 
1035
          node = node->Next;
 
1036
          if (node == NULL)
 
1037
              goto error;
 
1038
          if (strcmp (node->Tag, "gml:posList") == 0
 
1039
              || strcmp (node->Tag, "posList") == 0)
 
1040
              ;
 
1041
          else
 
1042
              goto error;
 
1043
          node = node->Next;
 
1044
          if (node == NULL)
 
1045
              goto error;
 
1046
          if (strcmp (node->Tag, "gml:LineString") == 0
 
1047
              || strcmp (node->Tag, "LineString") == 0)
 
1048
              ;
 
1049
          else
 
1050
              goto error;
 
1051
          *next = node->Next;
 
1052
          goto ok;
 
1053
      }
 
1054
    goto error;
 
1055
 
 
1056
  ok:
 
1057
/* ok, GML nodes match as expected */
 
1058
    points = gml_count_dyn_points (dyn);
 
1059
    if (points < 2)
 
1060
        goto error;
 
1061
    if (has_z)
 
1062
      {
 
1063
          ln = gaiaAllocGeomCollXYZ ();
 
1064
          ln->Srid = srid;
 
1065
          new_ln = gaiaAddLinestringToGeomColl (ln, points);
 
1066
          pt = dyn->First;
 
1067
          iv = 0;
 
1068
          while (pt)
 
1069
            {
 
1070
                gaiaSetPointXYZ (new_ln->Coords, iv, pt->X, pt->Y, pt->Z);
 
1071
                iv++;
 
1072
                pt = pt->Next;
 
1073
            }
 
1074
      }
 
1075
    else
 
1076
      {
 
1077
          ln = gaiaAllocGeomColl ();
 
1078
          ln->Srid = srid;
 
1079
          new_ln = gaiaAddLinestringToGeomColl (ln, points);
 
1080
          pt = dyn->First;
 
1081
          iv = 0;
 
1082
          while (pt)
 
1083
            {
 
1084
                gaiaSetPoint (new_ln->Coords, iv, pt->X, pt->Y);
 
1085
                iv++;
 
1086
                pt = pt->Next;
 
1087
            }
 
1088
      }
 
1089
    last = geom;
 
1090
    while (1)
 
1091
      {
 
1092
          /* searching the last Geometry within chain */
 
1093
          if (last->Next == NULL)
 
1094
              break;
 
1095
          last = last->Next;
 
1096
      }
 
1097
    last->Next = ln;
 
1098
    gaiaFreeDynamicLine (dyn);
 
1099
    return 1;
 
1100
 
 
1101
  error:
 
1102
    gaiaFreeDynamicLine (dyn);
 
1103
    return 0;
 
1104
}
 
1105
 
 
1106
static int
 
1107
gml_parse_curve (gaiaGeomCollPtr geom, gmlNodePtr node, int srid,
 
1108
                 gmlNodePtr * next)
 
1109
{
 
1110
/* parsing a <gml:Curve> */
 
1111
    gaiaGeomCollPtr ln;
 
1112
    gaiaGeomCollPtr last;
 
1113
    gaiaLinestringPtr new_ln;
 
1114
    gaiaPointPtr pt;
 
1115
    gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
 
1116
    int iv;
 
1117
    int has_z = 1;
 
1118
    int points = 0;
 
1119
 
 
1120
    if (strcmp (node->Tag, "gml:segments") == 0
 
1121
        || strcmp (node->Tag, "segments") == 0)
 
1122
      {
 
1123
          /* parsing a GML v.3.x <gml:Curve> */
 
1124
          node = node->Next;
 
1125
          if (node == NULL)
 
1126
              goto error;
 
1127
          if (strcmp (node->Tag, "gml:LineStringSegment") == 0
 
1128
              || strcmp (node->Tag, "LineStringSegment") == 0)
 
1129
              ;
 
1130
          else
 
1131
              goto error;
 
1132
          node = node->Next;
 
1133
          if (node == NULL)
 
1134
              goto error;
 
1135
          if (strcmp (node->Tag, "gml:posList") == 0
 
1136
              || strcmp (node->Tag, "posList") == 0)
 
1137
              ;
 
1138
          else
 
1139
              goto error;
 
1140
          has_z = gml_get_srsDimension (node);
 
1141
          if (!gml_parse_posList (node->Coordinates, dyn, has_z))
 
1142
              goto error;
 
1143
          node = node->Next;
 
1144
          if (node == NULL)
 
1145
              goto error;
 
1146
          if (strcmp (node->Tag, "gml:posList") == 0
 
1147
              || strcmp (node->Tag, "posList") == 0)
 
1148
              ;
 
1149
          else
 
1150
              goto error;
 
1151
          node = node->Next;
 
1152
          if (node == NULL)
 
1153
              goto error;
 
1154
          if (strcmp (node->Tag, "gml:LineStringSegment") == 0
 
1155
              || strcmp (node->Tag, "LineStringSegment") == 0)
 
1156
              ;
 
1157
          else
 
1158
              goto error;
 
1159
          node = node->Next;
 
1160
          if (node == NULL)
 
1161
              goto error;
 
1162
          if (strcmp (node->Tag, "gml:segments") == 0
 
1163
              || strcmp (node->Tag, "segments") == 0)
 
1164
              ;
 
1165
          else
 
1166
              goto error;
 
1167
          node = node->Next;
 
1168
          if (node == NULL)
 
1169
              goto error;
 
1170
          if (strcmp (node->Tag, "gml:Curve") == 0
 
1171
              || strcmp (node->Tag, "Curve") == 0)
 
1172
              ;
 
1173
          else
 
1174
              goto error;
 
1175
          *next = node->Next;
 
1176
          goto ok;
 
1177
      }
 
1178
    goto error;
 
1179
 
 
1180
  ok:
 
1181
/* ok, GML nodes match as expected */
 
1182
    points = gml_count_dyn_points (dyn);
 
1183
    if (points < 2)
 
1184
        goto error;
 
1185
    if (has_z)
 
1186
      {
 
1187
          ln = gaiaAllocGeomCollXYZ ();
 
1188
          ln->Srid = srid;
 
1189
          new_ln = gaiaAddLinestringToGeomColl (ln, points);
 
1190
          pt = dyn->First;
 
1191
          iv = 0;
 
1192
          while (pt)
 
1193
            {
 
1194
                gaiaSetPointXYZ (new_ln->Coords, iv, pt->X, pt->Y, pt->Z);
 
1195
                iv++;
 
1196
                pt = pt->Next;
 
1197
            }
 
1198
      }
 
1199
    else
 
1200
      {
 
1201
          ln = gaiaAllocGeomColl ();
 
1202
          ln->Srid = srid;
 
1203
          new_ln = gaiaAddLinestringToGeomColl (ln, points);
 
1204
          pt = dyn->First;
 
1205
          iv = 0;
 
1206
          while (pt)
 
1207
            {
 
1208
                gaiaSetPoint (new_ln->Coords, iv, pt->X, pt->Y);
 
1209
                iv++;
 
1210
                pt = pt->Next;
 
1211
            }
 
1212
      }
 
1213
    last = geom;
 
1214
    while (1)
 
1215
      {
 
1216
          /* searching the last Geometry within chain */
 
1217
          if (last->Next == NULL)
 
1218
              break;
 
1219
          last = last->Next;
 
1220
      }
 
1221
    last->Next = ln;
 
1222
    gaiaFreeDynamicLine (dyn);
 
1223
    return 1;
 
1224
 
 
1225
  error:
 
1226
    gaiaFreeDynamicLine (dyn);
 
1227
    return 0;
 
1228
}
 
1229
 
 
1230
static gaiaDynamicLinePtr
 
1231
gml_parse_ring (gmlNodePtr node, int *interior, int *has_z, gmlNodePtr * next)
 
1232
{
 
1233
/* parsing a generic GML ring */
 
1234
    gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
 
1235
    *has_z = 1;
 
1236
 
 
1237
    if (strcmp (node->Tag, "gml:outerBoundaryIs") == 0
 
1238
        || strcmp (node->Tag, "outerBoundaryIs") == 0)
 
1239
      {
 
1240
          /* parsing a GML v.2.x <gml:outerBoundaryIs> */
 
1241
          node = node->Next;
 
1242
          if (node == NULL)
 
1243
              goto error;
 
1244
          if (strcmp (node->Tag, "gml:LinearRing") == 0
 
1245
              || strcmp (node->Tag, "LinearRing") == 0)
 
1246
              ;
 
1247
          else
 
1248
              goto error;
 
1249
          node = node->Next;
 
1250
          if (node == NULL)
 
1251
              goto error;
 
1252
          if (strcmp (node->Tag, "gml:coordinates") == 0
 
1253
              || strcmp (node->Tag, "coordinates") == 0)
 
1254
            {
 
1255
                /* parsing a GML v.2.x <gml:coordinates> */
 
1256
                if (!gml_parse_coordinates (node->Coordinates, dyn, has_z))
 
1257
                    goto error;
 
1258
                node = node->Next;
 
1259
                if (node == NULL)
 
1260
                    goto error;
 
1261
                if (strcmp (node->Tag, "gml:coordinates") == 0
 
1262
                    || strcmp (node->Tag, "coordinates") == 0)
 
1263
                    ;
 
1264
                else
 
1265
                    goto error;
 
1266
            }
 
1267
          else if (strcmp (node->Tag, "gml:posList") == 0
 
1268
                   || strcmp (node->Tag, "posList") == 0)
 
1269
            {
 
1270
                /* parsing a GML v.3.x <gml:posList> */
 
1271
                *has_z = gml_get_srsDimension (node);
 
1272
                if (!gml_parse_posList (node->Coordinates, dyn, *has_z))
 
1273
                    goto error;
 
1274
                node = node->Next;
 
1275
                if (node == NULL)
 
1276
                    goto error;
 
1277
                if (strcmp (node->Tag, "gml:posList") == 0
 
1278
                    || strcmp (node->Tag, "posList") == 0)
 
1279
                    ;
 
1280
                else
 
1281
                    goto error;
 
1282
            }
 
1283
          else
 
1284
              goto error;
 
1285
          node = node->Next;
 
1286
          if (node == NULL)
 
1287
              goto error;
 
1288
          if (strcmp (node->Tag, "gml:LinearRing") == 0
 
1289
              || strcmp (node->Tag, "LinearRing") == 0)
 
1290
              ;
 
1291
          else
 
1292
              goto error;
 
1293
          node = node->Next;
 
1294
          if (node == NULL)
 
1295
              goto error;
 
1296
          if (strcmp (node->Tag, "gml:outerBoundaryIs") == 0
 
1297
              || strcmp (node->Tag, "outerBoundaryIs") == 0)
 
1298
              ;
 
1299
          else
 
1300
              goto error;
 
1301
          *interior = 0;
 
1302
          *next = node->Next;
 
1303
          return dyn;
 
1304
      }
 
1305
    if (strcmp (node->Tag, "gml:innerBoundaryIs") == 0
 
1306
        || strcmp (node->Tag, "innerBoundaryIs") == 0)
 
1307
      {
 
1308
          /* parsing a GML v.2.x <gml:innerBoundaryIs> */
 
1309
          node = node->Next;
 
1310
          if (node == NULL)
 
1311
              goto error;
 
1312
          if (strcmp (node->Tag, "gml:LinearRing") == 0
 
1313
              || strcmp (node->Tag, "LinearRing") == 0)
 
1314
              ;
 
1315
          else
 
1316
              goto error;
 
1317
          node = node->Next;
 
1318
          if (node == NULL)
 
1319
              goto error;
 
1320
          if (strcmp (node->Tag, "gml:coordinates") == 0
 
1321
              || strcmp (node->Tag, "coordinates") == 0)
 
1322
            {
 
1323
                /* parsing a GML v.2.x <gml:coordinates> */
 
1324
                if (!gml_parse_coordinates (node->Coordinates, dyn, has_z))
 
1325
                    goto error;
 
1326
                node = node->Next;
 
1327
                if (node == NULL)
 
1328
                    goto error;
 
1329
                if (strcmp (node->Tag, "gml:coordinates") == 0
 
1330
                    || strcmp (node->Tag, "coordinates") == 0)
 
1331
                    ;
 
1332
                else
 
1333
                    goto error;
 
1334
            }
 
1335
          else if (strcmp (node->Tag, "gml:posList") == 0
 
1336
                   || strcmp (node->Tag, "posList") == 0)
 
1337
            {
 
1338
                /* parsing a GML v.3.x <gml:posList> */
 
1339
                *has_z = gml_get_srsDimension (node);
 
1340
                if (!gml_parse_posList (node->Coordinates, dyn, *has_z))
 
1341
                    goto error;
 
1342
                node = node->Next;
 
1343
                if (node == NULL)
 
1344
                    goto error;
 
1345
                if (strcmp (node->Tag, "gml:posList") == 0
 
1346
                    || strcmp (node->Tag, "posList") == 0)
 
1347
                    ;
 
1348
                else
 
1349
                    goto error;
 
1350
            }
 
1351
          else
 
1352
              goto error;
 
1353
          node = node->Next;
 
1354
          if (node == NULL)
 
1355
              goto error;
 
1356
          if (strcmp (node->Tag, "gml:LinearRing") == 0
 
1357
              || strcmp (node->Tag, "LinearRing") == 0)
 
1358
              ;
 
1359
          else
 
1360
              goto error;
 
1361
          node = node->Next;
 
1362
          if (node == NULL)
 
1363
              goto error;
 
1364
          if (strcmp (node->Tag, "gml:innerBoundaryIs") == 0
 
1365
              || strcmp (node->Tag, "innerBoundaryIs") == 0)
 
1366
              ;
 
1367
          else
 
1368
              goto error;
 
1369
          *interior = 1;
 
1370
          *next = node->Next;
 
1371
          return dyn;
 
1372
      }
 
1373
    if (strcmp (node->Tag, "gml:exterior") == 0
 
1374
        || strcmp (node->Tag, "exterior") == 0)
 
1375
      {
 
1376
          /* parsing a GML v.3.x <gml:exterior> */
 
1377
          node = node->Next;
 
1378
          if (node == NULL)
 
1379
              goto error;
 
1380
          if (strcmp (node->Tag, "gml:LinearRing") == 0
 
1381
              || strcmp (node->Tag, "LinearRing") == 0)
 
1382
              ;
 
1383
          else
 
1384
              goto error;
 
1385
          node = node->Next;
 
1386
          if (node == NULL)
 
1387
              goto error;
 
1388
          if (strcmp (node->Tag, "gml:posList") == 0
 
1389
              || strcmp (node->Tag, "posList") == 0)
 
1390
              ;
 
1391
          else
 
1392
              goto error;
 
1393
          *has_z = gml_get_srsDimension (node);
 
1394
          if (!gml_parse_posList (node->Coordinates, dyn, *has_z))
 
1395
              goto error;
 
1396
          node = node->Next;
 
1397
          if (node == NULL)
 
1398
              goto error;
 
1399
          if (strcmp (node->Tag, "gml:posList") == 0
 
1400
              || strcmp (node->Tag, "posList") == 0)
 
1401
              ;
 
1402
          else
 
1403
              goto error;
 
1404
          node = node->Next;
 
1405
          if (node == NULL)
 
1406
              goto error;
 
1407
          if (strcmp (node->Tag, "gml:LinearRing") == 0
 
1408
              || strcmp (node->Tag, "LinearRing") == 0)
 
1409
              ;
 
1410
          else
 
1411
              goto error;
 
1412
          node = node->Next;
 
1413
          if (node == NULL)
 
1414
              goto error;
 
1415
          if (strcmp (node->Tag, "gml:exterior") == 0
 
1416
              || strcmp (node->Tag, "exterior") == 0)
 
1417
              ;
 
1418
          else
 
1419
              goto error;
 
1420
          *interior = 0;
 
1421
          *next = node->Next;
 
1422
          return dyn;
 
1423
      }
 
1424
    if (strcmp (node->Tag, "gml:interior") == 0
 
1425
        || strcmp (node->Tag, "interior") == 0)
 
1426
      {
 
1427
          /* parsing a GML v.3.x <gml:interior> */
 
1428
          node = node->Next;
 
1429
          if (node == NULL)
 
1430
              goto error;
 
1431
          if (strcmp (node->Tag, "gml:LinearRing") == 0
 
1432
              || strcmp (node->Tag, "LinearRing") == 0)
 
1433
              ;
 
1434
          else
 
1435
              goto error;
 
1436
          node = node->Next;
 
1437
          if (node == NULL)
 
1438
              goto error;
 
1439
          if (strcmp (node->Tag, "gml:posList") == 0
 
1440
              || strcmp (node->Tag, "posList") == 0)
 
1441
              ;
 
1442
          else
 
1443
              goto error;
 
1444
          *has_z = gml_get_srsDimension (node);
 
1445
          if (!gml_parse_posList (node->Coordinates, dyn, *has_z))
 
1446
              goto error;
 
1447
          node = node->Next;
 
1448
          if (node == NULL)
 
1449
              goto error;
 
1450
          if (strcmp (node->Tag, "gml:posList") == 0
 
1451
              || strcmp (node->Tag, "posList") == 0)
 
1452
              ;
 
1453
          else
 
1454
              goto error;
 
1455
          node = node->Next;
 
1456
          if (node == NULL)
 
1457
              goto error;
 
1458
          if (strcmp (node->Tag, "gml:LinearRing") == 0
 
1459
              || strcmp (node->Tag, "LinearRing") == 0)
 
1460
              ;
 
1461
          else
 
1462
              goto error;
 
1463
          node = node->Next;
 
1464
          if (node == NULL)
 
1465
              goto error;
 
1466
          if (strcmp (node->Tag, "gml:interior") == 0
 
1467
              || strcmp (node->Tag, "interior") == 0)
 
1468
              ;
 
1469
          else
 
1470
              goto error;
 
1471
          *interior = 1;
 
1472
          *next = node->Next;
 
1473
          return dyn;
 
1474
      }
 
1475
 
 
1476
  error:
 
1477
    gaiaFreeDynamicLine (dyn);
 
1478
    return 0;
 
1479
}
 
1480
 
 
1481
static int
 
1482
gml_parse_polygon (gaiaGeomCollPtr geom, gmlNodePtr node, int srid,
 
1483
                   gmlNodePtr * next_n)
 
1484
{
 
1485
/* parsing a <gml:Polygon> */
 
1486
    int interior;
 
1487
    int has_z;
 
1488
    int inners;
 
1489
    int outers;
 
1490
    int points;
 
1491
    int iv;
 
1492
    int ib = 0;
 
1493
    gaiaGeomCollPtr pg;
 
1494
    gaiaGeomCollPtr last_g;
 
1495
    gaiaPolygonPtr new_pg;
 
1496
    gaiaRingPtr ring;
 
1497
    gaiaDynamicLinePtr dyn;
 
1498
    gaiaPointPtr pt;
 
1499
    gaiaDynamicLinePtr exterior_ring;
 
1500
    gmlNodePtr next;
 
1501
    gmlDynamicRingPtr dyn_rng;
 
1502
    gmlDynamicPolygonPtr dyn_pg = gml_alloc_dyn_polygon ();
 
1503
    gmlNodePtr n = node;
 
1504
    while (n)
 
1505
      {
 
1506
          /* looping on rings */
 
1507
          if (strcmp (n->Tag, "gml:Polygon") == 0
 
1508
              || strcmp (n->Tag, "Polygon") == 0)
 
1509
            {
 
1510
                *next_n = n->Next;
 
1511
                break;
 
1512
            }
 
1513
          dyn = gml_parse_ring (n, &interior, &has_z, &next);
 
1514
          if (dyn == NULL)
 
1515
              goto error;
 
1516
          if (gml_count_dyn_points (dyn) < 4)
 
1517
            {
 
1518
                /* cannot be a valid ring */
 
1519
                goto error;
 
1520
            }
 
1521
          /* checking if the ring is closed */
 
1522
          if (has_z)
 
1523
            {
 
1524
                if (dyn->First->X == dyn->Last->X
 
1525
                    && dyn->First->Y == dyn->Last->Y
 
1526
                    && dyn->First->Z == dyn->Last->Z)
 
1527
                    ;
 
1528
                else
 
1529
                    goto error;
 
1530
            }
 
1531
          else
 
1532
            {
 
1533
                if (dyn->First->X == dyn->Last->X
 
1534
                    && dyn->First->Y == dyn->Last->Y)
 
1535
                    ;
 
1536
                else
 
1537
                    goto error;
 
1538
            }
 
1539
          gml_add_polygon_ring (dyn_pg, dyn, interior, has_z);
 
1540
          n = next;
 
1541
      }
 
1542
/* ok, GML nodes match as expected */
 
1543
    inners = 0;
 
1544
    outers = 0;
 
1545
    has_z = 1;
 
1546
    dyn_rng = dyn_pg->first;
 
1547
    while (dyn_rng)
 
1548
      {
 
1549
          /* verifying the rings collection */
 
1550
          if (dyn_rng->has_z == 0)
 
1551
              has_z = 0;
 
1552
          if (dyn_rng->interior)
 
1553
              inners++;
 
1554
          else
 
1555
            {
 
1556
                outers++;
 
1557
                points = gml_count_dyn_points (dyn_rng->ring);
 
1558
                exterior_ring = dyn_rng->ring;
 
1559
            }
 
1560
          dyn_rng = dyn_rng->next;
 
1561
      }
 
1562
    if (outers != 1)            /* no exterior ring declared */
 
1563
        goto error;
 
1564
 
 
1565
    if (has_z)
 
1566
      {
 
1567
          pg = gaiaAllocGeomCollXYZ ();
 
1568
          pg->Srid = srid;
 
1569
          new_pg = gaiaAddPolygonToGeomColl (pg, points, inners);
 
1570
          /* initializing the EXTERIOR RING */
 
1571
          ring = new_pg->Exterior;
 
1572
          pt = exterior_ring->First;
 
1573
          iv = 0;
 
1574
          while (pt)
 
1575
            {
 
1576
                gaiaSetPointXYZ (ring->Coords, iv, pt->X, pt->Y, pt->Z);
 
1577
                iv++;
 
1578
                pt = pt->Next;
 
1579
            }
 
1580
          dyn_rng = dyn_pg->first;
 
1581
          while (dyn_rng)
 
1582
            {
 
1583
                /* initializing any INTERIOR RING */
 
1584
                if (dyn_rng->interior == 0)
 
1585
                  {
 
1586
                      dyn_rng = dyn_rng->next;
 
1587
                      continue;
 
1588
                  }
 
1589
                points = gml_count_dyn_points (dyn_rng->ring);
 
1590
                ring = gaiaAddInteriorRing (new_pg, ib, points);
 
1591
                ib++;
 
1592
                pt = dyn_rng->ring->First;
 
1593
                iv = 0;
 
1594
                while (pt)
 
1595
                  {
 
1596
                      gaiaSetPointXYZ (ring->Coords, iv, pt->X, pt->Y, pt->Z);
 
1597
                      iv++;
 
1598
                      pt = pt->Next;
 
1599
                  }
 
1600
                dyn_rng = dyn_rng->next;
 
1601
            }
 
1602
      }
 
1603
    else
 
1604
      {
 
1605
          pg = gaiaAllocGeomColl ();
 
1606
          pg->Srid = srid;
 
1607
          new_pg = gaiaAddPolygonToGeomColl (pg, points, inners);
 
1608
          /* initializing the EXTERIOR RING */
 
1609
          ring = new_pg->Exterior;
 
1610
          pt = exterior_ring->First;
 
1611
          iv = 0;
 
1612
          while (pt)
 
1613
            {
 
1614
                gaiaSetPoint (ring->Coords, iv, pt->X, pt->Y);
 
1615
                iv++;
 
1616
                pt = pt->Next;
 
1617
            }
 
1618
          dyn_rng = dyn_pg->first;
 
1619
          while (dyn_rng)
 
1620
            {
 
1621
                /* initializing any INTERIOR RING */
 
1622
                if (dyn_rng->interior == 0)
 
1623
                  {
 
1624
                      dyn_rng = dyn_rng->next;
 
1625
                      continue;
 
1626
                  }
 
1627
                points = gml_count_dyn_points (dyn_rng->ring);
 
1628
                ring = gaiaAddInteriorRing (new_pg, ib, points);
 
1629
                ib++;
 
1630
                pt = dyn_rng->ring->First;
 
1631
                iv = 0;
 
1632
                while (pt)
 
1633
                  {
 
1634
                      gaiaSetPoint (ring->Coords, iv, pt->X, pt->Y);
 
1635
                      iv++;
 
1636
                      pt = pt->Next;
 
1637
                  }
 
1638
                dyn_rng = dyn_rng->next;
 
1639
            }
 
1640
      }
 
1641
 
 
1642
    last_g = geom;
 
1643
    while (1)
 
1644
      {
 
1645
          /* searching the last Geometry within chain */
 
1646
          if (last_g->Next == NULL)
 
1647
              break;
 
1648
          last_g = last_g->Next;
 
1649
      }
 
1650
    last_g->Next = pg;
 
1651
    gml_free_dyn_polygon (dyn_pg);
 
1652
    return 1;
 
1653
 
 
1654
  error:
 
1655
    gml_free_dyn_polygon (dyn_pg);
 
1656
    return 0;
 
1657
}
 
1658
 
 
1659
static int
 
1660
gml_parse_multi_point (gaiaGeomCollPtr geom, gmlNodePtr node)
 
1661
{
 
1662
/* parsing a <gml:MultiPoint> */
 
1663
    int srid;
 
1664
    gmlNodePtr next;
 
1665
    gmlNodePtr n = node;
 
1666
    while (n)
 
1667
      {
 
1668
          /* looping on Point Members */
 
1669
          if (n->Next == NULL)
 
1670
            {
 
1671
                /* verifying the last GML node */
 
1672
                if (strcmp (n->Tag, "gml:MultiPoint") == 0
 
1673
                    || strcmp (n->Tag, "MultiPoint") == 0)
 
1674
                    break;
 
1675
                else
 
1676
                    return 0;
 
1677
            }
 
1678
          if (strcmp (n->Tag, "gml:pointMember") == 0
 
1679
              || strcmp (n->Tag, "pointMember") == 0)
 
1680
              ;
 
1681
          else
 
1682
              return 0;
 
1683
          n = n->Next;
 
1684
          if (n == NULL)
 
1685
              return 0;
 
1686
          if (strcmp (n->Tag, "gml:Point") == 0
 
1687
              || strcmp (n->Tag, "Point") == 0)
 
1688
              ;
 
1689
          else
 
1690
              return 0;
 
1691
          srid = guessGmlSrid (n);
 
1692
          n = n->Next;
 
1693
          if (n == NULL)
 
1694
              return 0;
 
1695
          if (!gml_parse_point (geom, n, srid, &next))
 
1696
              return 0;
 
1697
          n = next;
 
1698
          if (n == NULL)
 
1699
              return 0;
 
1700
          if (strcmp (n->Tag, "gml:pointMember") == 0
 
1701
              || strcmp (n->Tag, "pointMember") == 0)
 
1702
              ;
 
1703
          else
 
1704
              return 0;
 
1705
          n = n->Next;
 
1706
      }
 
1707
    return 1;
 
1708
}
 
1709
 
 
1710
static int
 
1711
gml_parse_multi_linestring (gaiaGeomCollPtr geom, gmlNodePtr node)
 
1712
{
 
1713
/* parsing a <gml:MultiLineString> */
 
1714
    int srid;
 
1715
    gmlNodePtr next;
 
1716
    gmlNodePtr n = node;
 
1717
    while (n)
 
1718
      {
 
1719
          /* looping on LineString Members */
 
1720
          if (n->Next == NULL)
 
1721
            {
 
1722
                /* verifying the last GML node */
 
1723
                if (strcmp (n->Tag, "gml:MultiLineString") == 0
 
1724
                    || strcmp (n->Tag, "MultiLineString") == 0)
 
1725
                    break;
 
1726
                else
 
1727
                    return 0;
 
1728
            }
 
1729
          if (strcmp (n->Tag, "gml:lineStringMember") == 0
 
1730
              || strcmp (n->Tag, "lineStringMember") == 0)
 
1731
              ;
 
1732
          else
 
1733
              return 0;
 
1734
          n = n->Next;
 
1735
          if (n == NULL)
 
1736
              return 0;
 
1737
          if (strcmp (n->Tag, "gml:LineString") == 0
 
1738
              || strcmp (n->Tag, "LineString") == 0)
 
1739
              ;
 
1740
          else
 
1741
              return 0;
 
1742
          srid = guessGmlSrid (n);
 
1743
          n = n->Next;
 
1744
          if (n == NULL)
 
1745
              return 0;
 
1746
          if (!gml_parse_linestring (geom, n, srid, &next))
 
1747
              return 0;
 
1748
          n = next;
 
1749
          if (n == NULL)
 
1750
              return 0;
 
1751
          if (strcmp (n->Tag, "gml:lineStringMember") == 0
 
1752
              || strcmp (n->Tag, "lineStringMember") == 0)
 
1753
              ;
 
1754
          else
 
1755
              return 0;
 
1756
          n = n->Next;
 
1757
      }
 
1758
    return 1;
 
1759
}
 
1760
 
 
1761
static int
 
1762
gml_parse_multi_curve (gaiaGeomCollPtr geom, gmlNodePtr node)
 
1763
{
 
1764
/* parsing a <gml:MultiCurve> */
 
1765
    int srid;
 
1766
    gmlNodePtr next;
 
1767
    gmlNodePtr n = node;
 
1768
    while (n)
 
1769
      {
 
1770
          /* looping on Curve Members */
 
1771
          if (n->Next == NULL)
 
1772
            {
 
1773
                /* verifying the last GML node */
 
1774
                if (strcmp (n->Tag, "gml:MultiCurve") == 0
 
1775
                    || strcmp (n->Tag, "MultiCurve") == 0)
 
1776
                    break;
 
1777
                else
 
1778
                    return 0;
 
1779
            }
 
1780
          if (strcmp (n->Tag, "gml:curveMember") == 0
 
1781
              || strcmp (n->Tag, "curveMember") == 0)
 
1782
              ;
 
1783
          else
 
1784
              return 0;
 
1785
          n = n->Next;
 
1786
          if (n == NULL)
 
1787
              return 0;
 
1788
          if (strcmp (n->Tag, "gml:Curve") == 0
 
1789
              || strcmp (n->Tag, "Curve") == 0)
 
1790
              ;
 
1791
          else
 
1792
              return 0;
 
1793
          srid = guessGmlSrid (n);
 
1794
          n = n->Next;
 
1795
          if (n == NULL)
 
1796
              return 0;
 
1797
          if (!gml_parse_curve (geom, n, srid, &next))
 
1798
              return 0;
 
1799
          n = next;
 
1800
          if (n == NULL)
 
1801
              return 0;
 
1802
          if (strcmp (n->Tag, "gml:curveMember") == 0
 
1803
              || strcmp (n->Tag, "curveMember") == 0)
 
1804
              ;
 
1805
          else
 
1806
              return 0;
 
1807
          n = n->Next;
 
1808
      }
 
1809
    return 1;
 
1810
}
 
1811
 
 
1812
static int
 
1813
gml_parse_multi_polygon (gaiaGeomCollPtr geom, gmlNodePtr node)
 
1814
{
 
1815
/* parsing a <gml:MultiPolygon> */
 
1816
    int srid;
 
1817
    gmlNodePtr next;
 
1818
    gmlNodePtr n = node;
 
1819
    while (n)
 
1820
      {
 
1821
          /* looping on Polygon Members */
 
1822
          if (n->Next == NULL)
 
1823
            {
 
1824
                /* verifying the last GML node */
 
1825
                if (strcmp (n->Tag, "gml:MultiPolygon") == 0
 
1826
                    || strcmp (n->Tag, "MultiPolygon") == 0)
 
1827
                    break;
 
1828
                else
 
1829
                    return 0;
 
1830
            }
 
1831
          if (strcmp (n->Tag, "gml:polygonMember") == 0
 
1832
              || strcmp (n->Tag, "polygonMember") == 0)
 
1833
              ;
 
1834
          else
 
1835
              return 0;
 
1836
          n = n->Next;
 
1837
          if (n == NULL)
 
1838
              return 0;
 
1839
          if (strcmp (n->Tag, "gml:Polygon") == 0
 
1840
              || strcmp (n->Tag, "Polygon") == 0)
 
1841
              ;
 
1842
          else
 
1843
              return 0;
 
1844
          srid = guessGmlSrid (n);
 
1845
          n = n->Next;
 
1846
          if (n == NULL)
 
1847
              return 0;
 
1848
          if (!gml_parse_polygon (geom, n, srid, &next))
 
1849
              return 0;
 
1850
          n = next;
 
1851
          if (n == NULL)
 
1852
              return 0;
 
1853
          if (strcmp (n->Tag, "gml:polygonMember") == 0
 
1854
              || strcmp (n->Tag, "polygonMember") == 0)
 
1855
              ;
 
1856
          else
 
1857
              return 0;
 
1858
          n = n->Next;
 
1859
      }
 
1860
    return 1;
 
1861
}
 
1862
 
 
1863
static int
 
1864
gml_parse_multi_surface (gaiaGeomCollPtr geom, gmlNodePtr node)
 
1865
{
 
1866
/* parsing a <gml:MultiSurface> */
 
1867
    int srid;
 
1868
    gmlNodePtr next;
 
1869
    gmlNodePtr n = node;
 
1870
    while (n)
 
1871
      {
 
1872
          /* looping on Surface Members */
 
1873
          if (n->Next == NULL)
 
1874
            {
 
1875
                /* verifying the last GML node */
 
1876
                if (strcmp (n->Tag, "gml:MultiSurface") == 0
 
1877
                    || strcmp (n->Tag, "MultiSurface") == 0)
 
1878
                    break;
 
1879
                else
 
1880
                    return 0;
 
1881
            }
 
1882
          if (strcmp (n->Tag, "gml:surfaceMember") == 0
 
1883
              || strcmp (n->Tag, "surfaceMember") == 0)
 
1884
              ;
 
1885
          else
 
1886
              return 0;
 
1887
          n = n->Next;
 
1888
          if (n == NULL)
 
1889
              return 0;
 
1890
          if (strcmp (n->Tag, "gml:Polygon") == 0
 
1891
              || strcmp (n->Tag, "Polygon") == 0)
 
1892
              ;
 
1893
          else
 
1894
              return 0;
 
1895
          srid = guessGmlSrid (n);
 
1896
          n = n->Next;
 
1897
          if (n == NULL)
 
1898
              return 0;
 
1899
          if (!gml_parse_polygon (geom, n, srid, &next))
 
1900
              return 0;
 
1901
          n = next;
 
1902
          if (n == NULL)
 
1903
              return 0;
 
1904
          if (strcmp (n->Tag, "gml:surfaceMember") == 0
 
1905
              || strcmp (n->Tag, "surfaceMember") == 0)
 
1906
              ;
 
1907
          else
 
1908
              return 0;
 
1909
          n = n->Next;
 
1910
      }
 
1911
    return 1;
 
1912
}
 
1913
 
 
1914
static int
 
1915
gml_parse_multi_geometry (gaiaGeomCollPtr geom, gmlNodePtr node)
 
1916
{
 
1917
/* parsing a <gml:MultiGeometry> */
 
1918
    int srid;
 
1919
    gmlNodePtr next;
 
1920
    gmlNodePtr n = node;
 
1921
    while (n)
 
1922
      {
 
1923
          /* looping on Geometry Members */
 
1924
          if (n->Next == NULL)
 
1925
            {
 
1926
                /* verifying the last GML node */
 
1927
                if (strcmp (n->Tag, "gml:MultiGeometry") == 0
 
1928
                    || strcmp (n->Tag, "MultiGeometry") == 0)
 
1929
                    break;
 
1930
                else
 
1931
                    return 0;
 
1932
            }
 
1933
          if (strcmp (n->Tag, "gml:geometryMember") == 0
 
1934
              || strcmp (n->Tag, "geometryMember") == 0)
 
1935
              ;
 
1936
          else
 
1937
              return 0;
 
1938
          n = n->Next;
 
1939
          if (n == NULL)
 
1940
              return 0;
 
1941
          if (strcmp (n->Tag, "gml:Point") == 0
 
1942
              || strcmp (n->Tag, "Point") == 0)
 
1943
            {
 
1944
                srid = guessGmlSrid (n);
 
1945
                n = n->Next;
 
1946
                if (n == NULL)
 
1947
                    return 0;
 
1948
                if (!gml_parse_point (geom, n, srid, &next))
 
1949
                    return 0;
 
1950
                n = next;
 
1951
            }
 
1952
          else if (strcmp (n->Tag, "gml:LineString") == 0
 
1953
                   || strcmp (n->Tag, "LineString") == 0)
 
1954
            {
 
1955
                srid = guessGmlSrid (n);
 
1956
                n = n->Next;
 
1957
                if (n == NULL)
 
1958
                    return 0;
 
1959
                if (!gml_parse_linestring (geom, n, srid, &next))
 
1960
                    return 0;
 
1961
                n = next;
 
1962
            }
 
1963
          else if (strcmp (n->Tag, "gml:Curve") == 0
 
1964
                   || strcmp (n->Tag, "Curve") == 0)
 
1965
            {
 
1966
                srid = guessGmlSrid (n);
 
1967
                n = n->Next;
 
1968
                if (n == NULL)
 
1969
                    return 0;
 
1970
                if (!gml_parse_curve (geom, n, srid, &next))
 
1971
                    return 0;
 
1972
                n = next;
 
1973
            }
 
1974
          else if (strcmp (n->Tag, "gml:Polygon") == 0
 
1975
                   || strcmp (n->Tag, "Polygon") == 0)
 
1976
            {
 
1977
                srid = guessGmlSrid (n);
 
1978
                n = n->Next;
 
1979
                if (n == NULL)
 
1980
                    return 0;
 
1981
                if (!gml_parse_polygon (geom, n, srid, &next))
 
1982
                    return 0;
 
1983
                n = next;
 
1984
            }
 
1985
          else
 
1986
              return 0;
 
1987
          if (n == NULL)
 
1988
              return 0;
 
1989
          if (strcmp (n->Tag, "gml:geometryMember") == 0
 
1990
              || strcmp (n->Tag, "geometryMember") == 0)
 
1991
              ;
 
1992
          else
 
1993
              return 0;
 
1994
          n = n->Next;
 
1995
      }
 
1996
    return 1;
 
1997
}
 
1998
 
 
1999
static gaiaGeomCollPtr
 
2000
gml_validate_geometry (gaiaGeomCollPtr chain, sqlite3 * sqlite_handle)
 
2001
{
 
2002
    int xy = 0;
 
2003
    int xyz = 0;
 
2004
    int pts = 0;
 
2005
    int lns = 0;
 
2006
    int pgs = 0;
 
2007
    gaiaPointPtr pt;
 
2008
    gaiaLinestringPtr ln;
 
2009
    gaiaPolygonPtr pg;
 
2010
    gaiaPointPtr save_pt;
 
2011
    gaiaLinestringPtr save_ln;
 
2012
    gaiaPolygonPtr save_pg;
 
2013
    gaiaRingPtr i_ring;
 
2014
    gaiaRingPtr o_ring;
 
2015
    int ib;
 
2016
    int delete_g2;
 
2017
    gaiaGeomCollPtr g;
 
2018
    gaiaGeomCollPtr g2;
 
2019
    gaiaGeomCollPtr geom;
 
2020
    char proj_from[2048];
 
2021
    char proj_to[2048];
 
2022
 
 
2023
    g = chain;
 
2024
    while (g)
 
2025
      {
 
2026
          if (g != chain)
 
2027
            {
 
2028
                if (g->DimensionModel == GAIA_XY)
 
2029
                    xy++;
 
2030
                if (g->DimensionModel == GAIA_XY_Z)
 
2031
                    xyz++;
 
2032
            }
 
2033
          pt = g->FirstPoint;
 
2034
          while (pt)
 
2035
            {
 
2036
                pts++;
 
2037
                save_pt = pt;
 
2038
                pt = pt->Next;
 
2039
            }
 
2040
          ln = g->FirstLinestring;
 
2041
          while (ln)
 
2042
            {
 
2043
                lns++;
 
2044
                save_ln = ln;
 
2045
                ln = ln->Next;
 
2046
            }
 
2047
          pg = g->FirstPolygon;
 
2048
          while (pg)
 
2049
            {
 
2050
                pgs++;
 
2051
                save_pg = pg;
 
2052
                pg = pg->Next;
 
2053
            }
 
2054
          g = g->Next;
 
2055
      }
 
2056
    if (pts == 1 && lns == 0 && pgs == 0)
 
2057
      {
 
2058
          /* POINT */
 
2059
          if (xy > 0)
 
2060
            {
 
2061
                /* 2D [XY] */
 
2062
                geom = gaiaAllocGeomColl ();
 
2063
                geom->Srid = chain->Srid;
 
2064
                if (chain->DeclaredType == GAIA_MULTIPOINT)
 
2065
                    geom->DeclaredType = GAIA_MULTIPOINT;
 
2066
                else if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2067
                    geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2068
                else
 
2069
                    geom->DeclaredType = GAIA_POINT;
 
2070
                gaiaAddPointToGeomColl (geom, save_pt->X, save_pt->Y);
 
2071
                return geom;
 
2072
            }
 
2073
          else
 
2074
            {
 
2075
                /* 3D [XYZ] */
 
2076
                geom = gaiaAllocGeomCollXYZ ();
 
2077
                geom->Srid = chain->Srid;
 
2078
                if (chain->DeclaredType == GAIA_MULTIPOINT)
 
2079
                    geom->DeclaredType = GAIA_MULTIPOINT;
 
2080
                else if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2081
                    geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2082
                else
 
2083
                    geom->DeclaredType = GAIA_POINT;
 
2084
                gaiaAddPointToGeomCollXYZ (geom, save_pt->X, save_pt->Y,
 
2085
                                           save_pt->Z);
 
2086
                return geom;
 
2087
            }
 
2088
      }
 
2089
    if (pts == 0 && lns == 1 && pgs == 0)
 
2090
      {
 
2091
          /* LINESTRING */
 
2092
          if (xy > 0)
 
2093
            {
 
2094
                /* 2D [XY] */
 
2095
                geom = gaiaAllocGeomColl ();
 
2096
            }
 
2097
          else
 
2098
            {
 
2099
                /* 3D [XYZ] */
 
2100
                geom = gaiaAllocGeomCollXYZ ();
 
2101
            }
 
2102
          geom->Srid = chain->Srid;
 
2103
          if (chain->DeclaredType == GAIA_MULTILINESTRING)
 
2104
              geom->DeclaredType = GAIA_MULTILINESTRING;
 
2105
          else if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2106
              geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2107
          else
 
2108
              geom->DeclaredType = GAIA_LINESTRING;
 
2109
          ln = gaiaAddLinestringToGeomColl (geom, save_ln->Points);
 
2110
          gaiaCopyLinestringCoords (ln, save_ln);
 
2111
          return geom;
 
2112
      }
 
2113
    if (pts == 0 && lns == 0 && pgs == 1)
 
2114
      {
 
2115
          /* POLYGON */
 
2116
          if (xy > 0)
 
2117
            {
 
2118
                /* 2D [XY] */
 
2119
                geom = gaiaAllocGeomColl ();
 
2120
            }
 
2121
          else
 
2122
            {
 
2123
                /* 3D [XYZ] */
 
2124
                geom = gaiaAllocGeomCollXYZ ();
 
2125
            }
 
2126
          geom->Srid = chain->Srid;
 
2127
          if (chain->DeclaredType == GAIA_MULTIPOLYGON)
 
2128
              geom->DeclaredType = GAIA_MULTIPOLYGON;
 
2129
          else if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2130
              geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2131
          else
 
2132
              geom->DeclaredType = GAIA_POLYGON;
 
2133
          i_ring = save_pg->Exterior;
 
2134
          pg = gaiaAddPolygonToGeomColl (geom, i_ring->Points,
 
2135
                                         save_pg->NumInteriors);
 
2136
          o_ring = pg->Exterior;
 
2137
          gaiaCopyRingCoords (o_ring, i_ring);
 
2138
          for (ib = 0; ib < save_pg->NumInteriors; ib++)
 
2139
            {
 
2140
                i_ring = save_pg->Interiors + ib;
 
2141
                o_ring = gaiaAddInteriorRing (pg, ib, i_ring->Points);
 
2142
                gaiaCopyRingCoords (o_ring, i_ring);
 
2143
            }
 
2144
          return geom;
 
2145
      }
 
2146
    if (pts >= 1 && lns == 0 && pgs == 0)
 
2147
      {
 
2148
          /* MULTIPOINT */
 
2149
          if (xy > 0)
 
2150
            {
 
2151
                /* 2D [XY] */
 
2152
                geom = gaiaAllocGeomColl ();
 
2153
                geom->Srid = chain->Srid;
 
2154
                if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2155
                    geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2156
                else
 
2157
                    geom->DeclaredType = GAIA_MULTIPOINT;
 
2158
                g = chain;
 
2159
                while (g)
 
2160
                  {
 
2161
                      if (geom->Srid == -1)
 
2162
                        {
 
2163
                            /* we haven't yet set any SRID */
 
2164
                            geom->Srid = g->Srid;
 
2165
                        }
 
2166
                      g2 = g;
 
2167
                      delete_g2 = 0;
 
2168
                      if (g->Srid != geom->Srid && g->Srid != -1
 
2169
                          && sqlite_handle != NULL)
 
2170
                        {
 
2171
                            /* we'll try to apply a reprojection */
 
2172
#ifndef OMIT_PROJ               /* but only if PROJ.4 is actually available */
 
2173
                            gml_proj_params (sqlite_handle, g->Srid, proj_from);
 
2174
                            gml_proj_params (sqlite_handle, geom->Srid,
 
2175
                                             proj_to);
 
2176
                            if (*proj_to == '\0' || *proj_from == '\0')
 
2177
                                ;
 
2178
                            else
 
2179
                              {
 
2180
                                  g2 = gaiaTransform (g, proj_from, proj_to);
 
2181
                                  if (!g2)
 
2182
                                      g2 = g;
 
2183
                                  else
 
2184
                                      delete_g2 = 1;
 
2185
                              }
 
2186
#endif
 
2187
                        }
 
2188
                      pt = g2->FirstPoint;
 
2189
                      while (pt)
 
2190
                        {
 
2191
                            gaiaAddPointToGeomColl (geom, pt->X, pt->Y);
 
2192
                            pt = pt->Next;
 
2193
                        }
 
2194
                      if (delete_g2)
 
2195
                          gaiaFreeGeomColl (g2);
 
2196
                      g = g->Next;
 
2197
                  }
 
2198
                return geom;
 
2199
            }
 
2200
          else
 
2201
            {
 
2202
                /* 3D [XYZ] */
 
2203
                geom = gaiaAllocGeomCollXYZ ();
 
2204
                geom->Srid = chain->Srid;
 
2205
                if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2206
                    geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2207
                else
 
2208
                    geom->DeclaredType = GAIA_MULTIPOINT;
 
2209
                g = chain;
 
2210
                while (g)
 
2211
                  {
 
2212
                      if (geom->Srid == -1)
 
2213
                        {
 
2214
                            /* we haven't yet a SRID set */
 
2215
                            geom->Srid = g->Srid;
 
2216
                        }
 
2217
                      g2 = g;
 
2218
                      delete_g2 = 0;
 
2219
                      if (g->Srid != geom->Srid && g->Srid != -1
 
2220
                          && sqlite_handle != NULL)
 
2221
                        {
 
2222
                            /* we'll try to apply a reprojection */
 
2223
#ifndef OMIT_PROJ               /* but only if PROJ.4 is actually available */
 
2224
                            gml_proj_params (sqlite_handle, g->Srid, proj_from);
 
2225
                            gml_proj_params (sqlite_handle, geom->Srid,
 
2226
                                             proj_to);
 
2227
                            if (*proj_to == '\0' || *proj_from == '\0')
 
2228
                                ;
 
2229
                            else
 
2230
                              {
 
2231
                                  g2 = gaiaTransform (g, proj_from, proj_to);
 
2232
                                  if (!g2)
 
2233
                                      g2 = g;
 
2234
                                  else
 
2235
                                      delete_g2 = 1;
 
2236
                              }
 
2237
#endif
 
2238
                        }
 
2239
                      pt = g2->FirstPoint;
 
2240
                      while (pt)
 
2241
                        {
 
2242
                            gaiaAddPointToGeomCollXYZ (geom, pt->X, pt->Y,
 
2243
                                                       pt->Z);
 
2244
                            pt = pt->Next;
 
2245
                        }
 
2246
                      if (delete_g2)
 
2247
                          gaiaFreeGeomColl (g2);
 
2248
                      g = g->Next;
 
2249
                  }
 
2250
                return geom;
 
2251
            }
 
2252
      }
 
2253
    if (pts == 0 && lns >= 1 && pgs == 0)
 
2254
      {
 
2255
          /* MULTILINESTRING */
 
2256
          if (xy > 0)
 
2257
            {
 
2258
                /* 2D [XY] */
 
2259
                geom = gaiaAllocGeomColl ();
 
2260
                geom->Srid = chain->Srid;
 
2261
                if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2262
                    geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2263
                else
 
2264
                    geom->DeclaredType = GAIA_MULTILINESTRING;
 
2265
                g = chain;
 
2266
                while (g)
 
2267
                  {
 
2268
                      if (geom->Srid == -1)
 
2269
                        {
 
2270
                            /* we haven't yet set any SRID */
 
2271
                            geom->Srid = g->Srid;
 
2272
                        }
 
2273
                      g2 = g;
 
2274
                      delete_g2 = 0;
 
2275
                      if (g->Srid != geom->Srid && g->Srid != -1
 
2276
                          && sqlite_handle != NULL)
 
2277
                        {
 
2278
                            /* we'll try to apply a reprojection */
 
2279
#ifndef OMIT_PROJ               /* but only if PROJ.4 is actually available */
 
2280
                            gml_proj_params (sqlite_handle, g->Srid, proj_from);
 
2281
                            gml_proj_params (sqlite_handle, geom->Srid,
 
2282
                                             proj_to);
 
2283
                            if (*proj_to == '\0' || *proj_from == '\0')
 
2284
                                ;
 
2285
                            else
 
2286
                              {
 
2287
                                  g2 = gaiaTransform (g, proj_from, proj_to);
 
2288
                                  if (!g2)
 
2289
                                      g2 = g;
 
2290
                                  else
 
2291
                                      delete_g2 = 1;
 
2292
                              }
 
2293
#endif
 
2294
                        }
 
2295
                      ln = g2->FirstLinestring;
 
2296
                      while (ln)
 
2297
                        {
 
2298
                            save_ln =
 
2299
                                gaiaAddLinestringToGeomColl (geom, ln->Points);
 
2300
                            gaiaCopyLinestringCoords (save_ln, ln);
 
2301
                            ln = ln->Next;
 
2302
                        }
 
2303
                      if (delete_g2)
 
2304
                          gaiaFreeGeomColl (g2);
 
2305
                      g = g->Next;
 
2306
                  }
 
2307
                return geom;
 
2308
            }
 
2309
          else
 
2310
            {
 
2311
                /* 3D [XYZ] */
 
2312
                geom = gaiaAllocGeomCollXYZ ();
 
2313
                geom->Srid = chain->Srid;
 
2314
                if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2315
                    geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2316
                else
 
2317
                    geom->DeclaredType = GAIA_MULTILINESTRING;
 
2318
                g = chain;
 
2319
                while (g)
 
2320
                  {
 
2321
                      if (geom->Srid == -1)
 
2322
                        {
 
2323
                            /* we haven't yet a SRID set */
 
2324
                            geom->Srid = g->Srid;
 
2325
                        }
 
2326
                      g2 = g;
 
2327
                      delete_g2 = 0;
 
2328
                      if (g->Srid != geom->Srid && g->Srid != -1
 
2329
                          && sqlite_handle != NULL)
 
2330
                        {
 
2331
                            /* we'll try to apply a reprojection */
 
2332
#ifndef OMIT_PROJ               /* but only if PROJ.4 is actually available */
 
2333
                            gml_proj_params (sqlite_handle, g->Srid, proj_from);
 
2334
                            gml_proj_params (sqlite_handle, geom->Srid,
 
2335
                                             proj_to);
 
2336
                            if (*proj_to == '\0' || *proj_from == '\0')
 
2337
                                ;
 
2338
                            else
 
2339
                              {
 
2340
                                  g2 = gaiaTransform (g, proj_from, proj_to);
 
2341
                                  if (!g2)
 
2342
                                      g2 = g;
 
2343
                                  else
 
2344
                                      delete_g2 = 1;
 
2345
                              }
 
2346
#endif
 
2347
                        }
 
2348
                      ln = g2->FirstLinestring;
 
2349
                      while (ln)
 
2350
                        {
 
2351
                            save_ln =
 
2352
                                gaiaAddLinestringToGeomColl (geom, ln->Points);
 
2353
                            gaiaCopyLinestringCoords (save_ln, ln);
 
2354
                            ln = ln->Next;
 
2355
                        }
 
2356
                      if (delete_g2)
 
2357
                          gaiaFreeGeomColl (g2);
 
2358
                      g = g->Next;
 
2359
                  }
 
2360
                return geom;
 
2361
            }
 
2362
      }
 
2363
    if (pts == 0 && lns == 0 && pgs >= 1)
 
2364
      {
 
2365
          /* MULTIPOLYGON */
 
2366
          if (xy > 0)
 
2367
            {
 
2368
                /* 2D [XY] */
 
2369
                geom = gaiaAllocGeomColl ();
 
2370
                geom->Srid = chain->Srid;
 
2371
                if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2372
                    geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2373
                else
 
2374
                    geom->DeclaredType = GAIA_MULTIPOLYGON;
 
2375
                g = chain;
 
2376
                while (g)
 
2377
                  {
 
2378
                      if (geom->Srid == -1)
 
2379
                        {
 
2380
                            /* we haven't yet set any SRID */
 
2381
                            geom->Srid = g->Srid;
 
2382
                        }
 
2383
                      g2 = g;
 
2384
                      delete_g2 = 0;
 
2385
                      if (g->Srid != geom->Srid && g->Srid != -1
 
2386
                          && sqlite_handle != NULL)
 
2387
                        {
 
2388
                            /* we'll try to apply a reprojection */
 
2389
#ifndef OMIT_PROJ               /* but only if PROJ.4 is actually available */
 
2390
                            gml_proj_params (sqlite_handle, g->Srid, proj_from);
 
2391
                            gml_proj_params (sqlite_handle, geom->Srid,
 
2392
                                             proj_to);
 
2393
                            if (*proj_to == '\0' || *proj_from == '\0')
 
2394
                                ;
 
2395
                            else
 
2396
                              {
 
2397
                                  g2 = gaiaTransform (g, proj_from, proj_to);
 
2398
                                  if (!g2)
 
2399
                                      g2 = g;
 
2400
                                  else
 
2401
                                      delete_g2 = 1;
 
2402
                              }
 
2403
#endif
 
2404
                        }
 
2405
                      pg = g2->FirstPolygon;
 
2406
                      while (pg)
 
2407
                        {
 
2408
                            i_ring = pg->Exterior;
 
2409
                            save_pg =
 
2410
                                gaiaAddPolygonToGeomColl (geom, i_ring->Points,
 
2411
                                                          pg->NumInteriors);
 
2412
                            o_ring = save_pg->Exterior;
 
2413
                            gaiaCopyRingCoords (o_ring, i_ring);
 
2414
                            for (ib = 0; ib < pg->NumInteriors; ib++)
 
2415
                              {
 
2416
                                  i_ring = pg->Interiors + ib;
 
2417
                                  o_ring =
 
2418
                                      gaiaAddInteriorRing (save_pg, ib,
 
2419
                                                           i_ring->Points);
 
2420
                                  gaiaCopyRingCoords (o_ring, i_ring);
 
2421
                              }
 
2422
                            pg = pg->Next;
 
2423
                        }
 
2424
                      if (delete_g2)
 
2425
                          gaiaFreeGeomColl (g2);
 
2426
                      g = g->Next;
 
2427
                  }
 
2428
                return geom;
 
2429
            }
 
2430
          else
 
2431
            {
 
2432
                /* 3D [XYZ] */
 
2433
                geom = gaiaAllocGeomCollXYZ ();
 
2434
                geom->Srid = chain->Srid;
 
2435
                if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
 
2436
                    geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2437
                else
 
2438
                    geom->DeclaredType = GAIA_MULTIPOLYGON;
 
2439
                g = chain;
 
2440
                while (g)
 
2441
                  {
 
2442
                      if (geom->Srid == -1)
 
2443
                        {
 
2444
                            /* we haven't yet a SRID set */
 
2445
                            geom->Srid = g->Srid;
 
2446
                        }
 
2447
                      g2 = g;
 
2448
                      delete_g2 = 0;
 
2449
                      if (g->Srid != geom->Srid && g->Srid != -1
 
2450
                          && sqlite_handle != NULL)
 
2451
                        {
 
2452
                            /* we'll try to apply a reprojection */
 
2453
#ifndef OMIT_PROJ               /* but only if PROJ.4 is actually available */
 
2454
                            gml_proj_params (sqlite_handle, g->Srid, proj_from);
 
2455
                            gml_proj_params (sqlite_handle, geom->Srid,
 
2456
                                             proj_to);
 
2457
                            if (*proj_to == '\0' || *proj_from == '\0')
 
2458
                                ;
 
2459
                            else
 
2460
                              {
 
2461
                                  g2 = gaiaTransform (g, proj_from, proj_to);
 
2462
                                  if (!g2)
 
2463
                                      g2 = g;
 
2464
                                  else
 
2465
                                      delete_g2 = 1;
 
2466
                              }
 
2467
#endif
 
2468
                        }
 
2469
                      pg = g2->FirstPolygon;
 
2470
                      while (pg)
 
2471
                        {
 
2472
                            i_ring = pg->Exterior;
 
2473
                            save_pg =
 
2474
                                gaiaAddPolygonToGeomColl (geom, i_ring->Points,
 
2475
                                                          pg->NumInteriors);
 
2476
                            o_ring = save_pg->Exterior;
 
2477
                            gaiaCopyRingCoords (o_ring, i_ring);
 
2478
                            for (ib = 0; ib < pg->NumInteriors; ib++)
 
2479
                              {
 
2480
                                  i_ring = pg->Interiors + ib;
 
2481
                                  o_ring =
 
2482
                                      gaiaAddInteriorRing (save_pg, ib,
 
2483
                                                           i_ring->Points);
 
2484
                                  gaiaCopyRingCoords (o_ring, i_ring);
 
2485
                              }
 
2486
                            pg = pg->Next;
 
2487
                        }
 
2488
                      if (delete_g2)
 
2489
                          gaiaFreeGeomColl (g2);
 
2490
                      g = g->Next;
 
2491
                  }
 
2492
                return geom;
 
2493
            }
 
2494
      }
 
2495
    if ((pts + lns + pgs) > 0)
 
2496
      {
 
2497
          /* GEOMETRYCOLLECTION */
 
2498
          if (xy > 0)
 
2499
            {
 
2500
                /* 2D [XY] */
 
2501
                geom = gaiaAllocGeomColl ();
 
2502
                geom->Srid = chain->Srid;
 
2503
                geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2504
                g = chain;
 
2505
                while (g)
 
2506
                  {
 
2507
                      if (geom->Srid == -1)
 
2508
                        {
 
2509
                            /* we haven't yet set any SRID */
 
2510
                            geom->Srid = g->Srid;
 
2511
                        }
 
2512
                      g2 = g;
 
2513
                      delete_g2 = 0;
 
2514
                      if (g->Srid != geom->Srid && g->Srid != -1
 
2515
                          && sqlite_handle != NULL)
 
2516
                        {
 
2517
                            /* we'll try to apply a reprojection */
 
2518
#ifndef OMIT_PROJ               /* but only if PROJ.4 is actually available */
 
2519
                            gml_proj_params (sqlite_handle, g->Srid, proj_from);
 
2520
                            gml_proj_params (sqlite_handle, geom->Srid,
 
2521
                                             proj_to);
 
2522
                            if (*proj_to == '\0' || *proj_from == '\0')
 
2523
                                ;
 
2524
                            else
 
2525
                              {
 
2526
                                  g2 = gaiaTransform (g, proj_from, proj_to);
 
2527
                                  if (!g2)
 
2528
                                      g2 = g;
 
2529
                                  else
 
2530
                                      delete_g2 = 1;
 
2531
                              }
 
2532
#endif
 
2533
                        }
 
2534
                      pt = g2->FirstPoint;
 
2535
                      while (pt)
 
2536
                        {
 
2537
                            gaiaAddPointToGeomColl (geom, pt->X, pt->Y);
 
2538
                            pt = pt->Next;
 
2539
                        }
 
2540
                      ln = g2->FirstLinestring;
 
2541
                      while (ln)
 
2542
                        {
 
2543
                            save_ln =
 
2544
                                gaiaAddLinestringToGeomColl (geom, ln->Points);
 
2545
                            gaiaCopyLinestringCoords (save_ln, ln);
 
2546
                            ln = ln->Next;
 
2547
                        }
 
2548
                      pg = g2->FirstPolygon;
 
2549
                      while (pg)
 
2550
                        {
 
2551
                            i_ring = pg->Exterior;
 
2552
                            save_pg =
 
2553
                                gaiaAddPolygonToGeomColl (geom, i_ring->Points,
 
2554
                                                          pg->NumInteriors);
 
2555
                            o_ring = save_pg->Exterior;
 
2556
                            gaiaCopyRingCoords (o_ring, i_ring);
 
2557
                            for (ib = 0; ib < pg->NumInteriors; ib++)
 
2558
                              {
 
2559
                                  i_ring = pg->Interiors + ib;
 
2560
                                  o_ring =
 
2561
                                      gaiaAddInteriorRing (save_pg, ib,
 
2562
                                                           i_ring->Points);
 
2563
                                  gaiaCopyRingCoords (o_ring, i_ring);
 
2564
                              }
 
2565
                            pg = pg->Next;
 
2566
                        }
 
2567
                      if (delete_g2)
 
2568
                          gaiaFreeGeomColl (g2);
 
2569
                      g = g->Next;
 
2570
                  }
 
2571
                return geom;
 
2572
            }
 
2573
          else
 
2574
            {
 
2575
                /* 3D [XYZ] */
 
2576
                geom = gaiaAllocGeomCollXYZ ();
 
2577
                geom->Srid = chain->Srid;
 
2578
                geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2579
                g = chain;
 
2580
                while (g)
 
2581
                  {
 
2582
                      if (geom->Srid == -1)
 
2583
                        {
 
2584
                            /* we haven't yet a SRID set */
 
2585
                            geom->Srid = g->Srid;
 
2586
                        }
 
2587
                      g2 = g;
 
2588
                      delete_g2 = 0;
 
2589
                      if (g->Srid != geom->Srid && g->Srid != -1
 
2590
                          && sqlite_handle != NULL)
 
2591
                        {
 
2592
                            /* we'll try to apply a reprojection */
 
2593
#ifndef OMIT_PROJ               /* but only if PROJ.4 is actually available */
 
2594
                            gml_proj_params (sqlite_handle, g->Srid, proj_from);
 
2595
                            gml_proj_params (sqlite_handle, geom->Srid,
 
2596
                                             proj_to);
 
2597
                            if (*proj_to == '\0' || *proj_from == '\0')
 
2598
                                ;
 
2599
                            else
 
2600
                              {
 
2601
                                  g2 = gaiaTransform (g, proj_from, proj_to);
 
2602
                                  if (!g2)
 
2603
                                      g2 = g;
 
2604
                                  else
 
2605
                                      delete_g2 = 1;
 
2606
                              }
 
2607
#endif
 
2608
                        }
 
2609
                      pt = g2->FirstPoint;
 
2610
                      while (pt)
 
2611
                        {
 
2612
                            gaiaAddPointToGeomCollXYZ (geom, pt->X, pt->Y,
 
2613
                                                       pt->Z);
 
2614
                            pt = pt->Next;
 
2615
                        }
 
2616
                      ln = g2->FirstLinestring;
 
2617
                      while (ln)
 
2618
                        {
 
2619
                            save_ln =
 
2620
                                gaiaAddLinestringToGeomColl (geom, ln->Points);
 
2621
                            gaiaCopyLinestringCoords (save_ln, ln);
 
2622
                            ln = ln->Next;
 
2623
                        }
 
2624
                      pg = g2->FirstPolygon;
 
2625
                      while (pg)
 
2626
                        {
 
2627
                            i_ring = pg->Exterior;
 
2628
                            save_pg =
 
2629
                                gaiaAddPolygonToGeomColl (geom, i_ring->Points,
 
2630
                                                          pg->NumInteriors);
 
2631
                            o_ring = save_pg->Exterior;
 
2632
                            gaiaCopyRingCoords (o_ring, i_ring);
 
2633
                            for (ib = 0; ib < pg->NumInteriors; ib++)
 
2634
                              {
 
2635
                                  i_ring = pg->Interiors + ib;
 
2636
                                  o_ring =
 
2637
                                      gaiaAddInteriorRing (save_pg, ib,
 
2638
                                                           i_ring->Points);
 
2639
                                  gaiaCopyRingCoords (o_ring, i_ring);
 
2640
                              }
 
2641
                            pg = pg->Next;
 
2642
                        }
 
2643
                      if (delete_g2)
 
2644
                          gaiaFreeGeomColl (g2);
 
2645
                      g = g->Next;
 
2646
                  }
 
2647
                return geom;
 
2648
            }
 
2649
      }
 
2650
    return NULL;
 
2651
}
 
2652
 
 
2653
static void
 
2654
gml_free_geom_chain (gaiaGeomCollPtr geom)
 
2655
{
 
2656
/* deleting a chain of preliminary geometries */
 
2657
    gaiaGeomCollPtr gn;
 
2658
    while (geom)
 
2659
      {
 
2660
          gn = geom->Next;
 
2661
          gaiaFreeGeomColl (geom);
 
2662
          geom = gn;
 
2663
      }
 
2664
}
 
2665
 
 
2666
static gaiaGeomCollPtr
 
2667
gml_build_geometry (gmlNodePtr tree, sqlite3 * sqlite_handle)
 
2668
{
 
2669
/* attempting to build a geometry from GML nodes */
 
2670
    gaiaGeomCollPtr geom;
 
2671
    gaiaGeomCollPtr result;
 
2672
    int geom_type;
 
2673
    gmlNodePtr next;
 
2674
 
 
2675
    if (tree == NULL)
 
2676
        return NULL;
 
2677
    geom_type = guessGmlGeometryType (tree);
 
2678
    if (geom_type == GAIA_GML_UNKNOWN)
 
2679
      {
 
2680
          /* unsupported main geometry type */
 
2681
          return NULL;
 
2682
      }
 
2683
/* creating the main geometry */
 
2684
    geom = gaiaAllocGeomColl ();
 
2685
    geom->Srid = guessGmlSrid (tree);
 
2686
 
 
2687
    switch (geom_type)
 
2688
      {
 
2689
          /* parsing GML nodes accordingly with declared GML type */
 
2690
      case GAIA_GML_POINT:
 
2691
          geom->DeclaredType = GAIA_POINT;
 
2692
          if (!gml_parse_point (geom, tree->Next, geom->Srid, &next))
 
2693
              goto error;
 
2694
          break;
 
2695
      case GAIA_GML_LINESTRING:
 
2696
          geom->DeclaredType = GAIA_LINESTRING;
 
2697
          if (!gml_parse_linestring (geom, tree->Next, geom->Srid, &next))
 
2698
              goto error;
 
2699
          break;
 
2700
      case GAIA_GML_CURVE:
 
2701
          geom->DeclaredType = GAIA_LINESTRING;
 
2702
          if (!gml_parse_curve (geom, tree->Next, geom->Srid, &next))
 
2703
              goto error;
 
2704
          break;
 
2705
      case GAIA_GML_POLYGON:
 
2706
          geom->DeclaredType = GAIA_POLYGON;
 
2707
          if (!gml_parse_polygon (geom, tree->Next, geom->Srid, &next))
 
2708
              goto error;
 
2709
          if (next != NULL)
 
2710
              goto error;
 
2711
          break;
 
2712
      case GAIA_GML_MULTIPOINT:
 
2713
          geom->DeclaredType = GAIA_MULTIPOINT;
 
2714
          if (!gml_parse_multi_point (geom, tree->Next))
 
2715
              goto error;
 
2716
          break;
 
2717
      case GAIA_GML_MULTILINESTRING:
 
2718
          geom->DeclaredType = GAIA_MULTILINESTRING;
 
2719
          if (!gml_parse_multi_linestring (geom, tree->Next))
 
2720
              goto error;
 
2721
          break;
 
2722
      case GAIA_GML_MULTICURVE:
 
2723
          geom->DeclaredType = GAIA_MULTILINESTRING;
 
2724
          if (!gml_parse_multi_curve (geom, tree->Next))
 
2725
              goto error;
 
2726
          break;
 
2727
      case GAIA_GML_MULTIPOLYGON:
 
2728
          geom->DeclaredType = GAIA_MULTIPOLYGON;
 
2729
          if (!gml_parse_multi_polygon (geom, tree->Next))
 
2730
              goto error;
 
2731
          break;
 
2732
      case GAIA_GML_MULTISURFACE:
 
2733
          geom->DeclaredType = GAIA_MULTIPOLYGON;
 
2734
          if (!gml_parse_multi_surface (geom, tree->Next))
 
2735
              goto error;
 
2736
          break;
 
2737
      case GAIA_GML_MULTIGEOMETRY:
 
2738
          geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
 
2739
          if (!gml_parse_multi_geometry (geom, tree->Next))
 
2740
              goto error;
 
2741
          break;
 
2742
      };
 
2743
 
 
2744
/* attempting to build the final geometry */
 
2745
    result = gml_validate_geometry (geom, sqlite_handle);
 
2746
    if (result == NULL)
 
2747
        goto error;
 
2748
    gml_free_geom_chain (geom);
 
2749
    return result;
 
2750
 
 
2751
  error:
 
2752
    gml_free_geom_chain (geom);
 
2753
    return NULL;
 
2754
}
 
2755
 
 
2756
 
 
2757
 
 
2758
/*
 
2759
** CAVEAT: we must redefine any Lemon/Flex own macro
 
2760
*/
 
2761
#define YYMINORTYPE             GML_MINORTYPE
 
2762
#define YY_CHAR                 GML_YY_CHAR
 
2763
#define input                   gml_input
 
2764
#define ParseAlloc              gmlParseAlloc
 
2765
#define ParseFree               gmlParseFree
 
2766
#define ParseStackPeak          gmlParseStackPeak
 
2767
#define Parse                   gmlParse
 
2768
#define yyStackEntry            gml_yyStackEntry
 
2769
#define yyzerominor             gml_yyzerominor
 
2770
#define yy_accept               gml_yy_accept
 
2771
#define yy_action               gml_yy_action
 
2772
#define yy_base                 gml_yy_base
 
2773
#define yy_buffer_stack         gml_yy_buffer_stack
 
2774
#define yy_buffer_stack_max     gml_yy_buffer_stack_max
 
2775
#define yy_buffer_stack_top     gml_yy_buffer_stack_top
 
2776
#define yy_c_buf_p              gml_yy_c_buf_p
 
2777
#define yy_chk                  gml_yy_chk
 
2778
#define yy_def                  gml_yy_def
 
2779
#define yy_default              gml_yy_default
 
2780
#define yy_destructor           gml_yy_destructor
 
2781
#define yy_ec                   gml_yy_ec
 
2782
#define yy_fatal_error          gml_yy_fatal_error
 
2783
#define yy_find_reduce_action   gml_yy_find_reduce_action
 
2784
#define yy_find_shift_action    gml_yy_find_shift_action
 
2785
#define yy_get_next_buffer      gml_yy_get_next_buffer
 
2786
#define yy_get_previous_state   gml_yy_get_previous_state
 
2787
#define yy_init                 gml_yy_init
 
2788
#define yy_init_globals         gml_yy_init_globals
 
2789
#define yy_lookahead            gml_yy_lookahead
 
2790
#define yy_meta                 gml_yy_meta
 
2791
#define yy_nxt                  gml_yy_nxt
 
2792
#define yy_parse_failed         gml_yy_parse_failed
 
2793
#define yy_pop_parser_stack     gml_yy_pop_parser_stack
 
2794
#define yy_reduce               gml_yy_reduce
 
2795
#define yy_reduce_ofst          gml_yy_reduce_ofst
 
2796
#define yy_shift                gml_yy_shift
 
2797
#define yy_shift_ofst           gml_yy_shift_ofst
 
2798
#define yy_start                gml_yy_start
 
2799
#define yy_state_type           gml_yy_state_type
 
2800
#define yy_syntax_error         gml_yy_syntax_error
 
2801
#define yy_trans_info           gml_yy_trans_info
 
2802
#define yy_try_NUL_trans        gml_yy_try_NUL_trans
 
2803
#define yyParser                gml_yyParser
 
2804
#define yyStackEntry            gml_yyStackEntry
 
2805
#define yyStackOverflow         gml_yyStackOverflow
 
2806
#define yyRuleInfo              gml_yyRuleInfo
 
2807
#define yyunput                 gml_yyunput
 
2808
#define yyzerominor             gml_yyzerominor
 
2809
#define yyTraceFILE             gml_yyTraceFILE
 
2810
#define yyTracePrompt           gml_yyTracePrompt
 
2811
#define yyTokenName             gml_yyTokenName
 
2812
#define yyRuleName              gml_yyRuleName
 
2813
#define ParseTrace              gml_ParseTrace
 
2814
 
 
2815
 
 
2816
/*
 
2817
 GML_LEMON_H_START - LEMON generated header starts here 
 
2818
*/
 
2819
#define GML_NEWLINE                     1
 
2820
#define GML_END                         2
 
2821
#define GML_CLOSE                       3
 
2822
#define GML_OPEN                        4
 
2823
#define GML_KEYWORD                     5
 
2824
#define GML_EQ                          6
 
2825
#define GML_VALUE                       7
 
2826
#define GML_COORD                       8
 
2827
/*
 
2828
 GML_LEMON_H_END - LEMON generated header ends here 
 
2829
*/
 
2830
 
 
2831
 
 
2832
typedef union
 
2833
{
 
2834
    char *pval;
 
2835
    struct symtab *symp;
 
2836
} gml_yystype;
 
2837
#define YYSTYPE gml_yystype
 
2838
 
 
2839
 
 
2840
/* extern YYSTYPE yylval; */
 
2841
YYSTYPE GmlLval;
 
2842
 
 
2843
 
 
2844
 
 
2845
/*
 
2846
 GML_LEMON_START - LEMON generated code starts here 
 
2847
*/
 
2848
 
 
2849
/* Driver template for the LEMON parser generator.
 
2850
** The author disclaims copyright to this source code.
 
2851
*/
 
2852
/* First off, code is included that follows the "include" declaration
 
2853
** in the input grammar file. */
 
2854
#include <stdio.h>
 
2855
 
 
2856
/* Next is all token values, in a form suitable for use by makeheaders.
 
2857
** This section will be null unless lemon is run with the -m switch.
 
2858
*/
 
2859
/* 
 
2860
** These constants (all generated automatically by the parser generator)
 
2861
** specify the various kinds of tokens (terminals) that the parser
 
2862
** understands. 
 
2863
**
 
2864
** Each symbol here is a terminal symbol in the grammar.
 
2865
*/
 
2866
/* Make sure the INTERFACE macro is defined.
 
2867
*/
 
2868
#ifndef INTERFACE
 
2869
# define INTERFACE 1
 
2870
#endif
 
2871
/* The next thing included is series of defines which control
 
2872
** various aspects of the generated parser.
 
2873
**    YYCODETYPE         is the data type used for storing terminal
 
2874
**                       and nonterminal numbers.  "unsigned char" is
 
2875
**                       used if there are fewer than 250 terminals
 
2876
**                       and nonterminals.  "int" is used otherwise.
 
2877
**    YYNOCODE           is a number of type YYCODETYPE which corresponds
 
2878
**                       to no legal terminal or nonterminal number.  This
 
2879
**                       number is used to fill in empty slots of the hash 
 
2880
**                       table.
 
2881
**    YYFALLBACK         If defined, this indicates that one or more tokens
 
2882
**                       have fall-back values which should be used if the
 
2883
**                       original value of the token will not parse.
 
2884
**    YYACTIONTYPE       is the data type used for storing terminal
 
2885
**                       and nonterminal numbers.  "unsigned char" is
 
2886
**                       used if there are fewer than 250 rules and
 
2887
**                       states combined.  "int" is used otherwise.
 
2888
**    ParseTOKENTYPE     is the data type used for minor tokens given 
 
2889
**                       directly to the parser from the tokenizer.
 
2890
**    YYMINORTYPE        is the data type used for all minor tokens.
 
2891
**                       This is typically a union of many types, one of
 
2892
**                       which is ParseTOKENTYPE.  The entry in the union
 
2893
**                       for base tokens is called "yy0".
 
2894
**    YYSTACKDEPTH       is the maximum depth of the parser's stack.  If
 
2895
**                       zero the stack is dynamically sized using realloc()
 
2896
**    ParseARG_SDECL     A static variable declaration for the %extra_argument
 
2897
**    ParseARG_PDECL     A parameter declaration for the %extra_argument
 
2898
**    ParseARG_STORE     Code to store %extra_argument into yypParser
 
2899
**    ParseARG_FETCH     Code to extract %extra_argument from yypParser
 
2900
**    YYNSTATE           the combined number of states.
 
2901
**    YYNRULE            the number of rules in the grammar
 
2902
**    YYERRORSYMBOL      is the code number of the error symbol.  If not
 
2903
**                       defined, then do no error processing.
 
2904
*/
 
2905
#define YYCODETYPE unsigned char
 
2906
#define YYNOCODE 28
 
2907
#define YYACTIONTYPE unsigned char
 
2908
#define ParseTOKENTYPE void *
 
2909
typedef union {
 
2910
  int yyinit;
 
2911
  ParseTOKENTYPE yy0;
 
2912
} YYMINORTYPE;
 
2913
#ifndef YYSTACKDEPTH
 
2914
#define YYSTACKDEPTH 1000000
 
2915
#endif
 
2916
#define ParseARG_SDECL  gmlNodePtr *result ;
 
2917
#define ParseARG_PDECL , gmlNodePtr *result 
 
2918
#define ParseARG_FETCH  gmlNodePtr *result  = yypParser->result 
 
2919
#define ParseARG_STORE yypParser->result  = result 
 
2920
#define YYNSTATE 49
 
2921
#define YYNRULE 34
 
2922
#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
 
2923
#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
 
2924
#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)
 
2925
 
 
2926
/* The yyzerominor constant is used to initialize instances of
 
2927
** YYMINORTYPE objects to zero. */
 
2928
static const YYMINORTYPE yyzerominor = { 0 };
 
2929
 
 
2930
/* Define the yytestcase() macro to be a no-op if is not already defined
 
2931
** otherwise.
 
2932
**
 
2933
** Applications can choose to define yytestcase() in the %include section
 
2934
** to a macro that can assist in verifying code coverage.  For production
 
2935
** code the yytestcase() macro should be turned off.  But it is useful
 
2936
** for testing.
 
2937
*/
 
2938
#ifndef yytestcase
 
2939
# define yytestcase(X)
 
2940
#endif
 
2941
 
 
2942
 
 
2943
/* Next are the tables used to determine what action to take based on the
 
2944
** current state and lookahead token.  These tables are used to implement
 
2945
** functions that take a state number and lookahead value and return an
 
2946
** action integer.  
 
2947
**
 
2948
** Suppose the action integer is N.  Then the action is determined as
 
2949
** follows
 
2950
**
 
2951
**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead
 
2952
**                                      token onto the stack and goto state N.
 
2953
**
 
2954
**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE.
 
2955
**
 
2956
**   N == YYNSTATE+YYNRULE              A syntax error has occurred.
 
2957
**
 
2958
**   N == YYNSTATE+YYNRULE+1            The parser accepts its input.
 
2959
**
 
2960
**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused
 
2961
**                                      slots in the yy_action[] table.
 
2962
**
 
2963
** The action table is constructed as a single large table named yy_action[].
 
2964
** Given state S and lookahead X, the action is computed as
 
2965
**
 
2966
**      yy_action[ yy_shift_ofst[S] + X ]
 
2967
**
 
2968
** If the index value yy_shift_ofst[S]+X is out of range or if the value
 
2969
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
 
2970
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
 
2971
** and that yy_default[S] should be used instead.  
 
2972
**
 
2973
** The formula above is for computing the action when the lookahead is
 
2974
** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
 
2975
** a reduce action) then the yy_reduce_ofst[] array is used in place of
 
2976
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
 
2977
** YY_SHIFT_USE_DFLT.
 
2978
**
 
2979
** The following are the tables generated in this section:
 
2980
**
 
2981
**  yy_action[]        A single table containing all actions.
 
2982
**  yy_lookahead[]     A table containing the lookahead for each entry in
 
2983
**                     yy_action.  Used to detect hash collisions.
 
2984
**  yy_shift_ofst[]    For each state, the offset into yy_action for
 
2985
**                     shifting terminals.
 
2986
**  yy_reduce_ofst[]   For each state, the offset into yy_action for
 
2987
**                     shifting non-terminals after a reduce.
 
2988
**  yy_default[]       Default action for each state.
 
2989
*/
 
2990
static const YYACTIONTYPE yy_action[] = {
 
2991
 /*     0 */    20,   28,   29,    4,   48,    5,    3,    3,    5,    5,
 
2992
 /*    10 */    42,   84,    1,   42,   42,   47,   46,    2,   10,    5,
 
2993
 /*    20 */    21,   12,   32,   23,   42,   38,   22,    6,   49,   23,
 
2994
 /*    30 */    13,   19,   14,   15,   35,    8,    8,   10,   25,   11,
 
2995
 /*    40 */    18,   34,   33,   45,   37,   16,   40,   17,   41,   14,
 
2996
 /*    50 */     9,   23,   43,    7,   45,   27,   30,   26,   31,   36,
 
2997
 /*    60 */    39,   44,   24,
 
2998
};
 
2999
static const YYCODETYPE yy_lookahead[] = {
 
3000
 /*     0 */    12,   13,   14,   15,   16,   17,   15,   15,   17,   17,
 
3001
 /*    10 */    22,   10,   11,   22,   22,   24,   24,   15,   18,   17,
 
3002
 /*    20 */     2,    3,    8,    5,   22,   25,    2,    3,    0,    5,
 
3003
 /*    30 */    18,   19,    4,   20,   21,   20,   20,   18,    2,    3,
 
3004
 /*    40 */     2,   26,   26,    5,   25,   20,   21,   20,   21,    4,
 
3005
 /*    50 */    18,    5,   23,   20,    5,    1,    3,   23,    3,    7,
 
3006
 /*    60 */     3,    3,    6,
 
3007
};
 
3008
#define YY_SHIFT_USE_DFLT (-1)
 
3009
#define YY_SHIFT_MAX 26
 
3010
static const signed char yy_shift_ofst[] = {
 
3011
 /*     0 */    -1,   28,   45,   45,   45,   18,   14,   14,   14,   46,
 
3012
 /*    10 */    46,   14,   14,   24,   38,   14,   14,   14,   49,   36,
 
3013
 /*    20 */    54,   53,   55,   56,   52,   57,   58,
 
3014
};
 
3015
#define YY_REDUCE_USE_DFLT (-13)
 
3016
#define YY_REDUCE_MAX 18
 
3017
static const signed char yy_reduce_ofst[] = {
 
3018
 /*     0 */     1,  -12,   -9,   -8,    2,   12,   13,   15,   16,    0,
 
3019
 /*    10 */    19,   25,   27,   32,   29,   33,   33,   33,   34,
 
3020
};
 
3021
static const YYACTIONTYPE yy_default[] = {
 
3022
 /*     0 */    50,   83,   72,   72,   54,   83,   60,   80,   80,   76,
 
3023
 /*    10 */    76,   61,   59,   83,   83,   64,   66,   62,   83,   83,
 
3024
 /*    20 */    83,   83,   83,   83,   83,   83,   83,   51,   52,   53,
 
3025
 /*    30 */    56,   57,   79,   81,   82,   65,   75,   77,   78,   58,
 
3026
 /*    40 */    67,   63,   68,   69,   70,   71,   73,   74,   55,
 
3027
};
 
3028
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
 
3029
 
 
3030
/* The next table maps tokens into fallback tokens.  If a construct
 
3031
** like the following:
 
3032
** 
 
3033
**      %fallback ID X Y Z.
 
3034
**
 
3035
** appears in the grammar, then ID becomes a fallback token for X, Y,
 
3036
** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
 
3037
** but it does not parse, the type of the token is changed to ID and
 
3038
** the parse is retried before an error is thrown.
 
3039
*/
 
3040
#ifdef YYFALLBACK
 
3041
static const YYCODETYPE yyFallback[] = {
 
3042
};
 
3043
#endif /* YYFALLBACK */
 
3044
 
 
3045
/* The following structure represents a single element of the
 
3046
** parser's stack.  Information stored includes:
 
3047
**
 
3048
**   +  The state number for the parser at this level of the stack.
 
3049
**
 
3050
**   +  The value of the token stored at this level of the stack.
 
3051
**      (In other words, the "major" token.)
 
3052
**
 
3053
**   +  The semantic value stored at this level of the stack.  This is
 
3054
**      the information used by the action routines in the grammar.
 
3055
**      It is sometimes called the "minor" token.
 
3056
*/
 
3057
struct yyStackEntry {
 
3058
  YYACTIONTYPE stateno;  /* The state-number */
 
3059
  YYCODETYPE major;      /* The major token value.  This is the code
 
3060
                         ** number for the token at this stack level */
 
3061
  YYMINORTYPE minor;     /* The user-supplied minor token value.  This
 
3062
                         ** is the value of the token  */
 
3063
};
 
3064
typedef struct yyStackEntry yyStackEntry;
 
3065
 
 
3066
/* The state of the parser is completely contained in an instance of
 
3067
** the following structure */
 
3068
struct yyParser {
 
3069
  int yyidx;                    /* Index of top element in stack */
 
3070
#ifdef YYTRACKMAXSTACKDEPTH
 
3071
  int yyidxMax;                 /* Maximum value of yyidx */
 
3072
#endif
 
3073
  int yyerrcnt;                 /* Shifts left before out of the error */
 
3074
  ParseARG_SDECL                /* A place to hold %extra_argument */
 
3075
#if YYSTACKDEPTH<=0
 
3076
  int yystksz;                  /* Current side of the stack */
 
3077
  yyStackEntry *yystack;        /* The parser's stack */
 
3078
#else
 
3079
  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
 
3080
#endif
 
3081
};
 
3082
typedef struct yyParser yyParser;
 
3083
 
 
3084
#ifndef NDEBUG
 
3085
#include <stdio.h>
 
3086
static FILE *yyTraceFILE = 0;
 
3087
static char *yyTracePrompt = 0;
 
3088
#endif /* NDEBUG */
 
3089
 
 
3090
#ifndef NDEBUG
 
3091
/* 
 
3092
** Turn parser tracing on by giving a stream to which to write the trace
 
3093
** and a prompt to preface each trace message.  Tracing is turned off
 
3094
** by making either argument NULL 
 
3095
**
 
3096
** Inputs:
 
3097
** <ul>
 
3098
** <li> A FILE* to which trace output should be written.
 
3099
**      If NULL, then tracing is turned off.
 
3100
** <li> A prefix string written at the beginning of every
 
3101
**      line of trace output.  If NULL, then tracing is
 
3102
**      turned off.
 
3103
** </ul>
 
3104
**
 
3105
** Outputs:
 
3106
** None.
 
3107
*/
 
3108
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
 
3109
  yyTraceFILE = TraceFILE;
 
3110
  yyTracePrompt = zTracePrompt;
 
3111
  if( yyTraceFILE==0 ) yyTracePrompt = 0;
 
3112
  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
 
3113
}
 
3114
#endif /* NDEBUG */
 
3115
 
 
3116
#ifndef NDEBUG
 
3117
/* For tracing shifts, the names of all terminals and nonterminals
 
3118
** are required.  The following table supplies these names */
 
3119
static const char *const yyTokenName[] = { 
 
3120
  "$",             "GML_NEWLINE",   "GML_END",       "GML_CLOSE",   
 
3121
  "GML_OPEN",      "GML_KEYWORD",   "GML_EQ",        "GML_VALUE",   
 
3122
  "GML_COORD",     "error",         "main",          "in",          
 
3123
  "state",         "program",       "gml_tree",      "node",        
 
3124
  "node_chain",    "open_tag",      "attr",          "attributes",  
 
3125
  "coord",         "coord_chain",   "close_tag",     "keyword",     
 
3126
  "extra_nodes",   "extra_attr",    "extra_coord", 
 
3127
};
 
3128
#endif /* NDEBUG */
 
3129
 
 
3130
#ifndef NDEBUG
 
3131
/* For tracing reduce actions, the names of all rules are required.
 
3132
*/
 
3133
static const char *const yyRuleName[] = {
 
3134
 /*   0 */ "main ::= in",
 
3135
 /*   1 */ "in ::=",
 
3136
 /*   2 */ "in ::= in state GML_NEWLINE",
 
3137
 /*   3 */ "state ::= program",
 
3138
 /*   4 */ "program ::= gml_tree",
 
3139
 /*   5 */ "gml_tree ::= node",
 
3140
 /*   6 */ "gml_tree ::= node_chain",
 
3141
 /*   7 */ "node ::= open_tag GML_END GML_CLOSE",
 
3142
 /*   8 */ "node ::= open_tag attr GML_END GML_CLOSE",
 
3143
 /*   9 */ "node ::= open_tag attributes GML_END GML_CLOSE",
 
3144
 /*  10 */ "node ::= open_tag GML_CLOSE",
 
3145
 /*  11 */ "node ::= open_tag attr GML_CLOSE",
 
3146
 /*  12 */ "node ::= open_tag attributes GML_CLOSE",
 
3147
 /*  13 */ "node ::= open_tag GML_CLOSE coord",
 
3148
 /*  14 */ "node ::= open_tag GML_CLOSE coord_chain",
 
3149
 /*  15 */ "node ::= open_tag attr GML_CLOSE coord",
 
3150
 /*  16 */ "node ::= open_tag attr GML_CLOSE coord_chain",
 
3151
 /*  17 */ "node ::= open_tag attributes GML_CLOSE coord",
 
3152
 /*  18 */ "node ::= open_tag attributes GML_CLOSE coord_chain",
 
3153
 /*  19 */ "node ::= close_tag",
 
3154
 /*  20 */ "open_tag ::= GML_OPEN keyword",
 
3155
 /*  21 */ "close_tag ::= GML_OPEN GML_END keyword GML_CLOSE",
 
3156
 /*  22 */ "keyword ::= GML_KEYWORD",
 
3157
 /*  23 */ "extra_nodes ::=",
 
3158
 /*  24 */ "extra_nodes ::= node extra_nodes",
 
3159
 /*  25 */ "node_chain ::= node node extra_nodes",
 
3160
 /*  26 */ "attr ::= GML_KEYWORD GML_EQ GML_VALUE",
 
3161
 /*  27 */ "extra_attr ::=",
 
3162
 /*  28 */ "extra_attr ::= attr extra_attr",
 
3163
 /*  29 */ "attributes ::= attr attr extra_attr",
 
3164
 /*  30 */ "coord ::= GML_COORD",
 
3165
 /*  31 */ "extra_coord ::=",
 
3166
 /*  32 */ "extra_coord ::= coord extra_coord",
 
3167
 /*  33 */ "coord_chain ::= coord coord extra_coord",
 
3168
};
 
3169
#endif /* NDEBUG */
 
3170
 
 
3171
 
 
3172
#if YYSTACKDEPTH<=0
 
3173
/*
 
3174
** Try to increase the size of the parser stack.
 
3175
*/
 
3176
static void yyGrowStack(yyParser *p){
 
3177
  int newSize;
 
3178
  yyStackEntry *pNew;
 
3179
 
 
3180
  newSize = p->yystksz*2 + 100;
 
3181
  pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
 
3182
  if( pNew ){
 
3183
    p->yystack = pNew;
 
3184
    p->yystksz = newSize;
 
3185
#ifndef NDEBUG
 
3186
    if( yyTraceFILE ){
 
3187
      fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
 
3188
              yyTracePrompt, p->yystksz);
 
3189
    }
 
3190
#endif
 
3191
  }
 
3192
}
 
3193
#endif
 
3194
 
 
3195
/* 
 
3196
** This function allocates a new parser.
 
3197
** The only argument is a pointer to a function which works like
 
3198
** malloc.
 
3199
**
 
3200
** Inputs:
 
3201
** A pointer to the function used to allocate memory.
 
3202
**
 
3203
** Outputs:
 
3204
** A pointer to a parser.  This pointer is used in subsequent calls
 
3205
** to Parse and ParseFree.
 
3206
*/
 
3207
void *ParseAlloc(void *(*mallocProc)(size_t)){
 
3208
  yyParser *pParser;
 
3209
  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
 
3210
  if( pParser ){
 
3211
    pParser->yyidx = -1;
 
3212
#ifdef YYTRACKMAXSTACKDEPTH
 
3213
    pParser->yyidxMax = 0;
 
3214
#endif
 
3215
#if YYSTACKDEPTH<=0
 
3216
    pParser->yystack = NULL;
 
3217
    pParser->yystksz = 0;
 
3218
    yyGrowStack(pParser);
 
3219
#endif
 
3220
  }
 
3221
  return pParser;
 
3222
}
 
3223
 
 
3224
/* The following function deletes the value associated with a
 
3225
** symbol.  The symbol can be either a terminal or nonterminal.
 
3226
** "yymajor" is the symbol code, and "yypminor" is a pointer to
 
3227
** the value.
 
3228
*/
 
3229
static void yy_destructor(
 
3230
  yyParser *yypParser,    /* The parser */
 
3231
  YYCODETYPE yymajor,     /* Type code for object to destroy */
 
3232
  YYMINORTYPE *yypminor   /* The object to be destroyed */
 
3233
){
 
3234
  ParseARG_FETCH;
 
3235
  switch( yymajor ){
 
3236
    /* Here is inserted the actions which take place when a
 
3237
    ** terminal or non-terminal is destroyed.  This can happen
 
3238
    ** when the symbol is popped from the stack during a
 
3239
    ** reduce or during error processing or when a parser is 
 
3240
    ** being destroyed before it is finished parsing.
 
3241
    **
 
3242
    ** Note: during a reduce, the only symbols destroyed are those
 
3243
    ** which appear on the RHS of the rule, but which are not used
 
3244
    ** inside the C code.
 
3245
    */
 
3246
    default:  break;   /* If no destructor action specified: do nothing */
 
3247
  }
 
3248
}
 
3249
 
 
3250
/*
 
3251
** Pop the parser's stack once.
 
3252
**
 
3253
** If there is a destructor routine associated with the token which
 
3254
** is popped from the stack, then call it.
 
3255
**
 
3256
** Return the major token number for the symbol popped.
 
3257
*/
 
3258
static int yy_pop_parser_stack(yyParser *pParser){
 
3259
  YYCODETYPE yymajor;
 
3260
  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
 
3261
 
 
3262
  if( pParser->yyidx<0 ) return 0;
 
3263
#ifndef NDEBUG
 
3264
  if( yyTraceFILE && pParser->yyidx>=0 ){
 
3265
    fprintf(yyTraceFILE,"%sPopping %s\n",
 
3266
      yyTracePrompt,
 
3267
      yyTokenName[yytos->major]);
 
3268
  }
 
3269
#endif
 
3270
  yymajor = yytos->major;
 
3271
  yy_destructor(pParser, yymajor, &yytos->minor);
 
3272
  pParser->yyidx--;
 
3273
  return yymajor;
 
3274
}
 
3275
 
 
3276
/* 
 
3277
** Deallocate and destroy a parser.  Destructors are all called for
 
3278
** all stack elements before shutting the parser down.
 
3279
**
 
3280
** Inputs:
 
3281
** <ul>
 
3282
** <li>  A pointer to the parser.  This should be a pointer
 
3283
**       obtained from ParseAlloc.
 
3284
** <li>  A pointer to a function used to reclaim memory obtained
 
3285
**       from malloc.
 
3286
** </ul>
 
3287
*/
 
3288
void ParseFree(
 
3289
  void *p,                    /* The parser to be deleted */
 
3290
  void (*freeProc)(void*)     /* Function used to reclaim memory */
 
3291
){
 
3292
  yyParser *pParser = (yyParser*)p;
 
3293
  if( pParser==0 ) return;
 
3294
  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
 
3295
#if YYSTACKDEPTH<=0
 
3296
  free(pParser->yystack);
 
3297
#endif
 
3298
  (*freeProc)((void*)pParser);
 
3299
}
 
3300
 
 
3301
/*
 
3302
** Return the peak depth of the stack for a parser.
 
3303
*/
 
3304
#ifdef YYTRACKMAXSTACKDEPTH
 
3305
int ParseStackPeak(void *p){
 
3306
  yyParser *pParser = (yyParser*)p;
 
3307
  return pParser->yyidxMax;
 
3308
}
 
3309
#endif
 
3310
 
 
3311
/*
 
3312
** Find the appropriate action for a parser given the terminal
 
3313
** look-ahead token iLookAhead.
 
3314
**
 
3315
** If the look-ahead token is YYNOCODE, then check to see if the action is
 
3316
** independent of the look-ahead.  If it is, return the action, otherwise
 
3317
** return YY_NO_ACTION.
 
3318
*/
 
3319
static int yy_find_shift_action(
 
3320
  yyParser *pParser,        /* The parser */
 
3321
  YYCODETYPE iLookAhead     /* The look-ahead token */
 
3322
){
 
3323
  int i;
 
3324
  int stateno = pParser->yystack[pParser->yyidx].stateno;
 
3325
 
 
3326
  if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
 
3327
    return yy_default[stateno];
 
3328
  }
 
3329
  assert( iLookAhead!=YYNOCODE );
 
3330
  i += iLookAhead;
 
3331
  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
 
3332
    if( iLookAhead>0 ){
 
3333
#ifdef YYFALLBACK
 
3334
      YYCODETYPE iFallback;            /* Fallback token */
 
3335
      if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
 
3336
             && (iFallback = yyFallback[iLookAhead])!=0 ){
 
3337
#ifndef NDEBUG
 
3338
        if( yyTraceFILE ){
 
3339
          fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
 
3340
             yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
 
3341
        }
 
3342
#endif
 
3343
        return yy_find_shift_action(pParser, iFallback);
 
3344
      }
 
3345
#endif
 
3346
#ifdef YYWILDCARD
 
3347
      {
 
3348
        int j = i - iLookAhead + YYWILDCARD;
 
3349
        if( j>=0 && j<YY_SZ_ACTTAB && yy_lookahead[j]==YYWILDCARD ){
 
3350
#ifndef NDEBUG
 
3351
          if( yyTraceFILE ){
 
3352
            fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
 
3353
               yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
 
3354
          }
 
3355
#endif /* NDEBUG */
 
3356
          return yy_action[j];
 
3357
        }
 
3358
      }
 
3359
#endif /* YYWILDCARD */
 
3360
    }
 
3361
    return yy_default[stateno];
 
3362
  }else{
 
3363
    return yy_action[i];
 
3364
  }
 
3365
}
 
3366
 
 
3367
/*
 
3368
** Find the appropriate action for a parser given the non-terminal
 
3369
** look-ahead token iLookAhead.
 
3370
**
 
3371
** If the look-ahead token is YYNOCODE, then check to see if the action is
 
3372
** independent of the look-ahead.  If it is, return the action, otherwise
 
3373
** return YY_NO_ACTION.
 
3374
*/
 
3375
static int yy_find_reduce_action(
 
3376
  int stateno,              /* Current state number */
 
3377
  YYCODETYPE iLookAhead     /* The look-ahead token */
 
3378
){
 
3379
  int i;
 
3380
#ifdef YYERRORSYMBOL
 
3381
  if( stateno>YY_REDUCE_MAX ){
 
3382
    return yy_default[stateno];
 
3383
  }
 
3384
#else
 
3385
  assert( stateno<=YY_REDUCE_MAX );
 
3386
#endif
 
3387
  i = yy_reduce_ofst[stateno];
 
3388
  assert( i!=YY_REDUCE_USE_DFLT );
 
3389
  assert( iLookAhead!=YYNOCODE );
 
3390
  i += iLookAhead;
 
3391
#ifdef YYERRORSYMBOL
 
3392
  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
 
3393
    return yy_default[stateno];
 
3394
  }
 
3395
#else
 
3396
  assert( i>=0 && i<YY_SZ_ACTTAB );
 
3397
  assert( yy_lookahead[i]==iLookAhead );
 
3398
#endif
 
3399
  return yy_action[i];
 
3400
}
 
3401
 
 
3402
/*
 
3403
** The following routine is called if the stack overflows.
 
3404
*/
 
3405
static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
 
3406
   ParseARG_FETCH;
 
3407
   yypParser->yyidx--;
 
3408
#ifndef NDEBUG
 
3409
   if( yyTraceFILE ){
 
3410
     fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
 
3411
   }
 
3412
#endif
 
3413
   while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
 
3414
   /* Here code is inserted which will execute if the parser
 
3415
   ** stack every overflows */
 
3416
 
 
3417
     fprintf(stderr,"Giving up.  Parser stack overflow\n");
 
3418
   ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
 
3419
}
 
3420
 
 
3421
/*
 
3422
** Perform a shift action.
 
3423
*/
 
3424
static void yy_shift(
 
3425
  yyParser *yypParser,          /* The parser to be shifted */
 
3426
  int yyNewState,               /* The new state to shift in */
 
3427
  int yyMajor,                  /* The major token to shift in */
 
3428
  YYMINORTYPE *yypMinor         /* Pointer to the minor token to shift in */
 
3429
){
 
3430
  yyStackEntry *yytos;
 
3431
  yypParser->yyidx++;
 
3432
#ifdef YYTRACKMAXSTACKDEPTH
 
3433
  if( yypParser->yyidx>yypParser->yyidxMax ){
 
3434
    yypParser->yyidxMax = yypParser->yyidx;
 
3435
  }
 
3436
#endif
 
3437
#if YYSTACKDEPTH>0 
 
3438
  if( yypParser->yyidx>=YYSTACKDEPTH ){
 
3439
    yyStackOverflow(yypParser, yypMinor);
 
3440
    return;
 
3441
  }
 
3442
#else
 
3443
  if( yypParser->yyidx>=yypParser->yystksz ){
 
3444
    yyGrowStack(yypParser);
 
3445
    if( yypParser->yyidx>=yypParser->yystksz ){
 
3446
      yyStackOverflow(yypParser, yypMinor);
 
3447
      return;
 
3448
    }
 
3449
  }
 
3450
#endif
 
3451
  yytos = &yypParser->yystack[yypParser->yyidx];
 
3452
  yytos->stateno = (YYACTIONTYPE)yyNewState;
 
3453
  yytos->major = (YYCODETYPE)yyMajor;
 
3454
  yytos->minor = *yypMinor;
 
3455
#ifndef NDEBUG
 
3456
  if( yyTraceFILE && yypParser->yyidx>0 ){
 
3457
    int i;
 
3458
    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
 
3459
    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
 
3460
    for(i=1; i<=yypParser->yyidx; i++)
 
3461
      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
 
3462
    fprintf(yyTraceFILE,"\n");
 
3463
  }
 
3464
#endif
 
3465
}
 
3466
 
 
3467
/* The following table contains information about every rule that
 
3468
** is used during the reduce.
 
3469
*/
 
3470
static const struct {
 
3471
  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
 
3472
  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
 
3473
} yyRuleInfo[] = {
 
3474
  { 10, 1 },
 
3475
  { 11, 0 },
 
3476
  { 11, 3 },
 
3477
  { 12, 1 },
 
3478
  { 13, 1 },
 
3479
  { 14, 1 },
 
3480
  { 14, 1 },
 
3481
  { 15, 3 },
 
3482
  { 15, 4 },
 
3483
  { 15, 4 },
 
3484
  { 15, 2 },
 
3485
  { 15, 3 },
 
3486
  { 15, 3 },
 
3487
  { 15, 3 },
 
3488
  { 15, 3 },
 
3489
  { 15, 4 },
 
3490
  { 15, 4 },
 
3491
  { 15, 4 },
 
3492
  { 15, 4 },
 
3493
  { 15, 1 },
 
3494
  { 17, 2 },
 
3495
  { 22, 4 },
 
3496
  { 23, 1 },
 
3497
  { 24, 0 },
 
3498
  { 24, 2 },
 
3499
  { 16, 3 },
 
3500
  { 18, 3 },
 
3501
  { 25, 0 },
 
3502
  { 25, 2 },
 
3503
  { 19, 3 },
 
3504
  { 20, 1 },
 
3505
  { 26, 0 },
 
3506
  { 26, 2 },
 
3507
  { 21, 3 },
 
3508
};
 
3509
 
 
3510
static void yy_accept(yyParser*);  /* Forward Declaration */
 
3511
 
 
3512
/*
 
3513
** Perform a reduce action and the shift that must immediately
 
3514
** follow the reduce.
 
3515
*/
 
3516
static void yy_reduce(
 
3517
  yyParser *yypParser,         /* The parser */
 
3518
  int yyruleno                 /* Number of the rule by which to reduce */
 
3519
){
 
3520
  int yygoto;                     /* The next state */
 
3521
  int yyact;                      /* The next action */
 
3522
  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
 
3523
  yyStackEntry *yymsp;            /* The top of the parser's stack */
 
3524
  int yysize;                     /* Amount to pop the stack */
 
3525
  ParseARG_FETCH;
 
3526
  yymsp = &yypParser->yystack[yypParser->yyidx];
 
3527
#ifndef NDEBUG
 
3528
  if( yyTraceFILE && yyruleno>=0 
 
3529
        && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
 
3530
    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
 
3531
      yyRuleName[yyruleno]);
 
3532
  }
 
3533
#endif /* NDEBUG */
 
3534
 
 
3535
  /* Silence complaints from purify about yygotominor being uninitialized
 
3536
  ** in some cases when it is copied into the stack after the following
 
3537
  ** switch.  yygotominor is uninitialized when a rule reduces that does
 
3538
  ** not set the value of its left-hand side nonterminal.  Leaving the
 
3539
  ** value of the nonterminal uninitialized is utterly harmless as long
 
3540
  ** as the value is never used.  So really the only thing this code
 
3541
  ** accomplishes is to quieten purify.  
 
3542
  **
 
3543
  ** 2007-01-16:  The wireshark project (www.wireshark.org) reports that
 
3544
  ** without this code, their parser segfaults.  I'm not sure what there
 
3545
  ** parser is doing to make this happen.  This is the second bug report
 
3546
  ** from wireshark this week.  Clearly they are stressing Lemon in ways
 
3547
  ** that it has not been previously stressed...  (SQLite ticket #2172)
 
3548
  */
 
3549
  /*memset(&yygotominor, 0, sizeof(yygotominor));*/
 
3550
  yygotominor = yyzerominor;
 
3551
 
 
3552
 
 
3553
  switch( yyruleno ){
 
3554
  /* Beginning here are the reduction cases.  A typical example
 
3555
  ** follows:
 
3556
  **   case 0:
 
3557
  **  #line <lineno> <grammarfile>
 
3558
  **     { ... }           // User supplied code
 
3559
  **  #line <lineno> <thisfile>
 
3560
  **     break;
 
3561
  */
 
3562
      case 5: /* gml_tree ::= node */
 
3563
      case 6: /* gml_tree ::= node_chain */ yytestcase(yyruleno==6);
 
3564
{ *result = yymsp[0].minor.yy0; }
 
3565
        break;
 
3566
      case 7: /* node ::= open_tag GML_END GML_CLOSE */
 
3567
{ yygotominor.yy0 = gml_createSelfClosedNode((void *)yymsp[-2].minor.yy0, NULL); }
 
3568
        break;
 
3569
      case 8: /* node ::= open_tag attr GML_END GML_CLOSE */
 
3570
      case 9: /* node ::= open_tag attributes GML_END GML_CLOSE */ yytestcase(yyruleno==9);
 
3571
{ yygotominor.yy0 = gml_createSelfClosedNode((void *)yymsp[-3].minor.yy0, (void *)yymsp[-2].minor.yy0); }
 
3572
        break;
 
3573
      case 10: /* node ::= open_tag GML_CLOSE */
 
3574
{ yygotominor.yy0 = gml_createNode((void *)yymsp[-1].minor.yy0, NULL, NULL); }
 
3575
        break;
 
3576
      case 11: /* node ::= open_tag attr GML_CLOSE */
 
3577
      case 12: /* node ::= open_tag attributes GML_CLOSE */ yytestcase(yyruleno==12);
 
3578
{ yygotominor.yy0 = gml_createNode((void *)yymsp[-2].minor.yy0, (void *)yymsp[-1].minor.yy0, NULL); }
 
3579
        break;
 
3580
      case 13: /* node ::= open_tag GML_CLOSE coord */
 
3581
      case 14: /* node ::= open_tag GML_CLOSE coord_chain */ yytestcase(yyruleno==14);
 
3582
{ yygotominor.yy0 = gml_createNode((void *)yymsp[-2].minor.yy0, NULL, (void *)yymsp[0].minor.yy0); }
 
3583
        break;
 
3584
      case 15: /* node ::= open_tag attr GML_CLOSE coord */
 
3585
      case 16: /* node ::= open_tag attr GML_CLOSE coord_chain */ yytestcase(yyruleno==16);
 
3586
      case 17: /* node ::= open_tag attributes GML_CLOSE coord */ yytestcase(yyruleno==17);
 
3587
      case 18: /* node ::= open_tag attributes GML_CLOSE coord_chain */ yytestcase(yyruleno==18);
 
3588
{ yygotominor.yy0 = gml_createNode((void *)yymsp[-3].minor.yy0, (void *)yymsp[-2].minor.yy0, (void *)yymsp[0].minor.yy0); }
 
3589
        break;
 
3590
      case 19: /* node ::= close_tag */
 
3591
{ yygotominor.yy0 = gml_closingNode((void *)yymsp[0].minor.yy0); }
 
3592
        break;
 
3593
      case 20: /* open_tag ::= GML_OPEN keyword */
 
3594
      case 22: /* keyword ::= GML_KEYWORD */ yytestcase(yyruleno==22);
 
3595
{ yygotominor.yy0 = yymsp[0].minor.yy0; }
 
3596
        break;
 
3597
      case 21: /* close_tag ::= GML_OPEN GML_END keyword GML_CLOSE */
 
3598
{ yygotominor.yy0 = yymsp[-1].minor.yy0; }
 
3599
        break;
 
3600
      case 23: /* extra_nodes ::= */
 
3601
      case 27: /* extra_attr ::= */ yytestcase(yyruleno==27);
 
3602
      case 31: /* extra_coord ::= */ yytestcase(yyruleno==31);
 
3603
{ yygotominor.yy0 = NULL; }
 
3604
        break;
 
3605
      case 24: /* extra_nodes ::= node extra_nodes */
 
3606
{ ((gmlNodePtr)yymsp[-1].minor.yy0)->Next = (gmlNodePtr)yymsp[0].minor.yy0;  yygotominor.yy0 = yymsp[-1].minor.yy0; }
 
3607
        break;
 
3608
      case 25: /* node_chain ::= node node extra_nodes */
 
3609
 
3610
           ((gmlNodePtr)yymsp[-1].minor.yy0)->Next = (gmlNodePtr)yymsp[0].minor.yy0; 
 
3611
           ((gmlNodePtr)yymsp[-2].minor.yy0)->Next = (gmlNodePtr)yymsp[-1].minor.yy0;
 
3612
           yygotominor.yy0 = yymsp[-2].minor.yy0;
 
3613
        }
 
3614
        break;
 
3615
      case 26: /* attr ::= GML_KEYWORD GML_EQ GML_VALUE */
 
3616
{ yygotominor.yy0 = gml_attribute((void *)yymsp[-2].minor.yy0, (void *)yymsp[0].minor.yy0); }
 
3617
        break;
 
3618
      case 28: /* extra_attr ::= attr extra_attr */
 
3619
{ ((gmlAttrPtr)yymsp[-1].minor.yy0)->Next = (gmlAttrPtr)yymsp[0].minor.yy0;  yygotominor.yy0 = yymsp[-1].minor.yy0; }
 
3620
        break;
 
3621
      case 29: /* attributes ::= attr attr extra_attr */
 
3622
 
3623
           ((gmlAttrPtr)yymsp[-1].minor.yy0)->Next = (gmlAttrPtr)yymsp[0].minor.yy0; 
 
3624
           ((gmlAttrPtr)yymsp[-2].minor.yy0)->Next = (gmlAttrPtr)yymsp[-1].minor.yy0;
 
3625
           yygotominor.yy0 = yymsp[-2].minor.yy0;
 
3626
        }
 
3627
        break;
 
3628
      case 30: /* coord ::= GML_COORD */
 
3629
{ yygotominor.yy0 = gml_coord((void *)yymsp[0].minor.yy0); }
 
3630
        break;
 
3631
      case 32: /* extra_coord ::= coord extra_coord */
 
3632
{ ((gmlCoordPtr)yymsp[-1].minor.yy0)->Next = (gmlCoordPtr)yymsp[0].minor.yy0;  yygotominor.yy0 = yymsp[-1].minor.yy0; }
 
3633
        break;
 
3634
      case 33: /* coord_chain ::= coord coord extra_coord */
 
3635
 
3636
           ((gmlCoordPtr)yymsp[-1].minor.yy0)->Next = (gmlCoordPtr)yymsp[0].minor.yy0; 
 
3637
           ((gmlCoordPtr)yymsp[-2].minor.yy0)->Next = (gmlCoordPtr)yymsp[-1].minor.yy0;
 
3638
           yygotominor.yy0 = yymsp[-2].minor.yy0;
 
3639
        }
 
3640
        break;
 
3641
      default:
 
3642
      /* (0) main ::= in */ yytestcase(yyruleno==0);
 
3643
      /* (1) in ::= */ yytestcase(yyruleno==1);
 
3644
      /* (2) in ::= in state GML_NEWLINE */ yytestcase(yyruleno==2);
 
3645
      /* (3) state ::= program */ yytestcase(yyruleno==3);
 
3646
      /* (4) program ::= gml_tree */ yytestcase(yyruleno==4);
 
3647
        break;
 
3648
  };
 
3649
  yygoto = yyRuleInfo[yyruleno].lhs;
 
3650
  yysize = yyRuleInfo[yyruleno].nrhs;
 
3651
  yypParser->yyidx -= yysize;
 
3652
  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
 
3653
  if( yyact < YYNSTATE ){
 
3654
#ifdef NDEBUG
 
3655
    /* If we are not debugging and the reduce action popped at least
 
3656
    ** one element off the stack, then we can push the new element back
 
3657
    ** onto the stack here, and skip the stack overflow test in yy_shift().
 
3658
    ** That gives a significant speed improvement. */
 
3659
    if( yysize ){
 
3660
      yypParser->yyidx++;
 
3661
      yymsp -= yysize-1;
 
3662
      yymsp->stateno = (YYACTIONTYPE)yyact;
 
3663
      yymsp->major = (YYCODETYPE)yygoto;
 
3664
      yymsp->minor = yygotominor;
 
3665
    }else
 
3666
#endif
 
3667
    {
 
3668
      yy_shift(yypParser,yyact,yygoto,&yygotominor);
 
3669
    }
 
3670
  }else{
 
3671
    assert( yyact == YYNSTATE + YYNRULE + 1 );
 
3672
    yy_accept(yypParser);
 
3673
  }
 
3674
}
 
3675
 
 
3676
/*
 
3677
** The following code executes when the parse fails
 
3678
*/
 
3679
#ifndef YYNOERRORRECOVERY
 
3680
static void yy_parse_failed(
 
3681
  yyParser *yypParser           /* The parser */
 
3682
){
 
3683
  ParseARG_FETCH;
 
3684
#ifndef NDEBUG
 
3685
  if( yyTraceFILE ){
 
3686
    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
 
3687
  }
 
3688
#endif
 
3689
  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
 
3690
  /* Here code is inserted which will be executed whenever the
 
3691
  ** parser fails */
 
3692
  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
 
3693
}
 
3694
#endif /* YYNOERRORRECOVERY */
 
3695
 
 
3696
/*
 
3697
** The following code executes when a syntax error first occurs.
 
3698
*/
 
3699
static void yy_syntax_error(
 
3700
  yyParser *yypParser,           /* The parser */
 
3701
  int yymajor,                   /* The major type of the error token */
 
3702
  YYMINORTYPE yyminor            /* The minor type of the error token */
 
3703
){
 
3704
  ParseARG_FETCH;
 
3705
#define TOKEN (yyminor.yy0)
 
3706
 
 
3707
/* 
 
3708
** when the LEMON parser encounters an error
 
3709
** then this global variable is set 
 
3710
*/
 
3711
        gml_parse_error = 1;
 
3712
        *result = NULL;
 
3713
  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
 
3714
}
 
3715
 
 
3716
/*
 
3717
** The following is executed when the parser accepts
 
3718
*/
 
3719
static void yy_accept(
 
3720
  yyParser *yypParser           /* The parser */
 
3721
){
 
3722
  ParseARG_FETCH;
 
3723
#ifndef NDEBUG
 
3724
  if( yyTraceFILE ){
 
3725
    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
 
3726
  }
 
3727
#endif
 
3728
  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
 
3729
  /* Here code is inserted which will be executed whenever the
 
3730
  ** parser accepts */
 
3731
  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
 
3732
}
 
3733
 
 
3734
/* The main parser program.
 
3735
** The first argument is a pointer to a structure obtained from
 
3736
** "ParseAlloc" which describes the current state of the parser.
 
3737
** The second argument is the major token number.  The third is
 
3738
** the minor token.  The fourth optional argument is whatever the
 
3739
** user wants (and specified in the grammar) and is available for
 
3740
** use by the action routines.
 
3741
**
 
3742
** Inputs:
 
3743
** <ul>
 
3744
** <li> A pointer to the parser (an opaque structure.)
 
3745
** <li> The major token number.
 
3746
** <li> The minor token number.
 
3747
** <li> An option argument of a grammar-specified type.
 
3748
** </ul>
 
3749
**
 
3750
** Outputs:
 
3751
** None.
 
3752
*/
 
3753
void Parse(
 
3754
  void *yyp,                   /* The parser */
 
3755
  int yymajor,                 /* The major token code number */
 
3756
  ParseTOKENTYPE yyminor       /* The value for the token */
 
3757
  ParseARG_PDECL               /* Optional %extra_argument parameter */
 
3758
){
 
3759
  YYMINORTYPE yyminorunion;
 
3760
  int yyact;            /* The parser action. */
 
3761
  int yyendofinput;     /* True if we are at the end of input */
 
3762
#ifdef YYERRORSYMBOL
 
3763
  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
 
3764
#endif
 
3765
  yyParser *yypParser;  /* The parser */
 
3766
 
 
3767
  /* (re)initialize the parser, if necessary */
 
3768
  yypParser = (yyParser*)yyp;
 
3769
  if( yypParser->yyidx<0 ){
 
3770
#if YYSTACKDEPTH<=0
 
3771
    if( yypParser->yystksz <=0 ){
 
3772
      /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
 
3773
      yyminorunion = yyzerominor;
 
3774
      yyStackOverflow(yypParser, &yyminorunion);
 
3775
      return;
 
3776
    }
 
3777
#endif
 
3778
    yypParser->yyidx = 0;
 
3779
    yypParser->yyerrcnt = -1;
 
3780
    yypParser->yystack[0].stateno = 0;
 
3781
    yypParser->yystack[0].major = 0;
 
3782
  }
 
3783
  yyminorunion.yy0 = yyminor;
 
3784
  yyendofinput = (yymajor==0);
 
3785
  ParseARG_STORE;
 
3786
 
 
3787
#ifndef NDEBUG
 
3788
  if( yyTraceFILE ){
 
3789
    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
 
3790
  }
 
3791
#endif
 
3792
 
 
3793
  do{
 
3794
    yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
 
3795
    if( yyact<YYNSTATE ){
 
3796
      assert( !yyendofinput );  /* Impossible to shift the $ token */
 
3797
      yy_shift(yypParser,yyact,yymajor,&yyminorunion);
 
3798
      yypParser->yyerrcnt--;
 
3799
      yymajor = YYNOCODE;
 
3800
    }else if( yyact < YYNSTATE + YYNRULE ){
 
3801
      yy_reduce(yypParser,yyact-YYNSTATE);
 
3802
    }else{
 
3803
      assert( yyact == YY_ERROR_ACTION );
 
3804
#ifdef YYERRORSYMBOL
 
3805
      int yymx;
 
3806
#endif
 
3807
#ifndef NDEBUG
 
3808
      if( yyTraceFILE ){
 
3809
        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
 
3810
      }
 
3811
#endif
 
3812
#ifdef YYERRORSYMBOL
 
3813
      /* A syntax error has occurred.
 
3814
      ** The response to an error depends upon whether or not the
 
3815
      ** grammar defines an error token "ERROR".  
 
3816
      **
 
3817
      ** This is what we do if the grammar does define ERROR:
 
3818
      **
 
3819
      **  * Call the %syntax_error function.
 
3820
      **
 
3821
      **  * Begin popping the stack until we enter a state where
 
3822
      **    it is legal to shift the error symbol, then shift
 
3823
      **    the error symbol.
 
3824
      **
 
3825
      **  * Set the error count to three.
 
3826
      **
 
3827
      **  * Begin accepting and shifting new tokens.  No new error
 
3828
      **    processing will occur until three tokens have been
 
3829
      **    shifted successfully.
 
3830
      **
 
3831
      */
 
3832
      if( yypParser->yyerrcnt<0 ){
 
3833
        yy_syntax_error(yypParser,yymajor,yyminorunion);
 
3834
      }
 
3835
      yymx = yypParser->yystack[yypParser->yyidx].major;
 
3836
      if( yymx==YYERRORSYMBOL || yyerrorhit ){
 
3837
#ifndef NDEBUG
 
3838
        if( yyTraceFILE ){
 
3839
          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
 
3840
             yyTracePrompt,yyTokenName[yymajor]);
 
3841
        }
 
3842
#endif
 
3843
        yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
 
3844
        yymajor = YYNOCODE;
 
3845
      }else{
 
3846
         while(
 
3847
          yypParser->yyidx >= 0 &&
 
3848
          yymx != YYERRORSYMBOL &&
 
3849
          (yyact = yy_find_reduce_action(
 
3850
                        yypParser->yystack[yypParser->yyidx].stateno,
 
3851
                        YYERRORSYMBOL)) >= YYNSTATE
 
3852
        ){
 
3853
          yy_pop_parser_stack(yypParser);
 
3854
        }
 
3855
        if( yypParser->yyidx < 0 || yymajor==0 ){
 
3856
          yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
 
3857
          yy_parse_failed(yypParser);
 
3858
          yymajor = YYNOCODE;
 
3859
        }else if( yymx!=YYERRORSYMBOL ){
 
3860
          YYMINORTYPE u2;
 
3861
          u2.YYERRSYMDT = 0;
 
3862
          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
 
3863
        }
 
3864
      }
 
3865
      yypParser->yyerrcnt = 3;
 
3866
      yyerrorhit = 1;
 
3867
#elif defined(YYNOERRORRECOVERY)
 
3868
      /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
 
3869
      ** do any kind of error recovery.  Instead, simply invoke the syntax
 
3870
      ** error routine and continue going as if nothing had happened.
 
3871
      **
 
3872
      ** Applications can set this macro (for example inside %include) if
 
3873
      ** they intend to abandon the parse upon the first syntax error seen.
 
3874
      */
 
3875
      yy_syntax_error(yypParser,yymajor,yyminorunion);
 
3876
      yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
 
3877
      yymajor = YYNOCODE;
 
3878
      
 
3879
#else  /* YYERRORSYMBOL is not defined */
 
3880
      /* This is what we do if the grammar does not define ERROR:
 
3881
      **
 
3882
      **  * Report an error message, and throw away the input token.
 
3883
      **
 
3884
      **  * If the input token is $, then fail the parse.
 
3885
      **
 
3886
      ** As before, subsequent error messages are suppressed until
 
3887
      ** three input tokens have been successfully shifted.
 
3888
      */
 
3889
      if( yypParser->yyerrcnt<=0 ){
 
3890
        yy_syntax_error(yypParser,yymajor,yyminorunion);
 
3891
      }
 
3892
      yypParser->yyerrcnt = 3;
 
3893
      yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
 
3894
      if( yyendofinput ){
 
3895
        yy_parse_failed(yypParser);
 
3896
      }
 
3897
      yymajor = YYNOCODE;
 
3898
#endif
 
3899
    }
 
3900
  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
 
3901
  return;
 
3902
}
 
3903
 
 
3904
 
 
3905
/*
 
3906
 GML_LEMON_END - LEMON generated code ends here 
 
3907
*/
 
3908
 
 
3909
 
 
3910
 
 
3911
 
 
3912
 
 
3913
 
 
3914
 
 
3915
 
 
3916
 
 
3917
 
 
3918
 
 
3919
 
 
3920
 
 
3921
 
 
3922
 
 
3923
 
 
3924
 
 
3925
/*
 
3926
** CAVEAT: there is an incompatibility between LEMON and FLEX
 
3927
** this macro resolves the issue
 
3928
*/
 
3929
#undef yy_accept
 
3930
#define yy_accept       yy_gml_flex_accept
 
3931
 
 
3932
 
 
3933
 
 
3934
/*
 
3935
 GML_FLEX_START - FLEX generated code starts here 
 
3936
*/
 
3937
 
 
3938
#line 3 "lex.Gml.c"
 
3939
 
 
3940
#define  YY_INT_ALIGNED short int
 
3941
 
 
3942
/* A lexical scanner generated by flex */
 
3943
 
 
3944
#define yy_create_buffer Gml_create_buffer
 
3945
#define yy_delete_buffer Gml_delete_buffer
 
3946
#define yy_flex_debug Gml_flex_debug
 
3947
#define yy_init_buffer Gml_init_buffer
 
3948
#define yy_flush_buffer Gml_flush_buffer
 
3949
#define yy_load_buffer_state Gml_load_buffer_state
 
3950
#define yy_switch_to_buffer Gml_switch_to_buffer
 
3951
#define yyin Gmlin
 
3952
#define yyleng Gmlleng
 
3953
#define yylex Gmllex
 
3954
#define yylineno Gmllineno
 
3955
#define yyout Gmlout
 
3956
#define yyrestart Gmlrestart
 
3957
#define yytext Gmltext
 
3958
#define yywrap Gmlwrap
 
3959
#define yyalloc Gmlalloc
 
3960
#define yyrealloc Gmlrealloc
 
3961
#define yyfree Gmlfree
 
3962
 
 
3963
#define FLEX_SCANNER
 
3964
#define YY_FLEX_MAJOR_VERSION 2
 
3965
#define YY_FLEX_MINOR_VERSION 5
 
3966
#define YY_FLEX_SUBMINOR_VERSION 35
 
3967
#if YY_FLEX_SUBMINOR_VERSION > 0
 
3968
#define FLEX_BETA
 
3969
#endif
 
3970
 
 
3971
/* First, we deal with  platform-specific or compiler-specific issues. */
 
3972
 
 
3973
/* begin standard C headers. */
 
3974
#include <stdio.h>
 
3975
#include <string.h>
 
3976
#include <errno.h>
 
3977
#include <stdlib.h>
 
3978
 
 
3979
/* end standard C headers. */
 
3980
 
 
3981
/* flex integer type definitions */
 
3982
 
 
3983
#ifndef FLEXINT_H
 
3984
#define FLEXINT_H
 
3985
 
 
3986
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
3987
 
 
3988
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 
3989
 
 
3990
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
 
3991
 * if you want the limit (max/min) macros for int types. 
 
3992
 */
 
3993
#ifndef __STDC_LIMIT_MACROS
 
3994
#define __STDC_LIMIT_MACROS 1
 
3995
#endif
 
3996
 
 
3997
#include <inttypes.h>
 
3998
typedef int8_t flex_int8_t;
 
3999
typedef uint8_t flex_uint8_t;
 
4000
typedef int16_t flex_int16_t;
 
4001
typedef uint16_t flex_uint16_t;
 
4002
typedef int32_t flex_int32_t;
 
4003
typedef uint32_t flex_uint32_t;
 
4004
#else
 
4005
typedef signed char flex_int8_t;
 
4006
typedef short int flex_int16_t;
 
4007
typedef int flex_int32_t;
 
4008
typedef unsigned char flex_uint8_t; 
 
4009
typedef unsigned short int flex_uint16_t;
 
4010
typedef unsigned int flex_uint32_t;
 
4011
 
 
4012
/* Limits of integral types. */
 
4013
#ifndef INT8_MIN
 
4014
#define INT8_MIN               (-128)
 
4015
#endif
 
4016
#ifndef INT16_MIN
 
4017
#define INT16_MIN              (-32767-1)
 
4018
#endif
 
4019
#ifndef INT32_MIN
 
4020
#define INT32_MIN              (-2147483647-1)
 
4021
#endif
 
4022
#ifndef INT8_MAX
 
4023
#define INT8_MAX               (127)
 
4024
#endif
 
4025
#ifndef INT16_MAX
 
4026
#define INT16_MAX              (32767)
 
4027
#endif
 
4028
#ifndef INT32_MAX
 
4029
#define INT32_MAX              (2147483647)
 
4030
#endif
 
4031
#ifndef UINT8_MAX
 
4032
#define UINT8_MAX              (255U)
 
4033
#endif
 
4034
#ifndef UINT16_MAX
 
4035
#define UINT16_MAX             (65535U)
 
4036
#endif
 
4037
#ifndef UINT32_MAX
 
4038
#define UINT32_MAX             (4294967295U)
 
4039
#endif
 
4040
 
 
4041
#endif /* ! C99 */
 
4042
 
 
4043
#endif /* ! FLEXINT_H */
 
4044
 
 
4045
#ifdef __cplusplus
 
4046
 
 
4047
/* The "const" storage-class-modifier is valid. */
 
4048
#define YY_USE_CONST
 
4049
 
 
4050
#else   /* ! __cplusplus */
 
4051
 
 
4052
/* C99 requires __STDC__ to be defined as 1. */
 
4053
#if defined (__STDC__)
 
4054
 
 
4055
#define YY_USE_CONST
 
4056
 
 
4057
#endif  /* defined (__STDC__) */
 
4058
#endif  /* ! __cplusplus */
 
4059
 
 
4060
#ifdef YY_USE_CONST
 
4061
#define yyconst const
 
4062
#else
 
4063
#define yyconst
 
4064
#endif
 
4065
 
 
4066
/* Returned upon end-of-file. */
 
4067
#define YY_NULL 0
 
4068
 
 
4069
/* Promotes a possibly negative, possibly signed char to an unsigned
 
4070
 * integer for use as an array index.  If the signed char is negative,
 
4071
 * we want to instead treat it as an 8-bit unsigned char, hence the
 
4072
 * double cast.
 
4073
 */
 
4074
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
 
4075
 
 
4076
/* Enter a start condition.  This macro really ought to take a parameter,
 
4077
 * but we do it the disgusting crufty way forced on us by the ()-less
 
4078
 * definition of BEGIN.
 
4079
 */
 
4080
#define BEGIN (yy_start) = 1 + 2 *
 
4081
 
 
4082
/* Translate the current start state into a value that can be later handed
 
4083
 * to BEGIN to return to the state.  The YYSTATE alias is for lex
 
4084
 * compatibility.
 
4085
 */
 
4086
#define YY_START (((yy_start) - 1) / 2)
 
4087
#define YYSTATE YY_START
 
4088
 
 
4089
/* Action number for EOF rule of a given start state. */
 
4090
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
 
4091
 
 
4092
/* Special action meaning "start processing a new file". */
 
4093
#define YY_NEW_FILE Gmlrestart(Gmlin  )
 
4094
 
 
4095
#define YY_END_OF_BUFFER_CHAR 0
 
4096
 
 
4097
/* Size of default input buffer. */
 
4098
#ifndef YY_BUF_SIZE
 
4099
#ifdef __ia64__
 
4100
/* On IA-64, the buffer size is 16k, not 8k.
 
4101
 * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
 
4102
 * Ditto for the __ia64__ case accordingly.
 
4103
 */
 
4104
#define YY_BUF_SIZE 32768
 
4105
#else
 
4106
#define YY_BUF_SIZE 16384
 
4107
#endif /* __ia64__ */
 
4108
#endif
 
4109
 
 
4110
/* The state buf must be large enough to hold one state per character in the main buffer.
 
4111
 */
 
4112
#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
 
4113
 
 
4114
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
 
4115
#define YY_TYPEDEF_YY_BUFFER_STATE
 
4116
typedef struct yy_buffer_state *YY_BUFFER_STATE;
 
4117
#endif
 
4118
 
 
4119
extern int Gmlleng;
 
4120
 
 
4121
extern FILE *Gmlin, *Gmlout;
 
4122
 
 
4123
#define EOB_ACT_CONTINUE_SCAN 0
 
4124
#define EOB_ACT_END_OF_FILE 1
 
4125
#define EOB_ACT_LAST_MATCH 2
 
4126
 
 
4127
    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
 
4128
     *       access to the local variable yy_act. Since yyless() is a macro, it would break
 
4129
     *       existing scanners that call yyless() from OUTSIDE Gmllex. 
 
4130
     *       One obvious solution it to make yy_act a global. I tried that, and saw
 
4131
     *       a 5% performance hit in a non-Gmllineno scanner, because yy_act is
 
4132
     *       normally declared as a register variable-- so it is not worth it.
 
4133
     */
 
4134
    #define  YY_LESS_LINENO(n) \
 
4135
            do { \
 
4136
                int yyl;\
 
4137
                for ( yyl = n; yyl < Gmlleng; ++yyl )\
 
4138
                    if ( Gmltext[yyl] == '\n' )\
 
4139
                        --Gmllineno;\
 
4140
            }while(0)
 
4141
    
 
4142
/* Return all but the first "n" matched characters back to the input stream. */
 
4143
#define yyless(n) \
 
4144
        do \
 
4145
                { \
 
4146
                /* Undo effects of setting up Gmltext. */ \
 
4147
        int yyless_macro_arg = (n); \
 
4148
        YY_LESS_LINENO(yyless_macro_arg);\
 
4149
                *yy_cp = (yy_hold_char); \
 
4150
                YY_RESTORE_YY_MORE_OFFSET \
 
4151
                (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
 
4152
                YY_DO_BEFORE_ACTION; /* set up Gmltext again */ \
 
4153
                } \
 
4154
        while ( 0 )
 
4155
 
 
4156
#define unput(c) yyunput( c, (yytext_ptr)  )
 
4157
 
 
4158
#ifndef YY_TYPEDEF_YY_SIZE_T
 
4159
#define YY_TYPEDEF_YY_SIZE_T
 
4160
typedef size_t yy_size_t;
 
4161
#endif
 
4162
 
 
4163
#ifndef YY_STRUCT_YY_BUFFER_STATE
 
4164
#define YY_STRUCT_YY_BUFFER_STATE
 
4165
struct yy_buffer_state
 
4166
        {
 
4167
        FILE *yy_input_file;
 
4168
 
 
4169
        char *yy_ch_buf;                /* input buffer */
 
4170
        char *yy_buf_pos;               /* current position in input buffer */
 
4171
 
 
4172
        /* Size of input buffer in bytes, not including room for EOB
 
4173
         * characters.
 
4174
         */
 
4175
        yy_size_t yy_buf_size;
 
4176
 
 
4177
        /* Number of characters read into yy_ch_buf, not including EOB
 
4178
         * characters.
 
4179
         */
 
4180
        int yy_n_chars;
 
4181
 
 
4182
        /* Whether we "own" the buffer - i.e., we know we created it,
 
4183
         * and can realloc() it to grow it, and should free() it to
 
4184
         * delete it.
 
4185
         */
 
4186
        int yy_is_our_buffer;
 
4187
 
 
4188
        /* Whether this is an "interactive" input source; if so, and
 
4189
         * if we're using stdio for input, then we want to use getc()
 
4190
         * instead of fread(), to make sure we stop fetching input after
 
4191
         * each newline.
 
4192
         */
 
4193
        int yy_is_interactive;
 
4194
 
 
4195
        /* Whether we're considered to be at the beginning of a line.
 
4196
         * If so, '^' rules will be active on the next match, otherwise
 
4197
         * not.
 
4198
         */
 
4199
        int yy_at_bol;
 
4200
 
 
4201
    int yy_bs_lineno; /**< The line count. */
 
4202
    int yy_bs_column; /**< The column count. */
 
4203
    
 
4204
        /* Whether to try to fill the input buffer when we reach the
 
4205
         * end of it.
 
4206
         */
 
4207
        int yy_fill_buffer;
 
4208
 
 
4209
        int yy_buffer_status;
 
4210
 
 
4211
#define YY_BUFFER_NEW 0
 
4212
#define YY_BUFFER_NORMAL 1
 
4213
        /* When an EOF's been seen but there's still some text to process
 
4214
         * then we mark the buffer as YY_EOF_PENDING, to indicate that we
 
4215
         * shouldn't try reading from the input source any more.  We might
 
4216
         * still have a bunch of tokens to match, though, because of
 
4217
         * possible backing-up.
 
4218
         *
 
4219
         * When we actually see the EOF, we change the status to "new"
 
4220
         * (via Gmlrestart()), so that the user can continue scanning by
 
4221
         * just pointing Gmlin at a new input file.
 
4222
         */
 
4223
#define YY_BUFFER_EOF_PENDING 2
 
4224
 
 
4225
        };
 
4226
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
 
4227
 
 
4228
/* Stack of input buffers. */
 
4229
static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
 
4230
static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
 
4231
static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
 
4232
 
 
4233
/* We provide macros for accessing buffer states in case in the
 
4234
 * future we want to put the buffer states in a more general
 
4235
 * "scanner state".
 
4236
 *
 
4237
 * Returns the top of the stack, or NULL.
 
4238
 */
 
4239
#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
 
4240
                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
 
4241
                          : NULL)
 
4242
 
 
4243
/* Same as previous macro, but useful when we know that the buffer stack is not
 
4244
 * NULL or when we need an lvalue. For internal use only.
 
4245
 */
 
4246
#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
 
4247
 
 
4248
/* yy_hold_char holds the character lost when Gmltext is formed. */
 
4249
static char yy_hold_char;
 
4250
static int yy_n_chars;          /* number of characters read into yy_ch_buf */
 
4251
int Gmlleng;
 
4252
 
 
4253
/* Points to current character in buffer. */
 
4254
static char *yy_c_buf_p = (char *) 0;
 
4255
static int yy_init = 0;         /* whether we need to initialize */
 
4256
static int yy_start = 0;        /* start state number */
 
4257
 
 
4258
/* Flag which is used to allow Gmlwrap()'s to do buffer switches
 
4259
 * instead of setting up a fresh Gmlin.  A bit of a hack ...
 
4260
 */
 
4261
static int yy_did_buffer_switch_on_eof;
 
4262
 
 
4263
void Gmlrestart (FILE *input_file  );
 
4264
void Gml_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
 
4265
YY_BUFFER_STATE Gml_create_buffer (FILE *file,int size  );
 
4266
void Gml_delete_buffer (YY_BUFFER_STATE b  );
 
4267
void Gml_flush_buffer (YY_BUFFER_STATE b  );
 
4268
void Gmlpush_buffer_state (YY_BUFFER_STATE new_buffer  );
 
4269
void Gmlpop_buffer_state (void );
 
4270
 
 
4271
static void Gmlensure_buffer_stack (void );
 
4272
static void Gml_load_buffer_state (void );
 
4273
static void Gml_init_buffer (YY_BUFFER_STATE b,FILE *file  );
 
4274
 
 
4275
#define YY_FLUSH_BUFFER Gml_flush_buffer(YY_CURRENT_BUFFER )
 
4276
 
 
4277
YY_BUFFER_STATE Gml_scan_buffer (char *base,yy_size_t size  );
 
4278
YY_BUFFER_STATE Gml_scan_string (yyconst char *yy_str  );
 
4279
YY_BUFFER_STATE Gml_scan_bytes (yyconst char *bytes,int len  );
 
4280
 
 
4281
void *Gmlalloc (yy_size_t  );
 
4282
void *Gmlrealloc (void *,yy_size_t  );
 
4283
void Gmlfree (void *  );
 
4284
 
 
4285
#define yy_new_buffer Gml_create_buffer
 
4286
 
 
4287
#define yy_set_interactive(is_interactive) \
 
4288
        { \
 
4289
        if ( ! YY_CURRENT_BUFFER ){ \
 
4290
        Gmlensure_buffer_stack (); \
 
4291
                YY_CURRENT_BUFFER_LVALUE =    \
 
4292
            Gml_create_buffer(Gmlin,YY_BUF_SIZE ); \
 
4293
        } \
 
4294
        YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
 
4295
        }
 
4296
 
 
4297
#define yy_set_bol(at_bol) \
 
4298
        { \
 
4299
        if ( ! YY_CURRENT_BUFFER ){\
 
4300
        Gmlensure_buffer_stack (); \
 
4301
                YY_CURRENT_BUFFER_LVALUE =    \
 
4302
            Gml_create_buffer(Gmlin,YY_BUF_SIZE ); \
 
4303
        } \
 
4304
        YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
 
4305
        }
 
4306
 
 
4307
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
 
4308
 
 
4309
/* Begin user sect3 */
 
4310
 
 
4311
typedef unsigned char YY_CHAR;
 
4312
 
 
4313
FILE *Gmlin = (FILE *) 0, *Gmlout = (FILE *) 0;
 
4314
 
 
4315
typedef int yy_state_type;
 
4316
 
 
4317
#define YY_FLEX_LEX_COMPAT
 
4318
extern int Gmllineno;
 
4319
 
 
4320
int Gmllineno = 1;
 
4321
 
 
4322
extern char Gmltext[];
 
4323
 
 
4324
static yy_state_type yy_get_previous_state (void );
 
4325
static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
 
4326
static int yy_get_next_buffer (void );
 
4327
static void yy_fatal_error (yyconst char msg[]  );
 
4328
 
 
4329
/* Done after the current pattern has been matched and before the
 
4330
 * corresponding action - sets up Gmltext.
 
4331
 */
 
4332
#define YY_DO_BEFORE_ACTION \
 
4333
        (yytext_ptr) = yy_bp; \
 
4334
        Gmlleng = (size_t) (yy_cp - yy_bp); \
 
4335
        (yy_hold_char) = *yy_cp; \
 
4336
        *yy_cp = '\0'; \
 
4337
        if ( Gmlleng + (yy_more_offset) >= YYLMAX ) \
 
4338
                YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
 
4339
        yy_flex_strncpy( &Gmltext[(yy_more_offset)], (yytext_ptr), Gmlleng + 1 ); \
 
4340
        Gmlleng += (yy_more_offset); \
 
4341
        (yy_prev_more_offset) = (yy_more_offset); \
 
4342
        (yy_more_offset) = 0; \
 
4343
        (yy_c_buf_p) = yy_cp;
 
4344
 
 
4345
#define YY_NUM_RULES 11
 
4346
#define YY_END_OF_BUFFER 12
 
4347
/* This struct is not used in this scanner,
 
4348
   but its presence is necessary. */
 
4349
struct yy_trans_info
 
4350
        {
 
4351
        flex_int32_t yy_verify;
 
4352
        flex_int32_t yy_nxt;
 
4353
        };
 
4354
static yyconst flex_int16_t yy_acclist[34] =
 
4355
    {   0,
 
4356
        5,    5,   12,   10,   11,    8,   10,   11,    9,   11,
 
4357
       10,   11,    5,   10,   11,    1,   10,   11,    3,   10,
 
4358
       11,    2,   10,   11,    4,   10,   11,    7,   10,   11,
 
4359
        6,    5,    7
 
4360
    } ;
 
4361
 
 
4362
static yyconst flex_int16_t yy_accept[20] =
 
4363
    {   0,
 
4364
        1,    2,    3,    4,    6,    9,   11,   13,   16,   19,
 
4365
       22,   25,   28,   31,   31,   32,   33,   34,   34
 
4366
    } ;
 
4367
 
 
4368
static yyconst flex_int32_t yy_ec[256] =
 
4369
    {   0,
 
4370
        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
 
4371
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4372
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4373
        1,    2,    1,    4,    1,    1,    1,    1,    1,    1,
 
4374
        1,    1,    5,    5,    5,    5,    6,    7,    7,    7,
 
4375
        7,    7,    7,    7,    7,    7,    7,    8,    1,    9,
 
4376
       10,   11,    1,    1,   12,   12,   12,   12,   12,   12,
 
4377
       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
 
4378
       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
 
4379
        1,    1,    1,    1,   12,    1,   12,   12,   12,   12,
 
4380
 
 
4381
       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
 
4382
       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
 
4383
       12,   12,    1,    1,    1,    1,    1,    1,    1,    1,
 
4384
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4385
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4386
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4387
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4388
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4389
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4390
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4391
 
 
4392
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4393
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4394
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4395
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4396
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4397
        1,    1,    1,    1,    1
 
4398
    } ;
 
4399
 
 
4400
static yyconst flex_int32_t yy_meta[13] =
 
4401
    {   0,
 
4402
        1,    1,    1,    1,    2,    1,    3,    4,    5,    1,
 
4403
        5,    4
 
4404
    } ;
 
4405
 
 
4406
static yyconst flex_int16_t yy_base[22] =
 
4407
    {   0,
 
4408
        0,    0,   23,   24,   24,   24,   18,    0,   24,   24,
 
4409
       24,   24,    0,   17,   24,    0,    0,   24,   12,   15,
 
4410
       16
 
4411
    } ;
 
4412
 
 
4413
static yyconst flex_int16_t yy_def[22] =
 
4414
    {   0,
 
4415
       18,    1,   18,   18,   18,   18,   19,   20,   18,   18,
 
4416
       18,   18,   21,   19,   18,   20,   21,    0,   18,   18,
 
4417
       18
 
4418
    } ;
 
4419
 
 
4420
static yyconst flex_int16_t yy_nxt[37] =
 
4421
    {   0,
 
4422
        4,    5,    6,    7,    8,    9,    8,    4,   10,   11,
 
4423
       12,   13,   14,   14,   14,   14,   16,   16,   17,   17,
 
4424
       15,   15,   18,    3,   18,   18,   18,   18,   18,   18,
 
4425
       18,   18,   18,   18,   18,   18
 
4426
    } ;
 
4427
 
 
4428
static yyconst flex_int16_t yy_chk[37] =
 
4429
    {   0,
 
4430
        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
4431
        1,    1,   19,   19,   19,   19,   20,   20,   21,   21,
 
4432
       14,    7,    3,   18,   18,   18,   18,   18,   18,   18,
 
4433
       18,   18,   18,   18,   18,   18
 
4434
    } ;
 
4435
 
 
4436
/* Table of booleans, true if rule could match eol. */
 
4437
static yyconst flex_int32_t yy_rule_can_match_eol[12] =
 
4438
    {   0,
 
4439
0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,     };
 
4440
 
 
4441
extern int Gml_flex_debug;
 
4442
int Gml_flex_debug = 0;
 
4443
 
 
4444
static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
 
4445
static char *yy_full_match;
 
4446
static int yy_lp;
 
4447
#define REJECT \
 
4448
{ \
 
4449
*yy_cp = (yy_hold_char); /* undo effects of setting up Gmltext */ \
 
4450
yy_cp = (yy_full_match); /* restore poss. backed-over text */ \
 
4451
++(yy_lp); \
 
4452
goto find_rule; \
 
4453
}
 
4454
 
 
4455
static int yy_more_offset = 0;
 
4456
static int yy_prev_more_offset = 0;
 
4457
#define yymore() ((yy_more_offset) = yy_flex_strlen( Gmltext ))
 
4458
#define YY_NEED_STRLEN
 
4459
#define YY_MORE_ADJ 0
 
4460
#define YY_RESTORE_YY_MORE_OFFSET \
 
4461
        { \
 
4462
        (yy_more_offset) = (yy_prev_more_offset); \
 
4463
        Gmlleng -= (yy_more_offset); \
 
4464
        }
 
4465
#ifndef YYLMAX
 
4466
#define YYLMAX 8192
 
4467
#endif
 
4468
 
 
4469
char Gmltext[YYLMAX];
 
4470
char *yytext_ptr;
 
4471
#line 1 "gmlLexer.l"
 
4472
/* 
 
4473
 gmlLexer.l -- GML parser - FLEX config
 
4474
  
 
4475
 version 2.4, 2011 June 3
 
4476
 
 
4477
 Author: Sandro Furieri a.furieri@lqt.it
 
4478
 
 
4479
 ------------------------------------------------------------------------------
 
4480
 
 
4481
 Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4482
 
 
4483
 The contents of this file are subject to the Mozilla Public License Version
 
4484
 1.1 (the "License"); you may not use this file except in compliance with
 
4485
 the License. You may obtain a copy of the License at
 
4486
 http://www.mozilla.org/MPL/
 
4487
 
 
4488
Software distributed under the License is distributed on an "AS IS" basis,
 
4489
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
4490
for the specific language governing rights and limitations under the
 
4491
License.
 
4492
 
 
4493
The Original Code is the SpatiaLite library
 
4494
 
 
4495
The Initial Developer of the Original Code is Alessandro Furieri
 
4496
 
 
4497
Portions created by the Initial Developer are Copyright (C) 2011
 
4498
the Initial Developer. All Rights Reserved.
 
4499
 
 
4500
Alternatively, the contents of this file may be used under the terms of
 
4501
either the GNU General Public License Version 2 or later (the "GPL"), or
 
4502
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
4503
in which case the provisions of the GPL or the LGPL are applicable instead
 
4504
of those above. If you wish to allow use of your version of this file only
 
4505
under the terms of either the GPL or the LGPL, and not to allow others to
 
4506
use your version of this file under the terms of the MPL, indicate your
 
4507
decision by deleting the provisions above and replace them with the notice
 
4508
and other provisions required by the GPL or the LGPL. If you do not delete
 
4509
the provisions above, a recipient may use your version of this file under
 
4510
the terms of any one of the MPL, the GPL or the LGPL.
 
4511
 
 
4512
*/
 
4513
#line 46 "gmlLexer.l"
 
4514
 
 
4515
/* For debugging purposes */
 
4516
int gml_line = 1, gml_col = 1;
 
4517
 
 
4518
/**
 
4519
*  The main string-token matcher.
 
4520
*  The lower case part is probably not needed.  We should really be converting 
 
4521
*  The string to all uppercase/lowercase to make it case iNsEnSiTiVe.
 
4522
*  What Flex will do is, For the input string, beginning from the front, Flex
 
4523
*  will try to match with any of the defined tokens from below.  Flex will 
 
4524
*  then match the string of longest length.  Suppose the string is: POINTM,
 
4525
*  Flex would match both POINT and POINTM, but since POINTM is the longer
 
4526
*  of the two tokens, FLEX will match POINTM.
 
4527
*/
 
4528
#line 593 "lex.Gml.c"
 
4529
 
 
4530
#define INITIAL 0
 
4531
 
 
4532
#ifndef YY_NO_UNISTD_H
 
4533
/* Special case for "unistd.h", since it is non-ANSI. We include it way
 
4534
 * down here because we want the user's section 1 to have been scanned first.
 
4535
 * The user has a chance to override it with an option.
 
4536
 */
 
4537
#include <unistd.h>
 
4538
#endif
 
4539
 
 
4540
#ifndef YY_EXTRA_TYPE
 
4541
#define YY_EXTRA_TYPE void *
 
4542
#endif
 
4543
 
 
4544
static int yy_init_globals (void );
 
4545
 
 
4546
/* Accessor methods to globals.
 
4547
   These are made visible to non-reentrant scanners for convenience. */
 
4548
 
 
4549
int Gmllex_destroy (void );
 
4550
 
 
4551
int Gmlget_debug (void );
 
4552
 
 
4553
void Gmlset_debug (int debug_flag  );
 
4554
 
 
4555
YY_EXTRA_TYPE Gmlget_extra (void );
 
4556
 
 
4557
void Gmlset_extra (YY_EXTRA_TYPE user_defined  );
 
4558
 
 
4559
FILE *Gmlget_in (void );
 
4560
 
 
4561
void Gmlset_in  (FILE * in_str  );
 
4562
 
 
4563
FILE *Gmlget_out (void );
 
4564
 
 
4565
void Gmlset_out  (FILE * out_str  );
 
4566
 
 
4567
int Gmlget_leng (void );
 
4568
 
 
4569
char *Gmlget_text (void );
 
4570
 
 
4571
int Gmlget_lineno (void );
 
4572
 
 
4573
void Gmlset_lineno (int line_number  );
 
4574
 
 
4575
/* Macros after this point can all be overridden by user definitions in
 
4576
 * section 1.
 
4577
 */
 
4578
 
 
4579
#ifndef YY_SKIP_YYWRAP
 
4580
#ifdef __cplusplus
 
4581
extern "C" int Gmlwrap (void );
 
4582
#else
 
4583
extern int Gmlwrap (void );
 
4584
#endif
 
4585
#endif
 
4586
 
 
4587
    static void yyunput (int c,char *buf_ptr  );
 
4588
    
 
4589
#ifndef yytext_ptr
 
4590
static void yy_flex_strncpy (char *,yyconst char *,int );
 
4591
#endif
 
4592
 
 
4593
#ifdef YY_NEED_STRLEN
 
4594
static int yy_flex_strlen (yyconst char * );
 
4595
#endif
 
4596
 
 
4597
#ifndef YY_NO_INPUT
 
4598
 
 
4599
#ifdef __cplusplus
 
4600
static int yyinput (void );
 
4601
#else
 
4602
static int input (void );
 
4603
#endif
 
4604
 
 
4605
#endif
 
4606
 
 
4607
/* Amount of stuff to slurp up with each read. */
 
4608
#ifndef YY_READ_BUF_SIZE
 
4609
#ifdef __ia64__
 
4610
/* On IA-64, the buffer size is 16k, not 8k */
 
4611
#define YY_READ_BUF_SIZE 16384
 
4612
#else
 
4613
#define YY_READ_BUF_SIZE 8192
 
4614
#endif /* __ia64__ */
 
4615
#endif
 
4616
 
 
4617
/* Copy whatever the last rule matched to the standard output. */
 
4618
#ifndef ECHO
 
4619
/* This used to be an fputs(), but since the string might contain NUL's,
 
4620
 * we now use fwrite().
 
4621
 */
 
4622
#define ECHO do { if (fwrite( Gmltext, Gmlleng, 1, Gmlout )) {} } while (0)
 
4623
#endif
 
4624
 
 
4625
/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
 
4626
 * is returned in "result".
 
4627
 */
 
4628
#ifndef YY_INPUT
 
4629
#define YY_INPUT(buf,result,max_size) \
 
4630
        if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 
4631
                { \
 
4632
                int c = '*'; \
 
4633
                size_t n; \
 
4634
                for ( n = 0; n < max_size && \
 
4635
                             (c = getc( Gmlin )) != EOF && c != '\n'; ++n ) \
 
4636
                        buf[n] = (char) c; \
 
4637
                if ( c == '\n' ) \
 
4638
                        buf[n++] = (char) c; \
 
4639
                if ( c == EOF && ferror( Gmlin ) ) \
 
4640
                        YY_FATAL_ERROR( "input in flex scanner failed" ); \
 
4641
                result = n; \
 
4642
                } \
 
4643
        else \
 
4644
                { \
 
4645
                errno=0; \
 
4646
                while ( (result = fread(buf, 1, max_size, Gmlin))==0 && ferror(Gmlin)) \
 
4647
                        { \
 
4648
                        if( errno != EINTR) \
 
4649
                                { \
 
4650
                                YY_FATAL_ERROR( "input in flex scanner failed" ); \
 
4651
                                break; \
 
4652
                                } \
 
4653
                        errno=0; \
 
4654
                        clearerr(Gmlin); \
 
4655
                        } \
 
4656
                }\
 
4657
\
 
4658
 
 
4659
#endif
 
4660
 
 
4661
/* No semi-colon after return; correct usage is to write "yyterminate();" -
 
4662
 * we don't want an extra ';' after the "return" because that will cause
 
4663
 * some compilers to complain about unreachable statements.
 
4664
 */
 
4665
#ifndef yyterminate
 
4666
#define yyterminate() return YY_NULL
 
4667
#endif
 
4668
 
 
4669
/* Number of entries by which start-condition stack grows. */
 
4670
#ifndef YY_START_STACK_INCR
 
4671
#define YY_START_STACK_INCR 25
 
4672
#endif
 
4673
 
 
4674
/* Report a fatal error. */
 
4675
#ifndef YY_FATAL_ERROR
 
4676
#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
 
4677
#endif
 
4678
 
 
4679
/* end tables serialization structures and prototypes */
 
4680
 
 
4681
/* Default declaration of generated scanner - a define so the user can
 
4682
 * easily add parameters.
 
4683
 */
 
4684
#ifndef YY_DECL
 
4685
#define YY_DECL_IS_OURS 1
 
4686
 
 
4687
extern int Gmllex (void);
 
4688
 
 
4689
#define YY_DECL int Gmllex (void)
 
4690
#endif /* !YY_DECL */
 
4691
 
 
4692
/* Code executed at the beginning of each rule, after Gmltext and Gmlleng
 
4693
 * have been set up.
 
4694
 */
 
4695
#ifndef YY_USER_ACTION
 
4696
#define YY_USER_ACTION
 
4697
#endif
 
4698
 
 
4699
/* Code executed at the end of each rule. */
 
4700
#ifndef YY_BREAK
 
4701
#define YY_BREAK break;
 
4702
#endif
 
4703
 
 
4704
#define YY_RULE_SETUP \
 
4705
        YY_USER_ACTION
 
4706
 
 
4707
/** The main scanner function which does all the work.
 
4708
 */
 
4709
YY_DECL
 
4710
{
 
4711
        register yy_state_type yy_current_state;
 
4712
        register char *yy_cp, *yy_bp;
 
4713
        register int yy_act;
 
4714
    
 
4715
#line 62 "gmlLexer.l"
 
4716
 
 
4717
#line 782 "lex.Gml.c"
 
4718
 
 
4719
        if ( !(yy_init) )
 
4720
                {
 
4721
                (yy_init) = 1;
 
4722
 
 
4723
#ifdef YY_USER_INIT
 
4724
                YY_USER_INIT;
 
4725
#endif
 
4726
 
 
4727
        /* Create the reject buffer large enough to save one state per allowed character. */
 
4728
        if ( ! (yy_state_buf) )
 
4729
            (yy_state_buf) = (yy_state_type *)Gmlalloc(YY_STATE_BUF_SIZE  );
 
4730
            if ( ! (yy_state_buf) )
 
4731
                YY_FATAL_ERROR( "out of dynamic memory in Gmllex()" );
 
4732
 
 
4733
                if ( ! (yy_start) )
 
4734
                        (yy_start) = 1; /* first start state */
 
4735
 
 
4736
                if ( ! Gmlin )
 
4737
                        Gmlin = stdin;
 
4738
 
 
4739
                if ( ! Gmlout )
 
4740
                        Gmlout = stdout;
 
4741
 
 
4742
                if ( ! YY_CURRENT_BUFFER ) {
 
4743
                        Gmlensure_buffer_stack ();
 
4744
                        YY_CURRENT_BUFFER_LVALUE =
 
4745
                                Gml_create_buffer(Gmlin,YY_BUF_SIZE );
 
4746
                }
 
4747
 
 
4748
                Gml_load_buffer_state( );
 
4749
                }
 
4750
 
 
4751
        while ( 1 )             /* loops until end-of-file is reached */
 
4752
                {
 
4753
                yy_cp = (yy_c_buf_p);
 
4754
 
 
4755
                /* Support of Gmltext. */
 
4756
                *yy_cp = (yy_hold_char);
 
4757
 
 
4758
                /* yy_bp points to the position in yy_ch_buf of the start of
 
4759
                 * the current run.
 
4760
                 */
 
4761
                yy_bp = yy_cp;
 
4762
 
 
4763
                yy_current_state = (yy_start);
 
4764
 
 
4765
                (yy_state_ptr) = (yy_state_buf);
 
4766
                *(yy_state_ptr)++ = yy_current_state;
 
4767
 
 
4768
yy_match:
 
4769
                do
 
4770
                        {
 
4771
                        register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
 
4772
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 
4773
                                {
 
4774
                                yy_current_state = (int) yy_def[yy_current_state];
 
4775
                                if ( yy_current_state >= 19 )
 
4776
                                        yy_c = yy_meta[(unsigned int) yy_c];
 
4777
                                }
 
4778
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 
4779
                        *(yy_state_ptr)++ = yy_current_state;
 
4780
                        ++yy_cp;
 
4781
                        }
 
4782
                while ( yy_base[yy_current_state] != 24 );
 
4783
 
 
4784
yy_find_action:
 
4785
                yy_current_state = *--(yy_state_ptr);
 
4786
                (yy_lp) = yy_accept[yy_current_state];
 
4787
find_rule: /* we branch to this label when backing up */
 
4788
                for ( ; ; ) /* until we find what rule we matched */
 
4789
                        {
 
4790
                        if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] )
 
4791
                                {
 
4792
                                yy_act = yy_acclist[(yy_lp)];
 
4793
                                        {
 
4794
                                        (yy_full_match) = yy_cp;
 
4795
                                        break;
 
4796
                                        }
 
4797
                                }
 
4798
                        --yy_cp;
 
4799
                        yy_current_state = *--(yy_state_ptr);
 
4800
                        (yy_lp) = yy_accept[yy_current_state];
 
4801
                        }
 
4802
 
 
4803
                YY_DO_BEFORE_ACTION;
 
4804
 
 
4805
                if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
 
4806
                        {
 
4807
                        int yyl;
 
4808
                        for ( yyl = (yy_prev_more_offset); yyl < Gmlleng; ++yyl )
 
4809
                                if ( Gmltext[yyl] == '\n' )
 
4810
                                           
 
4811
    Gmllineno++;
 
4812
;
 
4813
                        }
 
4814
 
 
4815
do_action:      /* This label is used only to access EOF actions. */
 
4816
 
 
4817
                switch ( yy_act )
 
4818
        { /* beginning of action switch */
 
4819
case 1:
 
4820
YY_RULE_SETUP
 
4821
#line 63 "gmlLexer.l"
 
4822
{ gml_freeString(&(GmlLval.pval)); return GML_END; }
 
4823
        YY_BREAK
 
4824
case 2:
 
4825
YY_RULE_SETUP
 
4826
#line 64 "gmlLexer.l"
 
4827
{ gml_freeString(&(GmlLval.pval)); return GML_EQ; }
 
4828
        YY_BREAK
 
4829
case 3:
 
4830
YY_RULE_SETUP
 
4831
#line 65 "gmlLexer.l"
 
4832
{ gml_freeString(&(GmlLval.pval)); return GML_OPEN; }
 
4833
        YY_BREAK
 
4834
case 4:
 
4835
YY_RULE_SETUP
 
4836
#line 66 "gmlLexer.l"
 
4837
{ gml_freeString(&(GmlLval.pval)); return GML_CLOSE; }
 
4838
        YY_BREAK
 
4839
case 5:
 
4840
YY_RULE_SETUP
 
4841
#line 67 "gmlLexer.l"
 
4842
{ gml_saveString(&(GmlLval.pval), Gmltext); return GML_COORD; }
 
4843
        YY_BREAK
 
4844
case 6:
 
4845
/* rule 6 can match eol */
 
4846
YY_RULE_SETUP
 
4847
#line 68 "gmlLexer.l"
 
4848
{ gml_saveString(&(GmlLval.pval), Gmltext); return GML_VALUE; }
 
4849
        YY_BREAK
 
4850
case 7:
 
4851
YY_RULE_SETUP
 
4852
#line 69 "gmlLexer.l"
 
4853
{ gml_saveString(&(GmlLval.pval), Gmltext); return GML_KEYWORD; }
 
4854
        YY_BREAK
 
4855
case 8:
 
4856
YY_RULE_SETUP
 
4857
#line 71 "gmlLexer.l"
 
4858
{ gml_freeString(&(GmlLval.pval)); gml_col += (int) strlen(Gmltext); }               /* ignore but count white space */
 
4859
        YY_BREAK
 
4860
case 9:
 
4861
/* rule 9 can match eol */
 
4862
YY_RULE_SETUP
 
4863
#line 73 "gmlLexer.l"
 
4864
{ gml_freeString(&(GmlLval.pval)); gml_col = 0; ++gml_line; }
 
4865
        YY_BREAK
 
4866
case 10:
 
4867
YY_RULE_SETUP
 
4868
#line 75 "gmlLexer.l"
 
4869
{ gml_freeString(&(GmlLval.pval)); gml_col += (int) strlen(Gmltext); return -1; }
 
4870
        YY_BREAK
 
4871
case 11:
 
4872
YY_RULE_SETUP
 
4873
#line 76 "gmlLexer.l"
 
4874
ECHO;
 
4875
        YY_BREAK
 
4876
#line 941 "lex.Gml.c"
 
4877
                        case YY_STATE_EOF(INITIAL):
 
4878
                                yyterminate();
 
4879
 
 
4880
        case YY_END_OF_BUFFER:
 
4881
                {
 
4882
                /* Amount of text matched not including the EOB char. */
 
4883
                int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
 
4884
 
 
4885
                /* Undo the effects of YY_DO_BEFORE_ACTION. */
 
4886
                *yy_cp = (yy_hold_char);
 
4887
                YY_RESTORE_YY_MORE_OFFSET
 
4888
 
 
4889
                if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
 
4890
                        {
 
4891
                        /* We're scanning a new file or input source.  It's
 
4892
                         * possible that this happened because the user
 
4893
                         * just pointed Gmlin at a new source and called
 
4894
                         * Gmllex().  If so, then we have to assure
 
4895
                         * consistency between YY_CURRENT_BUFFER and our
 
4896
                         * globals.  Here is the right place to do so, because
 
4897
                         * this is the first action (other than possibly a
 
4898
                         * back-up) that will match for the new input source.
 
4899
                         */
 
4900
                        (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
 
4901
                        YY_CURRENT_BUFFER_LVALUE->yy_input_file = Gmlin;
 
4902
                        YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
 
4903
                        }
 
4904
 
 
4905
                /* Note that here we test for yy_c_buf_p "<=" to the position
 
4906
                 * of the first EOB in the buffer, since yy_c_buf_p will
 
4907
                 * already have been incremented past the NUL character
 
4908
                 * (since all states make transitions on EOB to the
 
4909
                 * end-of-buffer state).  Contrast this with the test
 
4910
                 * in input().
 
4911
                 */
 
4912
                if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
 
4913
                        { /* This was really a NUL. */
 
4914
                        yy_state_type yy_next_state;
 
4915
 
 
4916
                        (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
 
4917
 
 
4918
                        yy_current_state = yy_get_previous_state(  );
 
4919
 
 
4920
                        /* Okay, we're now positioned to make the NUL
 
4921
                         * transition.  We couldn't have
 
4922
                         * yy_get_previous_state() go ahead and do it
 
4923
                         * for us because it doesn't know how to deal
 
4924
                         * with the possibility of jamming (and we don't
 
4925
                         * want to build jamming into it because then it
 
4926
                         * will run more slowly).
 
4927
                         */
 
4928
 
 
4929
                        yy_next_state = yy_try_NUL_trans( yy_current_state );
 
4930
 
 
4931
                        yy_bp = (yytext_ptr) + YY_MORE_ADJ;
 
4932
 
 
4933
                        if ( yy_next_state )
 
4934
                                {
 
4935
                                /* Consume the NUL. */
 
4936
                                yy_cp = ++(yy_c_buf_p);
 
4937
                                yy_current_state = yy_next_state;
 
4938
                                goto yy_match;
 
4939
                                }
 
4940
 
 
4941
                        else
 
4942
                                {
 
4943
                                yy_cp = (yy_c_buf_p);
 
4944
                                goto yy_find_action;
 
4945
                                }
 
4946
                        }
 
4947
 
 
4948
                else switch ( yy_get_next_buffer(  ) )
 
4949
                        {
 
4950
                        case EOB_ACT_END_OF_FILE:
 
4951
                                {
 
4952
                                (yy_did_buffer_switch_on_eof) = 0;
 
4953
 
 
4954
                                if ( Gmlwrap( ) )
 
4955
                                        {
 
4956
                                        /* Note: because we've taken care in
 
4957
                                         * yy_get_next_buffer() to have set up
 
4958
                                         * Gmltext, we can now set up
 
4959
                                         * yy_c_buf_p so that if some total
 
4960
                                         * hoser (like flex itself) wants to
 
4961
                                         * call the scanner after we return the
 
4962
                                         * YY_NULL, it'll still work - another
 
4963
                                         * YY_NULL will get returned.
 
4964
                                         */
 
4965
                                        (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
 
4966
 
 
4967
                                        yy_act = YY_STATE_EOF(YY_START);
 
4968
                                        goto do_action;
 
4969
                                        }
 
4970
 
 
4971
                                else
 
4972
                                        {
 
4973
                                        if ( ! (yy_did_buffer_switch_on_eof) )
 
4974
                                                YY_NEW_FILE;
 
4975
                                        }
 
4976
                                break;
 
4977
                                }
 
4978
 
 
4979
                        case EOB_ACT_CONTINUE_SCAN:
 
4980
                                (yy_c_buf_p) =
 
4981
                                        (yytext_ptr) + yy_amount_of_matched_text;
 
4982
 
 
4983
                                yy_current_state = yy_get_previous_state(  );
 
4984
 
 
4985
                                yy_cp = (yy_c_buf_p);
 
4986
                                yy_bp = (yytext_ptr) + YY_MORE_ADJ;
 
4987
                                goto yy_match;
 
4988
 
 
4989
                        case EOB_ACT_LAST_MATCH:
 
4990
                                (yy_c_buf_p) =
 
4991
                                &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
 
4992
 
 
4993
                                yy_current_state = yy_get_previous_state(  );
 
4994
 
 
4995
                                yy_cp = (yy_c_buf_p);
 
4996
                                yy_bp = (yytext_ptr) + YY_MORE_ADJ;
 
4997
                                goto yy_find_action;
 
4998
                        }
 
4999
                break;
 
5000
                }
 
5001
 
 
5002
        default:
 
5003
                YY_FATAL_ERROR(
 
5004
                        "fatal flex scanner internal error--no action found" );
 
5005
        } /* end of action switch */
 
5006
                } /* end of scanning one token */
 
5007
} /* end of Gmllex */
 
5008
 
 
5009
/* yy_get_next_buffer - try to read in a new buffer
 
5010
 *
 
5011
 * Returns a code representing an action:
 
5012
 *      EOB_ACT_LAST_MATCH -
 
5013
 *      EOB_ACT_CONTINUE_SCAN - continue scanning from current position
 
5014
 *      EOB_ACT_END_OF_FILE - end of file
 
5015
 */
 
5016
static int yy_get_next_buffer (void)
 
5017
{
 
5018
        register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
 
5019
        register char *source = (yytext_ptr);
 
5020
        register int number_to_move, i;
 
5021
        int ret_val;
 
5022
 
 
5023
        if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
 
5024
                YY_FATAL_ERROR(
 
5025
                "fatal flex scanner internal error--end of buffer missed" );
 
5026
 
 
5027
        if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
 
5028
                { /* Don't try to fill the buffer, so this is an EOF. */
 
5029
                if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
 
5030
                        {
 
5031
                        /* We matched a single character, the EOB, so
 
5032
                         * treat this as a final EOF.
 
5033
                         */
 
5034
                        return EOB_ACT_END_OF_FILE;
 
5035
                        }
 
5036
 
 
5037
                else
 
5038
                        {
 
5039
                        /* We matched some text prior to the EOB, first
 
5040
                         * process it.
 
5041
                         */
 
5042
                        return EOB_ACT_LAST_MATCH;
 
5043
                        }
 
5044
                }
 
5045
 
 
5046
        /* Try to read more data. */
 
5047
 
 
5048
        /* First move last chars to start of buffer. */
 
5049
        number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
 
5050
 
 
5051
        for ( i = 0; i < number_to_move; ++i )
 
5052
                *(dest++) = *(source++);
 
5053
 
 
5054
        if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
 
5055
                /* don't do the read, it's not guaranteed to return an EOF,
 
5056
                 * just force an EOF
 
5057
                 */
 
5058
                YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
 
5059
 
 
5060
        else
 
5061
                {
 
5062
                        int num_to_read =
 
5063
                        YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
5064
 
 
5065
                while ( num_to_read <= 0 )
 
5066
                        { /* Not enough room in the buffer - grow it. */
 
5067
 
 
5068
                        YY_FATAL_ERROR(
 
5069
"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
 
5070
 
 
5071
                        }
 
5072
 
 
5073
                if ( num_to_read > YY_READ_BUF_SIZE )
 
5074
                        num_to_read = YY_READ_BUF_SIZE;
 
5075
 
 
5076
                /* Read in more data. */
 
5077
                YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
 
5078
                        (yy_n_chars), (size_t) num_to_read );
 
5079
 
 
5080
                YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
 
5081
                }
 
5082
 
 
5083
        if ( (yy_n_chars) == 0 )
 
5084
                {
 
5085
                if ( number_to_move == YY_MORE_ADJ )
 
5086
                        {
 
5087
                        ret_val = EOB_ACT_END_OF_FILE;
 
5088
                        Gmlrestart(Gmlin  );
 
5089
                        }
 
5090
 
 
5091
                else
 
5092
                        {
 
5093
                        ret_val = EOB_ACT_LAST_MATCH;
 
5094
                        YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
 
5095
                                YY_BUFFER_EOF_PENDING;
 
5096
                        }
 
5097
                }
 
5098
 
 
5099
        else
 
5100
                ret_val = EOB_ACT_CONTINUE_SCAN;
 
5101
 
 
5102
        if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
 
5103
                /* Extend the array by 50%, plus the number we really need. */
 
5104
                yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
 
5105
                YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) Gmlrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
 
5106
                if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
 
5107
                        YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
 
5108
        }
 
5109
 
 
5110
        (yy_n_chars) += number_to_move;
 
5111
        YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
 
5112
        YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
 
5113
 
 
5114
        (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
 
5115
 
 
5116
        return ret_val;
 
5117
}
 
5118
 
 
5119
/* yy_get_previous_state - get the state just before the EOB char was reached */
 
5120
 
 
5121
    static yy_state_type yy_get_previous_state (void)
 
5122
{
 
5123
        register yy_state_type yy_current_state;
 
5124
        register char *yy_cp;
 
5125
    
 
5126
        yy_current_state = (yy_start);
 
5127
 
 
5128
        (yy_state_ptr) = (yy_state_buf);
 
5129
        *(yy_state_ptr)++ = yy_current_state;
 
5130
 
 
5131
        for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
 
5132
                {
 
5133
                register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
 
5134
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 
5135
                        {
 
5136
                        yy_current_state = (int) yy_def[yy_current_state];
 
5137
                        if ( yy_current_state >= 19 )
 
5138
                                yy_c = yy_meta[(unsigned int) yy_c];
 
5139
                        }
 
5140
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 
5141
                *(yy_state_ptr)++ = yy_current_state;
 
5142
                }
 
5143
 
 
5144
        return yy_current_state;
 
5145
}
 
5146
 
 
5147
/* yy_try_NUL_trans - try to make a transition on the NUL character
 
5148
 *
 
5149
 * synopsis
 
5150
 *      next_state = yy_try_NUL_trans( current_state );
 
5151
 */
 
5152
    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
 
5153
{
 
5154
        register int yy_is_jam;
 
5155
    
 
5156
        register YY_CHAR yy_c = 1;
 
5157
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 
5158
                {
 
5159
                yy_current_state = (int) yy_def[yy_current_state];
 
5160
                if ( yy_current_state >= 19 )
 
5161
                        yy_c = yy_meta[(unsigned int) yy_c];
 
5162
                }
 
5163
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 
5164
        yy_is_jam = (yy_current_state == 18);
 
5165
        if ( ! yy_is_jam )
 
5166
                *(yy_state_ptr)++ = yy_current_state;
 
5167
 
 
5168
        return yy_is_jam ? 0 : yy_current_state;
 
5169
}
 
5170
 
 
5171
    static void yyunput (int c, register char * yy_bp )
 
5172
{
 
5173
        register char *yy_cp;
 
5174
    
 
5175
    yy_cp = (yy_c_buf_p);
 
5176
 
 
5177
        /* undo effects of setting up Gmltext */
 
5178
        *yy_cp = (yy_hold_char);
 
5179
 
 
5180
        if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
 
5181
                { /* need to shift things up to make room */
 
5182
                /* +2 for EOB chars. */
 
5183
                register int number_to_move = (yy_n_chars) + 2;
 
5184
                register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
 
5185
                                        YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
 
5186
                register char *source =
 
5187
                                &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
 
5188
 
 
5189
                while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
 
5190
                        *--dest = *--source;
 
5191
 
 
5192
                yy_cp += (int) (dest - source);
 
5193
                yy_bp += (int) (dest - source);
 
5194
                YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
 
5195
                        (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
 
5196
 
 
5197
                if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
 
5198
                        YY_FATAL_ERROR( "flex scanner push-back overflow" );
 
5199
                }
 
5200
 
 
5201
        *--yy_cp = (char) c;
 
5202
 
 
5203
    if ( c == '\n' ){
 
5204
        --Gmllineno;
 
5205
    }
 
5206
 
 
5207
        (yytext_ptr) = yy_bp;
 
5208
        (yy_hold_char) = *yy_cp;
 
5209
        (yy_c_buf_p) = yy_cp;
 
5210
}
 
5211
 
 
5212
#ifndef YY_NO_INPUT
 
5213
#ifdef __cplusplus
 
5214
    static int yyinput (void)
 
5215
#else
 
5216
    static int input  (void)
 
5217
#endif
 
5218
 
 
5219
{
 
5220
        int c;
 
5221
    
 
5222
        *(yy_c_buf_p) = (yy_hold_char);
 
5223
 
 
5224
        if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
 
5225
                {
 
5226
                /* yy_c_buf_p now points to the character we want to return.
 
5227
                 * If this occurs *before* the EOB characters, then it's a
 
5228
                 * valid NUL; if not, then we've hit the end of the buffer.
 
5229
                 */
 
5230
                if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
 
5231
                        /* This was really a NUL. */
 
5232
                        *(yy_c_buf_p) = '\0';
 
5233
 
 
5234
                else
 
5235
                        { /* need more input */
 
5236
                        int offset = (yy_c_buf_p) - (yytext_ptr);
 
5237
                        ++(yy_c_buf_p);
 
5238
 
 
5239
                        switch ( yy_get_next_buffer(  ) )
 
5240
                                {
 
5241
                                case EOB_ACT_LAST_MATCH:
 
5242
                                        /* This happens because yy_g_n_b()
 
5243
                                         * sees that we've accumulated a
 
5244
                                         * token and flags that we need to
 
5245
                                         * try matching the token before
 
5246
                                         * proceeding.  But for input(),
 
5247
                                         * there's no matching to consider.
 
5248
                                         * So convert the EOB_ACT_LAST_MATCH
 
5249
                                         * to EOB_ACT_END_OF_FILE.
 
5250
                                         */
 
5251
 
 
5252
                                        /* Reset buffer status. */
 
5253
                                        Gmlrestart(Gmlin );
 
5254
 
 
5255
                                        /*FALLTHROUGH*/
 
5256
 
 
5257
                                case EOB_ACT_END_OF_FILE:
 
5258
                                        {
 
5259
                                        if ( Gmlwrap( ) )
 
5260
                                                return EOF;
 
5261
 
 
5262
                                        if ( ! (yy_did_buffer_switch_on_eof) )
 
5263
                                                YY_NEW_FILE;
 
5264
#ifdef __cplusplus
 
5265
                                        return yyinput();
 
5266
#else
 
5267
                                        return input();
 
5268
#endif
 
5269
                                        }
 
5270
 
 
5271
                                case EOB_ACT_CONTINUE_SCAN:
 
5272
                                        (yy_c_buf_p) = (yytext_ptr) + offset;
 
5273
                                        break;
 
5274
                                }
 
5275
                        }
 
5276
                }
 
5277
 
 
5278
        c = *(unsigned char *) (yy_c_buf_p);    /* cast for 8-bit char's */
 
5279
        *(yy_c_buf_p) = '\0';   /* preserve Gmltext */
 
5280
        (yy_hold_char) = *++(yy_c_buf_p);
 
5281
 
 
5282
        if ( c == '\n' )
 
5283
                   
 
5284
    Gmllineno++;
 
5285
;
 
5286
 
 
5287
        return c;
 
5288
}
 
5289
#endif  /* ifndef YY_NO_INPUT */
 
5290
 
 
5291
/** Immediately switch to a different input stream.
 
5292
 * @param input_file A readable stream.
 
5293
 * 
 
5294
 * @note This function does not reset the start condition to @c INITIAL .
 
5295
 */
 
5296
    void Gmlrestart  (FILE * input_file )
 
5297
{
 
5298
    
 
5299
        if ( ! YY_CURRENT_BUFFER ){
 
5300
        Gmlensure_buffer_stack ();
 
5301
                YY_CURRENT_BUFFER_LVALUE =
 
5302
            Gml_create_buffer(Gmlin,YY_BUF_SIZE );
 
5303
        }
 
5304
 
 
5305
        Gml_init_buffer(YY_CURRENT_BUFFER,input_file );
 
5306
        Gml_load_buffer_state( );
 
5307
}
 
5308
 
 
5309
/** Switch to a different input buffer.
 
5310
 * @param new_buffer The new input buffer.
 
5311
 * 
 
5312
 */
 
5313
    void Gml_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
 
5314
{
 
5315
    
 
5316
        /* TODO. We should be able to replace this entire function body
 
5317
         * with
 
5318
         *              Gmlpop_buffer_state();
 
5319
         *              Gmlpush_buffer_state(new_buffer);
 
5320
     */
 
5321
        Gmlensure_buffer_stack ();
 
5322
        if ( YY_CURRENT_BUFFER == new_buffer )
 
5323
                return;
 
5324
 
 
5325
        if ( YY_CURRENT_BUFFER )
 
5326
                {
 
5327
                /* Flush out information for old buffer. */
 
5328
                *(yy_c_buf_p) = (yy_hold_char);
 
5329
                YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
 
5330
                YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
 
5331
                }
 
5332
 
 
5333
        YY_CURRENT_BUFFER_LVALUE = new_buffer;
 
5334
        Gml_load_buffer_state( );
 
5335
 
 
5336
        /* We don't actually know whether we did this switch during
 
5337
         * EOF (Gmlwrap()) processing, but the only time this flag
 
5338
         * is looked at is after Gmlwrap() is called, so it's safe
 
5339
         * to go ahead and always set it.
 
5340
         */
 
5341
        (yy_did_buffer_switch_on_eof) = 1;
 
5342
}
 
5343
 
 
5344
static void Gml_load_buffer_state  (void)
 
5345
{
 
5346
        (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
 
5347
        (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
 
5348
        Gmlin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
 
5349
        (yy_hold_char) = *(yy_c_buf_p);
 
5350
}
 
5351
 
 
5352
/** Allocate and initialize an input buffer state.
 
5353
 * @param file A readable stream.
 
5354
 * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
 
5355
 * 
 
5356
 * @return the allocated buffer state.
 
5357
 */
 
5358
    YY_BUFFER_STATE Gml_create_buffer  (FILE * file, int  size )
 
5359
{
 
5360
        YY_BUFFER_STATE b;
 
5361
    
 
5362
        b = (YY_BUFFER_STATE) Gmlalloc(sizeof( struct yy_buffer_state )  );
 
5363
        if ( ! b )
 
5364
                YY_FATAL_ERROR( "out of dynamic memory in Gml_create_buffer()" );
 
5365
 
 
5366
        b->yy_buf_size = size;
 
5367
 
 
5368
        /* yy_ch_buf has to be 2 characters longer than the size given because
 
5369
         * we need to put in 2 end-of-buffer characters.
 
5370
         */
 
5371
        b->yy_ch_buf = (char *) Gmlalloc(b->yy_buf_size + 2  );
 
5372
        if ( ! b->yy_ch_buf )
 
5373
                YY_FATAL_ERROR( "out of dynamic memory in Gml_create_buffer()" );
 
5374
 
 
5375
        b->yy_is_our_buffer = 1;
 
5376
 
 
5377
        Gml_init_buffer(b,file );
 
5378
 
 
5379
        return b;
 
5380
}
 
5381
 
 
5382
/** Destroy the buffer.
 
5383
 * @param b a buffer created with Gml_create_buffer()
 
5384
 * 
 
5385
 */
 
5386
    void Gml_delete_buffer (YY_BUFFER_STATE  b )
 
5387
{
 
5388
    
 
5389
        if ( ! b )
 
5390
                return;
 
5391
 
 
5392
        if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
 
5393
                YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
 
5394
 
 
5395
        if ( b->yy_is_our_buffer )
 
5396
                Gmlfree((void *) b->yy_ch_buf  );
 
5397
 
 
5398
        Gmlfree((void *) b  );
 
5399
}
 
5400
 
 
5401
#ifndef __cplusplus
 
5402
extern int isatty (int );
 
5403
#endif /* __cplusplus */
 
5404
    
 
5405
/* Initializes or reinitializes a buffer.
 
5406
 * This function is sometimes called more than once on the same buffer,
 
5407
 * such as during a Gmlrestart() or at EOF.
 
5408
 */
 
5409
    static void Gml_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
 
5410
 
 
5411
{
 
5412
        int oerrno = errno;
 
5413
    
 
5414
        Gml_flush_buffer(b );
 
5415
 
 
5416
        b->yy_input_file = file;
 
5417
        b->yy_fill_buffer = 1;
 
5418
 
 
5419
    /* If b is the current buffer, then Gml_init_buffer was _probably_
 
5420
     * called from Gmlrestart() or through yy_get_next_buffer.
 
5421
     * In that case, we don't want to reset the lineno or column.
 
5422
     */
 
5423
    if (b != YY_CURRENT_BUFFER){
 
5424
        b->yy_bs_lineno = 1;
 
5425
        b->yy_bs_column = 0;
 
5426
    }
 
5427
 
 
5428
        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
 
5429
    
 
5430
        errno = oerrno;
 
5431
}
 
5432
 
 
5433
/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
 
5434
 * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
 
5435
 * 
 
5436
 */
 
5437
    void Gml_flush_buffer (YY_BUFFER_STATE  b )
 
5438
{
 
5439
        if ( ! b )
 
5440
                return;
 
5441
 
 
5442
        b->yy_n_chars = 0;
 
5443
 
 
5444
        /* We always need two end-of-buffer characters.  The first causes
 
5445
         * a transition to the end-of-buffer state.  The second causes
 
5446
         * a jam in that state.
 
5447
         */
 
5448
        b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
 
5449
        b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
 
5450
 
 
5451
        b->yy_buf_pos = &b->yy_ch_buf[0];
 
5452
 
 
5453
        b->yy_at_bol = 1;
 
5454
        b->yy_buffer_status = YY_BUFFER_NEW;
 
5455
 
 
5456
        if ( b == YY_CURRENT_BUFFER )
 
5457
                Gml_load_buffer_state( );
 
5458
}
 
5459
 
 
5460
/** Pushes the new state onto the stack. The new state becomes
 
5461
 *  the current state. This function will allocate the stack
 
5462
 *  if necessary.
 
5463
 *  @param new_buffer The new state.
 
5464
 *  
 
5465
 */
 
5466
void Gmlpush_buffer_state (YY_BUFFER_STATE new_buffer )
 
5467
{
 
5468
        if (new_buffer == NULL)
 
5469
                return;
 
5470
 
 
5471
        Gmlensure_buffer_stack();
 
5472
 
 
5473
        /* This block is copied from Gml_switch_to_buffer. */
 
5474
        if ( YY_CURRENT_BUFFER )
 
5475
                {
 
5476
                /* Flush out information for old buffer. */
 
5477
                *(yy_c_buf_p) = (yy_hold_char);
 
5478
                YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
 
5479
                YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
 
5480
                }
 
5481
 
 
5482
        /* Only push if top exists. Otherwise, replace top. */
 
5483
        if (YY_CURRENT_BUFFER)
 
5484
                (yy_buffer_stack_top)++;
 
5485
        YY_CURRENT_BUFFER_LVALUE = new_buffer;
 
5486
 
 
5487
        /* copied from Gml_switch_to_buffer. */
 
5488
        Gml_load_buffer_state( );
 
5489
        (yy_did_buffer_switch_on_eof) = 1;
 
5490
}
 
5491
 
 
5492
/** Removes and deletes the top of the stack, if present.
 
5493
 *  The next element becomes the new top.
 
5494
 *  
 
5495
 */
 
5496
void Gmlpop_buffer_state (void)
 
5497
{
 
5498
        if (!YY_CURRENT_BUFFER)
 
5499
                return;
 
5500
 
 
5501
        Gml_delete_buffer(YY_CURRENT_BUFFER );
 
5502
        YY_CURRENT_BUFFER_LVALUE = NULL;
 
5503
        if ((yy_buffer_stack_top) > 0)
 
5504
                --(yy_buffer_stack_top);
 
5505
 
 
5506
        if (YY_CURRENT_BUFFER) {
 
5507
                Gml_load_buffer_state( );
 
5508
                (yy_did_buffer_switch_on_eof) = 1;
 
5509
        }
 
5510
}
 
5511
 
 
5512
/* Allocates the stack if it does not exist.
 
5513
 *  Guarantees space for at least one push.
 
5514
 */
 
5515
static void Gmlensure_buffer_stack (void)
 
5516
{
 
5517
        int num_to_alloc;
 
5518
    
 
5519
        if (!(yy_buffer_stack)) {
 
5520
 
 
5521
                /* First allocation is just for 2 elements, since we don't know if this
 
5522
                 * scanner will even need a stack. We use 2 instead of 1 to avoid an
 
5523
                 * immediate realloc on the next call.
 
5524
         */
 
5525
                num_to_alloc = 1;
 
5526
                (yy_buffer_stack) = (struct yy_buffer_state**)Gmlalloc
 
5527
                                                                (num_to_alloc * sizeof(struct yy_buffer_state*)
 
5528
                                                                );
 
5529
                if ( ! (yy_buffer_stack) )
 
5530
                        YY_FATAL_ERROR( "out of dynamic memory in Gmlensure_buffer_stack()" );
 
5531
                                                                  
 
5532
                memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
 
5533
                                
 
5534
                (yy_buffer_stack_max) = num_to_alloc;
 
5535
                (yy_buffer_stack_top) = 0;
 
5536
                return;
 
5537
        }
 
5538
 
 
5539
        if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
 
5540
 
 
5541
                /* Increase the buffer to prepare for a possible push. */
 
5542
                int grow_size = 8 /* arbitrary grow size */;
 
5543
 
 
5544
                num_to_alloc = (yy_buffer_stack_max) + grow_size;
 
5545
                (yy_buffer_stack) = (struct yy_buffer_state**)Gmlrealloc
 
5546
                                                                ((yy_buffer_stack),
 
5547
                                                                num_to_alloc * sizeof(struct yy_buffer_state*)
 
5548
                                                                );
 
5549
                if ( ! (yy_buffer_stack) )
 
5550
                        YY_FATAL_ERROR( "out of dynamic memory in Gmlensure_buffer_stack()" );
 
5551
 
 
5552
                /* zero only the new slots.*/
 
5553
                memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
 
5554
                (yy_buffer_stack_max) = num_to_alloc;
 
5555
        }
 
5556
}
 
5557
 
 
5558
/** Setup the input buffer state to scan directly from a user-specified character buffer.
 
5559
 * @param base the character buffer
 
5560
 * @param size the size in bytes of the character buffer
 
5561
 * 
 
5562
 * @return the newly allocated buffer state object. 
 
5563
 */
 
5564
YY_BUFFER_STATE Gml_scan_buffer  (char * base, yy_size_t  size )
 
5565
{
 
5566
        YY_BUFFER_STATE b;
 
5567
    
 
5568
        if ( size < 2 ||
 
5569
             base[size-2] != YY_END_OF_BUFFER_CHAR ||
 
5570
             base[size-1] != YY_END_OF_BUFFER_CHAR )
 
5571
                /* They forgot to leave room for the EOB's. */
 
5572
                return 0;
 
5573
 
 
5574
        b = (YY_BUFFER_STATE) Gmlalloc(sizeof( struct yy_buffer_state )  );
 
5575
        if ( ! b )
 
5576
                YY_FATAL_ERROR( "out of dynamic memory in Gml_scan_buffer()" );
 
5577
 
 
5578
        b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
 
5579
        b->yy_buf_pos = b->yy_ch_buf = base;
 
5580
        b->yy_is_our_buffer = 0;
 
5581
        b->yy_input_file = 0;
 
5582
        b->yy_n_chars = b->yy_buf_size;
 
5583
        b->yy_is_interactive = 0;
 
5584
        b->yy_at_bol = 1;
 
5585
        b->yy_fill_buffer = 0;
 
5586
        b->yy_buffer_status = YY_BUFFER_NEW;
 
5587
 
 
5588
        Gml_switch_to_buffer(b  );
 
5589
 
 
5590
        return b;
 
5591
}
 
5592
 
 
5593
/** Setup the input buffer state to scan a string. The next call to Gmllex() will
 
5594
 * scan from a @e copy of @a str.
 
5595
 * @param yystr a NUL-terminated string to scan
 
5596
 * 
 
5597
 * @return the newly allocated buffer state object.
 
5598
 * @note If you want to scan bytes that may contain NUL values, then use
 
5599
 *       Gml_scan_bytes() instead.
 
5600
 */
 
5601
YY_BUFFER_STATE Gml_scan_string (yyconst char * yystr )
 
5602
{
 
5603
    
 
5604
        return Gml_scan_bytes(yystr,strlen(yystr) );
 
5605
}
 
5606
 
 
5607
/** Setup the input buffer state to scan the given bytes. The next call to Gmllex() will
 
5608
 * scan from a @e copy of @a bytes.
 
5609
 * @param yybytes the byte buffer to scan
 
5610
 * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
 
5611
 * 
 
5612
 * @return the newly allocated buffer state object.
 
5613
 */
 
5614
YY_BUFFER_STATE Gml_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
 
5615
{
 
5616
        YY_BUFFER_STATE b;
 
5617
        char *buf;
 
5618
        yy_size_t n;
 
5619
        int i;
 
5620
    
 
5621
        /* Get memory for full buffer, including space for trailing EOB's. */
 
5622
        n = _yybytes_len + 2;
 
5623
        buf = (char *) Gmlalloc(n  );
 
5624
        if ( ! buf )
 
5625
                YY_FATAL_ERROR( "out of dynamic memory in Gml_scan_bytes()" );
 
5626
 
 
5627
        for ( i = 0; i < _yybytes_len; ++i )
 
5628
                buf[i] = yybytes[i];
 
5629
 
 
5630
        buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
 
5631
 
 
5632
        b = Gml_scan_buffer(buf,n );
 
5633
        if ( ! b )
 
5634
                YY_FATAL_ERROR( "bad buffer in Gml_scan_bytes()" );
 
5635
 
 
5636
        /* It's okay to grow etc. this buffer, and we should throw it
 
5637
         * away when we're done.
 
5638
         */
 
5639
        b->yy_is_our_buffer = 1;
 
5640
 
 
5641
        return b;
 
5642
}
 
5643
 
 
5644
#ifndef YY_EXIT_FAILURE
 
5645
#define YY_EXIT_FAILURE 2
 
5646
#endif
 
5647
 
 
5648
static void yy_fatal_error (yyconst char* msg )
 
5649
{
 
5650
        (void) fprintf( stderr, "%s\n", msg );
 
5651
        exit( YY_EXIT_FAILURE );
 
5652
}
 
5653
 
 
5654
/* Redefine yyless() so it works in section 3 code. */
 
5655
 
 
5656
#undef yyless
 
5657
#define yyless(n) \
 
5658
        do \
 
5659
                { \
 
5660
                /* Undo effects of setting up Gmltext. */ \
 
5661
        int yyless_macro_arg = (n); \
 
5662
        YY_LESS_LINENO(yyless_macro_arg);\
 
5663
                Gmltext[Gmlleng] = (yy_hold_char); \
 
5664
                (yy_c_buf_p) = Gmltext + yyless_macro_arg; \
 
5665
                (yy_hold_char) = *(yy_c_buf_p); \
 
5666
                *(yy_c_buf_p) = '\0'; \
 
5667
                Gmlleng = yyless_macro_arg; \
 
5668
                } \
 
5669
        while ( 0 )
 
5670
 
 
5671
/* Accessor  methods (get/set functions) to struct members. */
 
5672
 
 
5673
/** Get the current line number.
 
5674
 * 
 
5675
 */
 
5676
int Gmlget_lineno  (void)
 
5677
{
 
5678
        
 
5679
    return Gmllineno;
 
5680
}
 
5681
 
 
5682
/** Get the input stream.
 
5683
 * 
 
5684
 */
 
5685
FILE *Gmlget_in  (void)
 
5686
{
 
5687
        return Gmlin;
 
5688
}
 
5689
 
 
5690
/** Get the output stream.
 
5691
 * 
 
5692
 */
 
5693
FILE *Gmlget_out  (void)
 
5694
{
 
5695
        return Gmlout;
 
5696
}
 
5697
 
 
5698
/** Get the length of the current token.
 
5699
 * 
 
5700
 */
 
5701
int Gmlget_leng  (void)
 
5702
{
 
5703
        return Gmlleng;
 
5704
}
 
5705
 
 
5706
/** Get the current token.
 
5707
 * 
 
5708
 */
 
5709
 
 
5710
char *Gmlget_text  (void)
 
5711
{
 
5712
        return Gmltext;
 
5713
}
 
5714
 
 
5715
/** Set the current line number.
 
5716
 * @param line_number
 
5717
 * 
 
5718
 */
 
5719
void Gmlset_lineno (int  line_number )
 
5720
{
 
5721
    
 
5722
    Gmllineno = line_number;
 
5723
}
 
5724
 
 
5725
/** Set the input stream. This does not discard the current
 
5726
 * input buffer.
 
5727
 * @param in_str A readable stream.
 
5728
 * 
 
5729
 * @see Gml_switch_to_buffer
 
5730
 */
 
5731
void Gmlset_in (FILE *  in_str )
 
5732
{
 
5733
        Gmlin = in_str ;
 
5734
}
 
5735
 
 
5736
void Gmlset_out (FILE *  out_str )
 
5737
{
 
5738
        Gmlout = out_str ;
 
5739
}
 
5740
 
 
5741
int Gmlget_debug  (void)
 
5742
{
 
5743
        return Gml_flex_debug;
 
5744
}
 
5745
 
 
5746
void Gmlset_debug (int  bdebug )
 
5747
{
 
5748
        Gml_flex_debug = bdebug ;
 
5749
}
 
5750
 
 
5751
static int yy_init_globals (void)
 
5752
{
 
5753
        /* Initialization is the same as for the non-reentrant scanner.
 
5754
     * This function is called from Gmllex_destroy(), so don't allocate here.
 
5755
     */
 
5756
 
 
5757
    /* We do not touch Gmllineno unless the option is enabled. */
 
5758
    Gmllineno =  1;
 
5759
    
 
5760
    (yy_buffer_stack) = 0;
 
5761
    (yy_buffer_stack_top) = 0;
 
5762
    (yy_buffer_stack_max) = 0;
 
5763
    (yy_c_buf_p) = (char *) 0;
 
5764
    (yy_init) = 0;
 
5765
    (yy_start) = 0;
 
5766
 
 
5767
    (yy_state_buf) = 0;
 
5768
    (yy_state_ptr) = 0;
 
5769
    (yy_full_match) = 0;
 
5770
    (yy_lp) = 0;
 
5771
 
 
5772
/* Defined in main.c */
 
5773
#ifdef YY_STDINIT
 
5774
    Gmlin = stdin;
 
5775
    Gmlout = stdout;
 
5776
#else
 
5777
    Gmlin = (FILE *) 0;
 
5778
    Gmlout = (FILE *) 0;
 
5779
#endif
 
5780
 
 
5781
    /* For future reference: Set errno on error, since we are called by
 
5782
     * Gmllex_init()
 
5783
     */
 
5784
    return 0;
 
5785
}
 
5786
 
 
5787
/* Gmllex_destroy is for both reentrant and non-reentrant scanners. */
 
5788
int Gmllex_destroy  (void)
 
5789
{
 
5790
    
 
5791
    /* Pop the buffer stack, destroying each element. */
 
5792
        while(YY_CURRENT_BUFFER){
 
5793
                Gml_delete_buffer(YY_CURRENT_BUFFER  );
 
5794
                YY_CURRENT_BUFFER_LVALUE = NULL;
 
5795
                Gmlpop_buffer_state();
 
5796
        }
 
5797
 
 
5798
        /* Destroy the stack itself. */
 
5799
        Gmlfree((yy_buffer_stack) );
 
5800
        (yy_buffer_stack) = NULL;
 
5801
 
 
5802
    Gmlfree ( (yy_state_buf) );
 
5803
    (yy_state_buf)  = NULL;
 
5804
 
 
5805
    /* Reset the globals. This is important in a non-reentrant scanner so the next time
 
5806
     * Gmllex() is called, initialization will occur. */
 
5807
    yy_init_globals( );
 
5808
 
 
5809
    return 0;
 
5810
}
 
5811
 
 
5812
/*
 
5813
 * Internal utility routines.
 
5814
 */
 
5815
 
 
5816
#ifndef yytext_ptr
 
5817
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 
5818
{
 
5819
        register int i;
 
5820
        for ( i = 0; i < n; ++i )
 
5821
                s1[i] = s2[i];
 
5822
}
 
5823
#endif
 
5824
 
 
5825
#ifdef YY_NEED_STRLEN
 
5826
static int yy_flex_strlen (yyconst char * s )
 
5827
{
 
5828
        register int n;
 
5829
        for ( n = 0; s[n]; ++n )
 
5830
                ;
 
5831
 
 
5832
        return n;
 
5833
}
 
5834
#endif
 
5835
 
 
5836
void *Gmlalloc (yy_size_t  size )
 
5837
{
 
5838
        return (void *) malloc( size );
 
5839
}
 
5840
 
 
5841
void *Gmlrealloc  (void * ptr, yy_size_t  size )
 
5842
{
 
5843
        /* The cast to (char *) in the following accommodates both
 
5844
         * implementations that use char* generic pointers, and those
 
5845
         * that use void* generic pointers.  It works with the latter
 
5846
         * because both ANSI C and C++ allow castless assignment from
 
5847
         * any pointer type to void*, and deal with argument conversions
 
5848
         * as though doing an assignment.
 
5849
         */
 
5850
        return (void *) realloc( (char *) ptr, size );
 
5851
}
 
5852
 
 
5853
void Gmlfree (void * ptr )
 
5854
{
 
5855
        free( (char *) ptr );   /* see Gmlrealloc() for (char *) cast */
 
5856
}
 
5857
 
 
5858
#define YYTABLES_NAME "yytables"
 
5859
 
 
5860
#line 76 "gmlLexer.l"
 
5861
 
 
5862
 
 
5863
/**
 
5864
 * reset the line and column count
 
5865
 *
 
5866
 *
 
5867
 */
 
5868
void gml_reset_lexer(void)
 
5869
{
 
5870
 
 
5871
  gml_line = 1;
 
5872
  gml_col  = 1;
 
5873
 
 
5874
}
 
5875
 
 
5876
/**
 
5877
 * gmlError() is invoked when the lexer or the parser encounter
 
5878
 * an error. The error message is passed via *s
 
5879
 *
 
5880
 *
 
5881
 */
 
5882
void GmlError(char *s)
 
5883
{
 
5884
  printf("error: %s at line: %d col: %d\n",s,gml_line,gml_col);
 
5885
 
 
5886
}
 
5887
 
 
5888
int Gmlwrap(void)
 
5889
{
 
5890
  return 1;
 
5891
}
 
5892
 
 
5893
 
 
5894
/*
 
5895
 GML_FLEX_END - FLEX generated code ends here 
 
5896
*/
 
5897
 
 
5898
 
 
5899
 
 
5900
gaiaGeomCollPtr
 
5901
gaiaParseGml (const unsigned char *dirty_buffer, sqlite3 * sqlite_handle)
 
5902
{
 
5903
    void *pParser = ParseAlloc (malloc);
 
5904
    /* Linked-list of token values */
 
5905
    gmlFlexToken *tokens = malloc (sizeof (gmlFlexToken));
 
5906
    /* Pointer to the head of the list */
 
5907
    gmlFlexToken *head = tokens;
 
5908
    int yv;
 
5909
    gmlNodePtr result = NULL;
 
5910
    gaiaGeomCollPtr geom = NULL;
 
5911
 
 
5912
    GmlLval.pval = NULL;
 
5913
    tokens->value = NULL;
 
5914
    tokens->Next = NULL;
 
5915
    gml_parse_error = 0;
 
5916
    Gml_scan_string ((char *) dirty_buffer);
 
5917
 
 
5918
    /*
 
5919
       / Keep tokenizing until we reach the end
 
5920
       / yylex() will return the next matching Token for us.
 
5921
     */
 
5922
    while ((yv = yylex ()) != 0)
 
5923
      {
 
5924
          if (yv == -1)
 
5925
            {
 
5926
                gml_parse_error = 1;
 
5927
                break;
 
5928
            }
 
5929
          tokens->Next = malloc (sizeof (gmlFlexToken));
 
5930
          tokens->Next->Next = NULL;
 
5931
          /*
 
5932
             /GmlLval is a global variable from FLEX.
 
5933
             /GmlLval is defined in gmlLexglobal.h
 
5934
           */
 
5935
          gml_xferString (&(tokens->Next->value), GmlLval.pval);
 
5936
          /* Pass the token to the wkt parser created from lemon */
 
5937
          Parse (pParser, yv, &(tokens->Next->value), &result);
 
5938
          tokens = tokens->Next;
 
5939
      }
 
5940
    /* This denotes the end of a line as well as the end of the parser */
 
5941
    Parse (pParser, GML_NEWLINE, 0, &result);
 
5942
    ParseFree (pParser, free);
 
5943
    Gmllex_destroy ();
 
5944
 
 
5945
    /* Assigning the token as the end to avoid seg faults while cleaning */
 
5946
    tokens->Next = NULL;
 
5947
    gml_cleanup (head);
 
5948
    gml_freeString (&(GmlLval.pval));
 
5949
 
 
5950
    if (gml_parse_error)
 
5951
      {
 
5952
          if (result)
 
5953
              gml_freeTree (result);
 
5954
          return NULL;
 
5955
      }
 
5956
 
 
5957
    /* attempting to build a geometry from GML */
 
5958
    geom = gml_build_geometry (result, sqlite_handle);
 
5959
    gml_freeTree (result);
 
5960
    return geom;
 
5961
}
 
5962
 
 
5963
 
 
5964
/*
 
5965
** CAVEAT: we must now undefine any Lemon/Flex own macro
 
5966
*/
 
5967
#undef YYNOCODE
 
5968
#undef YYNSTATE
 
5969
#undef YYNRULE
 
5970
#undef YY_SHIFT_MAX
 
5971
#undef YY_SHIFT_USE_DFLT
 
5972
#undef YY_REDUCE_USE_DFLT
 
5973
#undef YY_REDUCE_MAX
 
5974
#undef YY_FLUSH_BUFFER
 
5975
#undef YY_DO_BEFORE_ACTION
 
5976
#undef YY_NUM_RULES
 
5977
#undef YY_END_OF_BUFFER
 
5978
#undef YY_END_FILE
 
5979
#undef YYACTIONTYPE
 
5980
#undef YY_SZ_ACTTAB
 
5981
#undef YY_NEW_FILE
 
5982
#undef BEGIN
 
5983
#undef YY_START
 
5984
#undef YY_CURRENT_BUFFER
 
5985
#undef YY_CURRENT_BUFFER_LVALUE
 
5986
#undef YY_STATE_BUF_SIZE
 
5987
#undef YY_DECL
 
5988
#undef YY_FATAL_ERROR
 
5989
#undef YYMINORTYPE
 
5990
#undef YY_CHAR
 
5991
#undef YYSTYPE
 
5992
#undef input
 
5993
#undef ParseAlloc
 
5994
#undef ParseFree
 
5995
#undef ParseStackPeak
 
5996
#undef Parse
 
5997
#undef yyalloc
 
5998
#undef yyfree
 
5999
#undef yyin
 
6000
#undef yyleng
 
6001
#undef yyless
 
6002
#undef yylex
 
6003
#undef yylineno
 
6004
#undef yyout
 
6005
#undef yyrealloc
 
6006
#undef yyrestart
 
6007
#undef yyStackEntry
 
6008
#undef yytext
 
6009
#undef yywrap
 
6010
#undef yyzerominor
 
6011
#undef yy_accept
 
6012
#undef yy_action
 
6013
#undef yy_base
 
6014
#undef yy_buffer_stack
 
6015
#undef yy_buffer_stack_max
 
6016
#undef yy_buffer_stack_top
 
6017
#undef yy_c_buf_p
 
6018
#undef yy_chk
 
6019
#undef yy_create_buffer
 
6020
#undef yy_def
 
6021
#undef yy_default
 
6022
#undef yy_delete_buffer
 
6023
#undef yy_destructor
 
6024
#undef yy_ec
 
6025
#undef yy_fatal_error
 
6026
#undef yy_find_reduce_action
 
6027
#undef yy_find_shift_action
 
6028
#undef yy_flex_debug
 
6029
#undef yy_flush_buffer
 
6030
#undef yy_get_next_buffer
 
6031
#undef yy_get_previous_state
 
6032
#undef yy_init
 
6033
#undef yy_init_buffer
 
6034
#undef yy_init_globals
 
6035
#undef yy_load_buffer
 
6036
#undef yy_load_buffer_state
 
6037
#undef yy_lookahead
 
6038
#undef yy_meta
 
6039
#undef yy_new_buffer
 
6040
#undef yy_nxt
 
6041
#undef yy_parse_failed
 
6042
#undef yy_pop_parser_stack
 
6043
#undef yy_reduce
 
6044
#undef yy_reduce_ofst
 
6045
#undef yy_set_bol
 
6046
#undef yy_set_interactive
 
6047
#undef yy_shift
 
6048
#undef yy_shift_ofst
 
6049
#undef yy_start
 
6050
#undef yy_state_type
 
6051
#undef yy_switch_to_buffer
 
6052
#undef yy_syntax_error
 
6053
#undef yy_trans_info
 
6054
#undef yy_try_NUL_trans
 
6055
#undef yyParser
 
6056
#undef yyStackEntry
 
6057
#undef yyStackOverflow
 
6058
#undef yyRuleInfo
 
6059
#undef yytext_ptr
 
6060
#undef yyunput
 
6061
#undef yyzerominor
 
6062
#undef ParseARG_SDECL
 
6063
#undef ParseARG_PDECL
 
6064
#undef ParseARG_FETCH
 
6065
#undef ParseARG_STORE
 
6066
#undef REJECT
 
6067
#undef yymore
 
6068
#undef YY_MORE_ADJ
 
6069
#undef YY_RESTORE_YY_MORE_OFFSET
 
6070
#undef YY_LESS_LINENO
 
6071
#undef yyTracePrompt
 
6072
#undef yyTraceFILE
 
6073
#undef yyTokenName
 
6074
#undef yyRuleName
 
6075
#undef ParseTrace