diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 208f724bca2ac9e2c67fde9d01fd6eba27b79368..943799a9f1069f283c75e7df156b28e9ba8da615 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -1592,7 +1592,7 @@ StringXNumber PrintOptions_Number[] = {
     "Try to minimize primitive splitting in BSP tree sorted PostScript/PDF output" },
   { F|O, "EpsCompress" , opt_print_eps_compress , 0. ,
     "Compress PostScript/PDF output using zlib" },
-  { F|O, "EpsLineWidthFactor" , opt_print_eps_line_width_factor , 0.5 ,
+  { F|O, "EpsLineWidthFactor" , opt_print_eps_line_width_factor , 1.0 ,
     "Width factor for lines in PostScript/PDF output" },
   { F|O, "EpsOcclusionCulling" , opt_print_eps_occlusion_culling , 1. ,
     "Cull occluded primitives (to reduce PostScript/PDF file size)" },
diff --git a/Geo/GModelIO_Geo.cpp b/Geo/GModelIO_Geo.cpp
index fa86f83f936dc9fd2eeee9a20d678cb7c624d6e8..48350bd9e0592dac1daf366e915ff6d29bcbb1fe 100644
--- a/Geo/GModelIO_Geo.cpp
+++ b/Geo/GModelIO_Geo.cpp
@@ -130,19 +130,28 @@ int GModel::importGEOInternals()
     for(int i = 0; i < List_Nbr(curves); i++){
       Curve *c;
       List_Read(curves, i, &c);
-      if(c->Num >= 0 && c->beg && c->end){
+      if(c->Num >= 0){
         GEdge *e = getEdgeByTag(c->Num);
-        if(!e){
+        if(!e && c->Typ == MSH_SEGM_COMPOUND){
+          std::vector<GEdge*> comp;
+          for(unsigned int j = 0; j < c->compound.size(); j++){
+            GEdge *ge = getEdgeByTag(c->compound[j]);
+            if(ge) comp.push_back(ge);
+          }
+          e = new GEdgeCompound(this, c->Num, comp);
+          add(e);
+        }
+        else if(!e && c->beg && c->end){
           e = new gmshEdge(this, c,
                            getVertexByTag(c->beg->Num),
                            getVertexByTag(c->end->Num));
-         add(e);
+          add(e);
         }
         else
           e->resetMeshAttributes();
         if(!c->Visible) e->setVisibility(0);
         if(c->Color.type) e->setColor(c->Color.mesh);
-        if(c->degenerated)e->setTooSmall(true);
+        if(c->degenerated) e->setTooSmall(true);
       }
     }
     List_Delete(curves);
@@ -153,7 +162,26 @@ int GModel::importGEOInternals()
       Surface *s;
       List_Read(surfaces, i, &s);
       GFace *f = getFaceByTag(s->Num);
-      if(!f){
+      if(!f && s->Typ == MSH_SURF_COMPOUND){
+        std::list<GFace*> comp;
+        for(unsigned int j = 0; j < s->compound.size(); j++){
+          GFace *gf = getFaceByTag(s->compound[j]);
+          if(gf) comp.push_back(gf);
+        }
+        std::list<GEdge*> b[4];
+        for(int j = 0; j < 4; j++){
+          for(int k = 0; k < s->compoundBoundary[j].size(); k++){
+            GEdge *ge = getEdgeByTag(s->compoundBoundary[j][k]);
+            if(ge) b[j].push_back(ge);
+          }
+        }
+        f = new GFaceCompound(this, std::abs(s->Num), comp,
+                              b[0], b[1], b[2], b[3], 0,
+                              s->Num > 0 ? GFaceCompound::HARMONIC :
+                              GFaceCompound::CONFORMAL);
+        add(f);
+      }
+      else if(!f){
         f = new gmshFace(this, s);
         add(f);
       }
@@ -170,7 +198,16 @@ int GModel::importGEOInternals()
       Volume *v;
       List_Read(volumes, i, &v);
       GRegion *r = getRegionByTag(v->Num);
-      if(!r){
+      if(!r && v->Typ == MSH_VOLUME_COMPOUND){
+        std::vector<GRegion*> comp;
+        for(unsigned int j = 0; j < v->compound.size(); j++){
+          GRegion *gr = getRegionByTag(v->compound[j]);
+          if(gr) comp.push_back(gr);
+        }
+        r = new GRegionCompound(this, v->Num, comp);
+        add(r);
+      }
+      else if(!r){
         r = new gmshRegion(this, v);
         add(r);
       }
@@ -184,81 +221,21 @@ int GModel::importGEOInternals()
   for(int i = 0; i < List_Nbr(_geo_internals->PhysicalGroups); i++){
     PhysicalGroup *p;
     List_Read(_geo_internals->PhysicalGroups, i, &p);
-    std::vector<GEdge*> e_compound;
-    std::list<GFace*> f_compound;
-    std::vector<GRegion*> r_compound;
     for(int j = 0; j < List_Nbr(p->Entities); j++){
       int num;
       List_Read(p->Entities, j, &num);
       GEntity *ge = 0;
       switch(p->Typ){
-      case MSH_PHYSICAL_POINT:
-        ge = getVertexByTag(abs(num));
-        break;
-      case MSH_PHYSICAL_LINE: 
-        ge = getEdgeByTag(abs(num));
-        e_compound.push_back(getEdgeByTag(abs(num)));
-        break; 
-     case MSH_PHYSICAL_SURFACE: 
-        ge = getFaceByTag(abs(num));
-        f_compound.push_back(getFaceByTag(abs(num))); 
-        break;
-      case MSH_PHYSICAL_VOLUME:  
-        ge = getRegionByTag(abs(num)); 
-        r_compound.push_back(getRegionByTag(abs(num))); 
-        break;
+      case MSH_PHYSICAL_POINT:   ge = getVertexByTag(abs(num)); break;
+      case MSH_PHYSICAL_LINE:    ge = getEdgeByTag(abs(num)); break; 
+      case MSH_PHYSICAL_SURFACE: ge = getFaceByTag(abs(num)); break;
+      case MSH_PHYSICAL_VOLUME:  ge = getRegionByTag(abs(num)); break;
       }
       int pnum = sign(num) * p->Num;
       if(ge && std::find(ge->physicals.begin(), ge->physicals.end(), pnum) == 
          ge->physicals.end())
         ge->physicals.push_back(pnum);
     }
-
-    // the physical is a compound i.e. we allow the meshes
-    // not to conform internal MEdges of the compound
-
-    if (p->Typ == MSH_PHYSICAL_LINE && p->Boundaries[0]){
-      GEdge *ge = getEdgeByTag(abs(p->Num));
-      if (!ge){
-        GEdgeCompound *ge = new GEdgeCompound(this, p->Num, e_compound);
-        add(ge);
-      }
-      else
-        ge->resetMeshAttributes();
-    }      
-    if (p->Typ == MSH_PHYSICAL_SURFACE && p->Boundaries[0]){
-      int i = 0;
-      List_T *bnd;
-      std::list<GEdge*> b[4];
-      while(i < 4 && (bnd = p->Boundaries[i])){
-        for(int j = 0; j < List_Nbr(bnd); j++){
-          int ie;
-          List_Read(bnd, j, &ie);
-          b[i].push_back(getEdgeByTag(abs(ie)));
-        }
-        i++;
-      }
-      GFace *gf = getFaceByTag(abs(p->Num));
-      if (!gf){
-        GFaceCompound *gf = new GFaceCompound(this, abs(p->Num), f_compound, 
-                                              b[0], b[1], b[2], b[3],0,
-					      p->Num > 0 ? GFaceCompound::HARMONIC :
-					      GFaceCompound::CONFORMAL);
-        add(gf);
-      }
-      else
-        gf->resetMeshAttributes();
-    }   
-    if (p->Typ == MSH_PHYSICAL_VOLUME && p->Boundaries[0]){
-      GRegion *gr = getRegionByTag(abs(p->Num));
-      if (!gr){
-        GRegionCompound *gr = new GRegionCompound(this, p->Num, r_compound);
-        add(gr);
-      }
-      else
-        gr->resetMeshAttributes();
-    }
-   
   }
 
   Msg::Debug("Gmsh model (GModel) imported:");
diff --git a/Geo/Geo.cpp b/Geo/Geo.cpp
index f0643c4e6528abb8c115c075e46f1640773c345f..5b176ec30d5f933015e070ca01802ad2375f2125 100644
--- a/Geo/Geo.cpp
+++ b/Geo/Geo.cpp
@@ -147,7 +147,7 @@ static void Free_Vertex(void *a, void *b)
   }
 }
 
-PhysicalGroup *Create_PhysicalGroup(int Num, int typ, List_T *intlist, List_T *bndlist[4])
+PhysicalGroup *Create_PhysicalGroup(int Num, int typ, List_T *intlist)
 {
   PhysicalGroup *p = new PhysicalGroup;
   p->Entities = List_Create(List_Nbr(intlist), 1, sizeof(int));
@@ -161,17 +161,6 @@ PhysicalGroup *Create_PhysicalGroup(int Num, int typ, List_T *intlist, List_T *b
     List_Read(intlist, i, &j);
     List_Add(p->Entities, &j);
   }
-  p->Boundaries[0] = p->Boundaries[1] = p->Boundaries[2] = p->Boundaries[3] = 0;
-  if (bndlist){
-    for(int i = 0; i < 4; i++) {
-      p->Boundaries[i] = List_Create(List_Nbr(bndlist[i]), 1, sizeof(int));
-      for(int j = 0; j < List_Nbr(bndlist[i]); j++) {
-        int k;
-        List_Read(bndlist[i], j, &k);
-        List_Add(p->Boundaries[i], &k);
-      }
-    }
-  }
   return p;
 }
 
diff --git a/Geo/Geo.h b/Geo/Geo.h
index a24f0cfa63f95a51111ba34a0884ec1ced7b1eb1..0aa29f94ccc7362e12dd5d8e86d2868a66edf58c 100644
--- a/Geo/Geo.h
+++ b/Geo/Geo.h
@@ -7,6 +7,7 @@
 #define _GEO_H_
 
 #include <math.h>
+#include <vector>
 #include "GmshDefines.h"
 #include "gmshSurface.h"
 #include "ListUtils.h"
@@ -33,6 +34,7 @@
 #define MSH_SEGM_BND_LAYER     211
 #define MSH_SEGM_DISCRETE      212
 #define MSH_SEGM_FROM_GMODEL   213
+#define MSH_SEGM_COMPOUND      214
 
 #define MSH_SURF_PLAN          300
 #define MSH_SURF_REGL          301
@@ -41,10 +43,12 @@
 #define MSH_SURF_LOOP          304
 #define MSH_SURF_DISCRETE      305
 #define MSH_SURF_FROM_GMODEL   306
+#define MSH_SURF_COMPOUND      307
 
 #define MSH_VOLUME             400
 #define MSH_VOLUME_DISCRETE    401
 #define MSH_VOLUME_FROM_GMODEL 402
+#define MSH_VOLUME_COMPOUND    403
 
 #define MSH_PHYSICAL_POINT     500
 #define MSH_PHYSICAL_LINE      501
@@ -127,6 +131,7 @@ class Curve{
   CircParam Circle;
   DrawingColor Color;
   gmshSurface *geometry;
+  std::vector<int> compound;
 };
 
 class EdgeLoop{
@@ -158,6 +163,7 @@ class Surface{
   // should be the only one in gmsh, so parameter "Type" should
   // disappear from the class Surface.
   gmshSurface *geometry;
+  std::vector<int> compound, compoundBoundary[4];
 };
 
 class SurfaceLoop{
@@ -178,6 +184,7 @@ class Volume {
   List_T *SurfacesOrientations;
   List_T *SurfacesByTag;
   DrawingColor Color;
+  std::vector<int> compound;
 };
 
 class PhysicalGroup{
@@ -186,7 +193,6 @@ class PhysicalGroup{
   int Typ;
   char Visible;
   List_T *Entities;
-  List_T *Boundaries[4];
 };
 
 class GEO_Internals{
@@ -226,23 +232,22 @@ class LevelSet {
 
 int compareVertex(const void *a, const void *b);
 
-void Projette(Vertex * v, double mat[3][3]);
+void Projette(Vertex *v, double mat[3][3]);
 
 Vertex *Create_Vertex(int Num, double X, double Y, double Z, double lc, double u);
 Vertex *Create_Vertex(int Num, double u, double v, gmshSurface *s, double lc);
-Curve *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
-                    List_T * Knots, int p1, int p2, double u1, double u2);
+Curve *Create_Curve(int Num, int Typ, int Order, List_T *Liste,
+                    List_T *Knots, int p1, int p2, double u1, double u2);
 Curve *CreateReversedCurve(Curve *c);
 Surface *Create_Surface(int Num, int Typ);
 Volume *Create_Volume(int Num, int Typ);
-EdgeLoop *Create_EdgeLoop(int Num, List_T * intlist);
-SurfaceLoop *Create_SurfaceLoop(int Num, List_T * intlist);
-PhysicalGroup *Create_PhysicalGroup(int Num, int typ, List_T * intlist,
-                                    List_T *bndlist[4] = 0);
+EdgeLoop *Create_EdgeLoop(int Num, List_T *intlist);
+SurfaceLoop *Create_SurfaceLoop(int Num, List_T *intlist);
+PhysicalGroup *Create_PhysicalGroup(int Num, int typ, List_T *intlist);
 LevelSet *Create_LevelSet(int Num, gLevelset *l);
 
-void End_Curve(Curve * c);
-void End_Surface(Surface * s);
+void End_Curve(Curve *c);
+void End_Surface(Surface *s);
 
 int NEWPOINT(void);
 int NEWLINE(void);
@@ -302,7 +307,7 @@ int recognize_surfloop(List_T *liste, int *loop);
 
 void sortEdgesInLoop(int num, List_T *edges);
 void setSurfaceGeneratrices(Surface *s, List_T *loops);
-void setVolumeSurfaces(Volume *v, List_T * loops);
+void setVolumeSurfaces(Volume *v, List_T *loops);
 void setSurfaceEmbeddedPoints(Surface *s, List_T *points);
 void setSurfaceEmbeddedCurves(Surface *s, List_T *curves);
 
diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp
index 317772eaaedfd43bbe34e6c0d439d27c7377ae04..c3ed7f2db21212eb664ad9a94b1fb6bcde7fa0e1 100644
--- a/Parser/Gmsh.tab.cpp
+++ b/Parser/Gmsh.tab.cpp
@@ -1030,33 +1030,33 @@ static const yytype_uint16 yyrline[] =
      983,   986,   999,  1002,  1012,  1036,  1035,  1055,  1077,  1095,
     1117,  1135,  1165,  1195,  1213,  1231,  1257,  1275,  1274,  1297,
     1315,  1354,  1360,  1366,  1373,  1398,  1423,  1440,  1439,  1459,
-    1476,  1504,  1521,  1542,  1560,  1578,  1593,  1592,  1618,  1623,
-    1628,  1633,  1638,  1658,  1664,  1675,  1676,  1681,  1684,  1688,
-    1711,  1734,  1757,  1785,  1806,  1827,  1849,  1869,  1981,  2000,
-    2014,  2123,  2132,  2138,  2153,  2181,  2198,  2212,  2218,  2224,
-    2233,  2247,  2287,  2304,  2319,  2338,  2350,  2374,  2378,  2385,
-    2391,  2396,  2402,  2412,  2429,  2446,  2465,  2484,  2514,  2522,
-    2528,  2535,  2539,  2548,  2556,  2564,  2573,  2572,  2585,  2584,
-    2597,  2596,  2609,  2608,  2621,  2628,  2635,  2642,  2649,  2656,
-    2663,  2670,  2677,  2685,  2684,  2696,  2695,  2707,  2706,  2718,
-    2717,  2729,  2728,  2740,  2739,  2751,  2750,  2762,  2761,  2773,
-    2772,  2787,  2790,  2796,  2805,  2825,  2848,  2852,  2876,  2879,
-    2895,  2898,  2911,  2914,  2920,  2923,  2930,  2986,  3056,  3061,
-    3128,  3171,  3197,  3220,  3243,  3246,  3255,  3259,  3276,  3309,
-    3343,  3381,  3382,  3383,  3384,  3385,  3386,  3387,  3388,  3389,
-    3396,  3397,  3398,  3399,  3400,  3401,  3402,  3403,  3404,  3405,
-    3406,  3407,  3408,  3409,  3410,  3411,  3412,  3413,  3414,  3415,
-    3416,  3417,  3418,  3419,  3420,  3421,  3422,  3423,  3424,  3425,
-    3426,  3427,  3429,  3430,  3431,  3432,  3433,  3434,  3435,  3436,
-    3437,  3438,  3439,  3440,  3441,  3442,  3443,  3444,  3445,  3446,
-    3447,  3448,  3449,  3458,  3459,  3460,  3461,  3462,  3463,  3464,
-    3468,  3481,  3493,  3508,  3518,  3528,  3546,  3551,  3556,  3566,
-    3576,  3584,  3588,  3592,  3596,  3600,  3607,  3611,  3615,  3619,
-    3626,  3631,  3638,  3643,  3647,  3652,  3656,  3664,  3675,  3679,
-    3691,  3699,  3707,  3714,  3725,  3745,  3755,  3765,  3775,  3795,
-    3800,  3804,  3808,  3820,  3824,  3836,  3843,  3853,  3857,  3872,
-    3877,  3884,  3888,  3901,  3909,  3920,  3924,  3932,  3940,  3954,
-    3968,  3972
+    1475,  1505,  1521,  1541,  1559,  1577,  1592,  1591,  1617,  1622,
+    1627,  1632,  1637,  1657,  1663,  1674,  1675,  1680,  1683,  1687,
+    1710,  1733,  1756,  1784,  1805,  1826,  1848,  1868,  1980,  1999,
+    2013,  2122,  2131,  2137,  2152,  2180,  2197,  2211,  2217,  2223,
+    2232,  2246,  2286,  2303,  2318,  2337,  2349,  2373,  2377,  2384,
+    2390,  2395,  2401,  2411,  2428,  2445,  2464,  2483,  2513,  2521,
+    2527,  2534,  2538,  2547,  2555,  2563,  2572,  2571,  2584,  2583,
+    2596,  2595,  2608,  2607,  2620,  2627,  2634,  2641,  2648,  2655,
+    2662,  2669,  2676,  2684,  2683,  2695,  2694,  2706,  2705,  2717,
+    2716,  2728,  2727,  2739,  2738,  2750,  2749,  2761,  2760,  2772,
+    2771,  2786,  2789,  2795,  2804,  2824,  2847,  2851,  2875,  2878,
+    2894,  2897,  2910,  2913,  2919,  2922,  2929,  2985,  3055,  3060,
+    3127,  3170,  3196,  3219,  3242,  3245,  3254,  3258,  3275,  3308,
+    3342,  3380,  3381,  3382,  3383,  3384,  3385,  3386,  3387,  3388,
+    3395,  3396,  3397,  3398,  3399,  3400,  3401,  3402,  3403,  3404,
+    3405,  3406,  3407,  3408,  3409,  3410,  3411,  3412,  3413,  3414,
+    3415,  3416,  3417,  3418,  3419,  3420,  3421,  3422,  3423,  3424,
+    3425,  3426,  3428,  3429,  3430,  3431,  3432,  3433,  3434,  3435,
+    3436,  3437,  3438,  3439,  3440,  3441,  3442,  3443,  3444,  3445,
+    3446,  3447,  3448,  3457,  3458,  3459,  3460,  3461,  3462,  3463,
+    3467,  3480,  3492,  3507,  3517,  3527,  3545,  3550,  3555,  3565,
+    3575,  3583,  3587,  3591,  3595,  3599,  3606,  3610,  3614,  3618,
+    3625,  3630,  3637,  3642,  3646,  3651,  3655,  3663,  3674,  3678,
+    3690,  3698,  3706,  3713,  3724,  3744,  3754,  3764,  3774,  3794,
+    3799,  3803,  3807,  3819,  3823,  3835,  3842,  3852,  3856,  3871,
+    3876,  3883,  3887,  3900,  3908,  3919,  3923,  3931,  3939,  3953,
+    3967,  3971
 };
 #endif
 
@@ -5373,68 +5373,68 @@ yyreduce:
 #line 1460 "Gmsh.y"
     {
       int num = (int)(yyvsp[(4) - (8)].d);
-      if(FindPhysicalGroup(num, MSH_PHYSICAL_VOLUME)){
-	yymsg(0, "Physical volume %d already exists", num);
+      if(FindVolume(num)){
+	yymsg(0, "Volume %d already exists", num);
       }
       else{
-	List_T *temp = ListOfDouble2ListOfInt((yyvsp[(7) - (8)].l));
-	List_T *S[4] = {temp, 0, 0, 0};
-	PhysicalGroup *p = Create_PhysicalGroup(num, MSH_PHYSICAL_VOLUME, temp, S);
-	List_Delete(temp);
-        List_Add(GModel::current()->getGEOInternals()->PhysicalGroups, &p);
+	Volume *v = Create_Volume(num, MSH_VOLUME_COMPOUND);
+        for(int i = 0; i < List_Nbr((yyvsp[(7) - (8)].l)); i++)
+          v->compound.push_back((int)*(double*)List_Pointer((yyvsp[(7) - (8)].l), i));
+	Tree_Add(GModel::current()->getGEOInternals()->Volumes, &v);
       }
       List_Delete((yyvsp[(7) - (8)].l));
-      (yyval.s).Type = MSH_PHYSICAL_VOLUME;
+      (yyval.s).Type = MSH_VOLUME_COMPOUND;
       (yyval.s).Num = num;
     ;}
     break;
 
   case 120:
-#line 1478 "Gmsh.y"
+#line 1477 "Gmsh.y"
     {
       int num = (int)(yyvsp[(4) - (12)].d);
-      if(FindPhysicalGroup(num, MSH_PHYSICAL_SURFACE)){
-	yymsg(0, "Physical surface %d already exists", num);
+      if(FindSurface(num)){
+	yymsg(0, "Surface %d already exists", num);
       }
       else{
-	List_T *temp = ListOfDouble2ListOfInt((yyvsp[(7) - (12)].l));
-	List_T *S[4] = {0, 0, 0, 0};
+        Surface *s = Create_Surface(num, MSH_SURF_COMPOUND);
+        for(int i = 0; i < List_Nbr((yyvsp[(7) - (12)].l)); i++)
+          s->compound.push_back((int)*(double*)List_Pointer((yyvsp[(7) - (12)].l), i));
 	for (int i = 0; i < List_Nbr((yyvsp[(10) - (12)].l)); i++){
-	  List_T *ll;
-	  List_Read((yyvsp[(10) - (12)].l), i, &ll);
-	  S[i] = ListOfDouble2ListOfInt(ll);
-          List_Delete(ll);
+          if(i > 3){
+            yymsg(0, "Too many boundary specifiers in compound surface");
+            break;
+          }
+	  List_T *l = *(List_T**)List_Pointer((yyvsp[(10) - (12)].l), i);
+          for (int j = 0; j < List_Nbr(l); j++)
+            s->compoundBoundary[i].push_back((int)*(double*)List_Pointer(l, j));
 	}
-	PhysicalGroup *p = Create_PhysicalGroup(num, MSH_PHYSICAL_SURFACE, temp, S);
-	List_Delete(temp);
-	for (int i = 0; i < List_Nbr((yyvsp[(10) - (12)].l)); i++)
-	  List_Delete(S[i]);
-        List_Add(GModel::current()->getGEOInternals()->PhysicalGroups, &p);
+	Tree_Add(GModel::current()->getGEOInternals()->Surfaces, &s);
       }
       List_Delete((yyvsp[(7) - (12)].l));
+      for (int i = 0; i < List_Nbr((yyvsp[(10) - (12)].l)); i++)
+        List_Delete(*(List_T**)List_Pointer((yyvsp[(10) - (12)].l), i));
       List_Delete((yyvsp[(10) - (12)].l));
       Free((yyvsp[(8) - (12)].c));
-      (yyval.s).Type = MSH_PHYSICAL_SURFACE;
+      (yyval.s).Type = MSH_SURF_COMPOUND;
       (yyval.s).Num = num;
     ;}
     break;
 
   case 121:
-#line 1505 "Gmsh.y"
+#line 1506 "Gmsh.y"
     {
       int num = (int)(yyvsp[(4) - (8)].d);
-      if(FindPhysicalGroup(num, MSH_PHYSICAL_SURFACE)){
-	yymsg(0, "Physical surface %d already exists", num);
+      if(FindSurface(num)){
+	yymsg(0, "Surface %d already exists", num);
       }
       else{
-	List_T *temp = ListOfDouble2ListOfInt((yyvsp[(7) - (8)].l));
-	List_T *S[4] = {0, 0, 0, 0};
-	PhysicalGroup *p = Create_PhysicalGroup(num, MSH_PHYSICAL_SURFACE, temp, S);
-	List_Delete(temp);
-	List_Add(GModel::current()->getGEOInternals()->PhysicalGroups, &p);
+        Surface *s = Create_Surface(num, MSH_SURF_COMPOUND);
+        for(int i = 0; i < List_Nbr((yyvsp[(7) - (8)].l)); i++)
+          s->compound.push_back((int)*(double*)List_Pointer((yyvsp[(7) - (8)].l), i));
+	Tree_Add(GModel::current()->getGEOInternals()->Surfaces, &s);
       }
       List_Delete((yyvsp[(7) - (8)].l));
-      (yyval.s).Type = MSH_PHYSICAL_SURFACE;
+      (yyval.s).Type = MSH_SURF_COMPOUND;
       (yyval.s).Num = num;
     ;}
     break;
@@ -5443,24 +5443,23 @@ yyreduce:
 #line 1522 "Gmsh.y"
     {
       int num = (int)(yyvsp[(4) - (8)].d);
-      if(FindPhysicalGroup(num, MSH_PHYSICAL_LINE)){
-	yymsg(0, "Physical line %d already exists", num);
+      if(FindCurve(num)){
+	yymsg(0, "Curve %d already exists", num);
       }
       else{
-	List_T *temp = ListOfDouble2ListOfInt((yyvsp[(7) - (8)].l));
-	List_T *S[4] = {temp, 0, 0, 0};
-	PhysicalGroup *p = Create_PhysicalGroup(num, MSH_PHYSICAL_LINE, temp, S);
-	List_Delete(temp);
-	List_Add(GModel::current()->getGEOInternals()->PhysicalGroups, &p);
+        Curve *c = Create_Curve(num, MSH_SEGM_COMPOUND, 1, NULL, NULL, -1, -1, 0., 1.);
+        for(int i = 0; i < List_Nbr((yyvsp[(7) - (8)].l)); i++)
+          c->compound.push_back((int)*(double*)List_Pointer((yyvsp[(7) - (8)].l), i));
+	Tree_Add(GModel::current()->getGEOInternals()->Curves, &c);
       }
       List_Delete((yyvsp[(7) - (8)].l));
-      (yyval.s).Type = MSH_PHYSICAL_LINE;
+      (yyval.s).Type = MSH_SEGM_COMPOUND;
       (yyval.s).Num = num;
     ;}
     break;
 
   case 123:
-#line 1543 "Gmsh.y"
+#line 1542 "Gmsh.y"
     {
       yymsg(0, "'Complex Volume' command is deprecated: use 'Volume' instead");
       int num = (int)(yyvsp[(4) - (8)].d);
@@ -5481,7 +5480,7 @@ yyreduce:
     break;
 
   case 124:
-#line 1561 "Gmsh.y"
+#line 1560 "Gmsh.y"
     {
       int num = (int)(yyvsp[(3) - (7)].d);
       if(FindVolume(num)){
@@ -5501,7 +5500,7 @@ yyreduce:
     break;
 
   case 125:
-#line 1579 "Gmsh.y"
+#line 1578 "Gmsh.y"
     {
 #if defined(HAVE_OCC)
       std::vector<double> data;
@@ -5517,14 +5516,14 @@ yyreduce:
     break;
 
   case 126:
-#line 1593 "Gmsh.y"
+#line 1592 "Gmsh.y"
     {
       curPhysDim = 3;
     ;}
     break;
 
   case 127:
-#line 1597 "Gmsh.y"
+#line 1596 "Gmsh.y"
     {
       int num = (int)(yyvsp[(5) - (9)].i);
       if(FindPhysicalGroup(num, MSH_PHYSICAL_VOLUME)){
@@ -5543,7 +5542,7 @@ yyreduce:
     break;
 
   case 128:
-#line 1619 "Gmsh.y"
+#line 1618 "Gmsh.y"
     {
       TranslateShapes((yyvsp[(2) - (5)].v)[0], (yyvsp[(2) - (5)].v)[1], (yyvsp[(2) - (5)].v)[2], (yyvsp[(4) - (5)].l));
       (yyval.l) = (yyvsp[(4) - (5)].l);
@@ -5551,7 +5550,7 @@ yyreduce:
     break;
 
   case 129:
-#line 1624 "Gmsh.y"
+#line 1623 "Gmsh.y"
     {
       RotateShapes((yyvsp[(3) - (11)].v)[0], (yyvsp[(3) - (11)].v)[1], (yyvsp[(3) - (11)].v)[2], (yyvsp[(5) - (11)].v)[0], (yyvsp[(5) - (11)].v)[1], (yyvsp[(5) - (11)].v)[2], (yyvsp[(7) - (11)].d), (yyvsp[(10) - (11)].l));
       (yyval.l) = (yyvsp[(10) - (11)].l);
@@ -5559,7 +5558,7 @@ yyreduce:
     break;
 
   case 130:
-#line 1629 "Gmsh.y"
+#line 1628 "Gmsh.y"
     {
       SymmetryShapes((yyvsp[(2) - (5)].v)[0], (yyvsp[(2) - (5)].v)[1], (yyvsp[(2) - (5)].v)[2], (yyvsp[(2) - (5)].v)[3], (yyvsp[(4) - (5)].l));
       (yyval.l) = (yyvsp[(4) - (5)].l);
@@ -5567,7 +5566,7 @@ yyreduce:
     break;
 
   case 131:
-#line 1634 "Gmsh.y"
+#line 1633 "Gmsh.y"
     {
       DilatShapes((yyvsp[(3) - (9)].v)[0], (yyvsp[(3) - (9)].v)[1], (yyvsp[(3) - (9)].v)[2], (yyvsp[(5) - (9)].d), (yyvsp[(8) - (9)].l));
       (yyval.l) = (yyvsp[(8) - (9)].l);
@@ -5575,7 +5574,7 @@ yyreduce:
     break;
 
   case 132:
-#line 1639 "Gmsh.y"
+#line 1638 "Gmsh.y"
     {
       (yyval.l) = List_Create(3, 3, sizeof(Shape));
       if(!strcmp((yyvsp[(1) - (4)].c), "Duplicata")){
@@ -5598,7 +5597,7 @@ yyreduce:
     break;
 
   case 133:
-#line 1659 "Gmsh.y"
+#line 1658 "Gmsh.y"
     { 
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       IntersectCurvesWithSurface((yyvsp[(4) - (9)].l), (int)(yyvsp[(8) - (9)].d), (yyval.l));
@@ -5607,7 +5606,7 @@ yyreduce:
     break;
 
   case 134:
-#line 1665 "Gmsh.y"
+#line 1664 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape*));
       List_T *tmp = ListOfDouble2ListOfInt((yyvsp[(7) - (9)].l));
@@ -5618,31 +5617,31 @@ yyreduce:
     break;
 
   case 135:
-#line 1675 "Gmsh.y"
+#line 1674 "Gmsh.y"
     { (yyval.l) = (yyvsp[(1) - (1)].l); ;}
     break;
 
   case 136:
-#line 1676 "Gmsh.y"
+#line 1675 "Gmsh.y"
     { (yyval.l) = (yyvsp[(1) - (1)].l); ;}
     break;
 
   case 137:
-#line 1681 "Gmsh.y"
+#line 1680 "Gmsh.y"
     {
       (yyval.l) = List_Create(3, 3, sizeof(Shape));
     ;}
     break;
 
   case 138:
-#line 1685 "Gmsh.y"
+#line 1684 "Gmsh.y"
     {
       List_Add((yyval.l), &(yyvsp[(2) - (2)].s));
     ;}
     break;
 
   case 139:
-#line 1689 "Gmsh.y"
+#line 1688 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(4) - (6)].l)); i++){
 	double d;
@@ -5668,7 +5667,7 @@ yyreduce:
     break;
 
   case 140:
-#line 1712 "Gmsh.y"
+#line 1711 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(4) - (6)].l)); i++){
 	double d;
@@ -5694,7 +5693,7 @@ yyreduce:
     break;
 
   case 141:
-#line 1735 "Gmsh.y"
+#line 1734 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(4) - (6)].l)); i++){
 	double d;
@@ -5720,7 +5719,7 @@ yyreduce:
     break;
 
   case 142:
-#line 1758 "Gmsh.y"
+#line 1757 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(4) - (6)].l)); i++){
 	double d;
@@ -5746,7 +5745,7 @@ yyreduce:
     break;
 
   case 143:
-#line 1786 "Gmsh.y"
+#line 1785 "Gmsh.y"
     {
 #if defined(HAVE_DINTEGRATION)
       if(List_Nbr((yyvsp[(7) - (8)].l)) == 4){
@@ -5770,7 +5769,7 @@ yyreduce:
     break;
 
   case 144:
-#line 1808 "Gmsh.y"
+#line 1807 "Gmsh.y"
     {
 #if defined(HAVE_DINTEGRATION)
       if(List_Nbr((yyvsp[(12) - (14)].l)) == 0){
@@ -5793,7 +5792,7 @@ yyreduce:
     break;
 
   case 145:
-#line 1829 "Gmsh.y"
+#line 1828 "Gmsh.y"
     {
 #if defined(HAVE_DINTEGRATION)
       if(List_Nbr((yyvsp[(14) - (16)].l)) == 0){
@@ -5817,7 +5816,7 @@ yyreduce:
     break;
 
   case 146:
-#line 1850 "Gmsh.y"
+#line 1849 "Gmsh.y"
     {
 #if defined(HAVE_DINTEGRATION)
       if(List_Nbr((yyvsp[(10) - (12)].l)) == 1){
@@ -5840,7 +5839,7 @@ yyreduce:
     break;
 
   case 147:
-#line 1870 "Gmsh.y"
+#line 1869 "Gmsh.y"
     {
 #if defined(HAVE_DINTEGRATION)
       if(!strcmp((yyvsp[(2) - (8)].c), "Union")){
@@ -5955,7 +5954,7 @@ yyreduce:
     break;
 
   case 148:
-#line 1982 "Gmsh.y"
+#line 1981 "Gmsh.y"
     {
 #if defined(HAVE_DINTEGRATION)
       if(!strcmp((yyvsp[(2) - (8)].c), "MathEval")){
@@ -5977,7 +5976,7 @@ yyreduce:
     break;
 
   case 149:
-#line 2001 "Gmsh.y"
+#line 2000 "Gmsh.y"
     {
 #if defined(HAVE_DINTEGRATION)
       if(!strcmp((yyvsp[(2) - (6)].c), "CutMesh")){
@@ -5994,7 +5993,7 @@ yyreduce:
     break;
 
   case 150:
-#line 2016 "Gmsh.y"
+#line 2015 "Gmsh.y"
     {
 #if defined(HAVE_DINTEGRATION)
       if(!strcmp((yyvsp[(2) - (14)].c), "Cylinder") && List_Nbr((yyvsp[(12) - (14)].l)) == 1){
@@ -6100,7 +6099,7 @@ yyreduce:
     break;
 
   case 151:
-#line 2124 "Gmsh.y"
+#line 2123 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){
 	Shape TheShape;
@@ -6112,7 +6111,7 @@ yyreduce:
     break;
 
   case 152:
-#line 2133 "Gmsh.y"
+#line 2132 "Gmsh.y"
     {
 #if defined(HAVE_MESH)
       GModel::current()->getFields()->deleteField((int)(yyvsp[(4) - (6)].d));
@@ -6121,7 +6120,7 @@ yyreduce:
     break;
 
   case 153:
-#line 2139 "Gmsh.y"
+#line 2138 "Gmsh.y"
     {
 #if defined(HAVE_POST)
       if(!strcmp((yyvsp[(2) - (6)].c), "View")){
@@ -6139,7 +6138,7 @@ yyreduce:
     break;
 
   case 154:
-#line 2154 "Gmsh.y"
+#line 2153 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (3)].c), "Meshes") || !strcmp((yyvsp[(2) - (3)].c), "All")){
         ClearProject();
@@ -6170,7 +6169,7 @@ yyreduce:
     break;
 
   case 155:
-#line 2182 "Gmsh.y"
+#line 2181 "Gmsh.y"
     {
 #if defined(HAVE_POST)
       if(!strcmp((yyvsp[(2) - (4)].c), "Empty") && !strcmp((yyvsp[(3) - (4)].c), "Views")){
@@ -6185,7 +6184,7 @@ yyreduce:
     break;
 
   case 156:
-#line 2199 "Gmsh.y"
+#line 2198 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(4) - (5)].l)); i++){
 	Shape TheShape;
@@ -6197,7 +6196,7 @@ yyreduce:
     break;
 
   case 157:
-#line 2213 "Gmsh.y"
+#line 2212 "Gmsh.y"
     {
       for(int i = 0; i < 4; i++)
 	VisibilityShape((yyvsp[(2) - (3)].c), i, 1);
@@ -6206,7 +6205,7 @@ yyreduce:
     break;
 
   case 158:
-#line 2219 "Gmsh.y"
+#line 2218 "Gmsh.y"
     {
       for(int i = 0; i < 4; i++)
 	VisibilityShape((yyvsp[(2) - (3)].c), i, 0);
@@ -6215,7 +6214,7 @@ yyreduce:
     break;
 
   case 159:
-#line 2225 "Gmsh.y"
+#line 2224 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){
 	Shape TheShape;
@@ -6227,7 +6226,7 @@ yyreduce:
     break;
 
   case 160:
-#line 2234 "Gmsh.y"
+#line 2233 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){
 	Shape TheShape;
@@ -6239,7 +6238,7 @@ yyreduce:
     break;
 
   case 161:
-#line 2248 "Gmsh.y"
+#line 2247 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(1) - (3)].c), "Include")){
         std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(2) - (3)].c));
@@ -6282,7 +6281,7 @@ yyreduce:
     break;
 
   case 162:
-#line 2288 "Gmsh.y"
+#line 2287 "Gmsh.y"
     {
 #if defined(HAVE_POST)
       if(!strcmp((yyvsp[(1) - (7)].c), "Save") && !strcmp((yyvsp[(2) - (7)].c), "View")){
@@ -6302,7 +6301,7 @@ yyreduce:
     break;
 
   case 163:
-#line 2305 "Gmsh.y"
+#line 2304 "Gmsh.y"
     {
 #if defined(HAVE_POST) && defined(HAVE_MESH)
       if(!strcmp((yyvsp[(1) - (7)].c), "Background") && !strcmp((yyvsp[(2) - (7)].c), "Mesh")  && !strcmp((yyvsp[(3) - (7)].c), "View")){
@@ -6320,7 +6319,7 @@ yyreduce:
     break;
 
   case 164:
-#line 2320 "Gmsh.y"
+#line 2319 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(1) - (3)].c), "Sleep")){
 	SleepInSeconds((yyvsp[(2) - (3)].d));
@@ -6342,7 +6341,7 @@ yyreduce:
     break;
 
   case 165:
-#line 2339 "Gmsh.y"
+#line 2338 "Gmsh.y"
     {
 #if defined(HAVE_POST)
        try {
@@ -6357,7 +6356,7 @@ yyreduce:
     break;
 
   case 166:
-#line 2351 "Gmsh.y"
+#line 2350 "Gmsh.y"
     {
 #if defined(HAVE_POST)
       if(!strcmp((yyvsp[(2) - (3)].c), "ElementsFromAllViews"))
@@ -6384,14 +6383,14 @@ yyreduce:
     break;
 
   case 167:
-#line 2375 "Gmsh.y"
+#line 2374 "Gmsh.y"
     {
       exit(0);
     ;}
     break;
 
   case 168:
-#line 2379 "Gmsh.y"
+#line 2378 "Gmsh.y"
     {
       // FIXME: this is a hack to force a transfer from the old DB to
       // the new DB. This will become unnecessary if/when we fill the 
@@ -6401,7 +6400,7 @@ yyreduce:
     break;
 
   case 169:
-#line 2386 "Gmsh.y"
+#line 2385 "Gmsh.y"
     {
       CTX::instance()->forcedBBox = 0;
       GModel::current()->importGEOInternals();
@@ -6410,7 +6409,7 @@ yyreduce:
     break;
 
   case 170:
-#line 2392 "Gmsh.y"
+#line 2391 "Gmsh.y"
     {
       CTX::instance()->forcedBBox = 1;
       SetBoundingBox((yyvsp[(3) - (15)].d), (yyvsp[(5) - (15)].d), (yyvsp[(7) - (15)].d), (yyvsp[(9) - (15)].d), (yyvsp[(11) - (15)].d), (yyvsp[(13) - (15)].d));
@@ -6418,7 +6417,7 @@ yyreduce:
     break;
 
   case 171:
-#line 2397 "Gmsh.y"
+#line 2396 "Gmsh.y"
     {
 #if defined(HAVE_OPENGL)
       drawContext::global()->draw();
@@ -6427,14 +6426,14 @@ yyreduce:
     break;
 
   case 172:
-#line 2403 "Gmsh.y"
+#line 2402 "Gmsh.y"
     {
        GModel::current()->createTopologyFromMesh();
     ;}
     break;
 
   case 173:
-#line 2413 "Gmsh.y"
+#line 2412 "Gmsh.y"
     {
       LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(3) - (6)].d);
       LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(5) - (6)].d);
@@ -6454,7 +6453,7 @@ yyreduce:
     break;
 
   case 174:
-#line 2430 "Gmsh.y"
+#line 2429 "Gmsh.y"
     {
       LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(3) - (8)].d);
       LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(5) - (8)].d);
@@ -6474,7 +6473,7 @@ yyreduce:
     break;
 
   case 175:
-#line 2447 "Gmsh.y"
+#line 2446 "Gmsh.y"
     {
       LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(5) - (8)].d);
       LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(7) - (8)].d);
@@ -6496,7 +6495,7 @@ yyreduce:
     break;
 
   case 176:
-#line 2466 "Gmsh.y"
+#line 2465 "Gmsh.y"
     {
       LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(5) - (10)].d);
       LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(7) - (10)].d);
@@ -6518,7 +6517,7 @@ yyreduce:
     break;
 
   case 177:
-#line 2485 "Gmsh.y"
+#line 2484 "Gmsh.y"
     {
       if(ImbricatedLoop <= 0){
 	yymsg(0, "Invalid For/EndFor loop");
@@ -6551,7 +6550,7 @@ yyreduce:
     break;
 
   case 178:
-#line 2515 "Gmsh.y"
+#line 2514 "Gmsh.y"
     {
       if(!FunctionManager::Instance()->createFunction
          ((yyvsp[(2) - (2)].c), gmsh_yyin, gmsh_yyname, gmsh_yylineno))
@@ -6562,7 +6561,7 @@ yyreduce:
     break;
 
   case 179:
-#line 2523 "Gmsh.y"
+#line 2522 "Gmsh.y"
     {
       if(!FunctionManager::Instance()->leaveFunction
          (&gmsh_yyin, gmsh_yyname, gmsh_yylineno))
@@ -6571,7 +6570,7 @@ yyreduce:
     break;
 
   case 180:
-#line 2529 "Gmsh.y"
+#line 2528 "Gmsh.y"
     {
       if(!FunctionManager::Instance()->enterFunction
          ((yyvsp[(2) - (3)].c), &gmsh_yyin, gmsh_yyname, gmsh_yylineno))
@@ -6581,20 +6580,20 @@ yyreduce:
     break;
 
   case 181:
-#line 2536 "Gmsh.y"
+#line 2535 "Gmsh.y"
     {
       if(!(yyvsp[(3) - (4)].d)) skip_until("If", "EndIf");
     ;}
     break;
 
   case 182:
-#line 2540 "Gmsh.y"
+#line 2539 "Gmsh.y"
     {
     ;}
     break;
 
   case 183:
-#line 2549 "Gmsh.y"
+#line 2548 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE, (yyvsp[(4) - (5)].l), 
@@ -6605,7 +6604,7 @@ yyreduce:
     break;
 
   case 184:
-#line 2557 "Gmsh.y"
+#line 2556 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(ROTATE, (yyvsp[(10) - (11)].l), 
@@ -6616,7 +6615,7 @@ yyreduce:
     break;
 
   case 185:
-#line 2565 "Gmsh.y"
+#line 2564 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE_ROTATE, (yyvsp[(12) - (13)].l), 
@@ -6627,14 +6626,14 @@ yyreduce:
     break;
 
   case 186:
-#line 2573 "Gmsh.y"
+#line 2572 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 187:
-#line 2577 "Gmsh.y"
+#line 2576 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE, (yyvsp[(4) - (7)].l), 
@@ -6645,14 +6644,14 @@ yyreduce:
     break;
 
   case 188:
-#line 2585 "Gmsh.y"
+#line 2584 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 189:
-#line 2589 "Gmsh.y"
+#line 2588 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(ROTATE, (yyvsp[(10) - (13)].l), 
@@ -6663,14 +6662,14 @@ yyreduce:
     break;
 
   case 190:
-#line 2597 "Gmsh.y"
+#line 2596 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 191:
-#line 2601 "Gmsh.y"
+#line 2600 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE_ROTATE, (yyvsp[(12) - (15)].l), 
@@ -6681,14 +6680,14 @@ yyreduce:
     break;
 
   case 192:
-#line 2609 "Gmsh.y"
+#line 2608 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 193:
-#line 2613 "Gmsh.y"
+#line 2612 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(BOUNDARY_LAYER, (yyvsp[(3) - (6)].l), 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
@@ -6698,7 +6697,7 @@ yyreduce:
     break;
 
   case 194:
-#line 2622 "Gmsh.y"
+#line 2621 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_POINT, (int)(yyvsp[(4) - (8)].d), 
@@ -6708,7 +6707,7 @@ yyreduce:
     break;
 
   case 195:
-#line 2629 "Gmsh.y"
+#line 2628 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SEGM_LINE, (int)(yyvsp[(4) - (8)].d), 
@@ -6718,7 +6717,7 @@ yyreduce:
     break;
 
   case 196:
-#line 2636 "Gmsh.y"
+#line 2635 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SURF_PLAN, (int)(yyvsp[(4) - (8)].d), 
@@ -6728,7 +6727,7 @@ yyreduce:
     break;
 
   case 197:
-#line 2643 "Gmsh.y"
+#line 2642 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_POINT, (int)(yyvsp[(4) - (12)].d), 
@@ -6738,7 +6737,7 @@ yyreduce:
     break;
 
   case 198:
-#line 2650 "Gmsh.y"
+#line 2649 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SEGM_LINE, (int)(yyvsp[(4) - (12)].d), 
@@ -6748,7 +6747,7 @@ yyreduce:
     break;
 
   case 199:
-#line 2657 "Gmsh.y"
+#line 2656 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SURF_PLAN, (int)(yyvsp[(4) - (12)].d), 
@@ -6758,7 +6757,7 @@ yyreduce:
     break;
 
   case 200:
-#line 2664 "Gmsh.y"
+#line 2663 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_POINT, (int)(yyvsp[(4) - (14)].d), 
@@ -6768,7 +6767,7 @@ yyreduce:
     break;
 
   case 201:
-#line 2671 "Gmsh.y"
+#line 2670 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SEGM_LINE, (int)(yyvsp[(4) - (14)].d), 
@@ -6778,7 +6777,7 @@ yyreduce:
     break;
 
   case 202:
-#line 2678 "Gmsh.y"
+#line 2677 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SURF_PLAN, (int)(yyvsp[(4) - (14)].d), 
@@ -6788,14 +6787,14 @@ yyreduce:
     break;
 
   case 203:
-#line 2685 "Gmsh.y"
+#line 2684 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 204:
-#line 2689 "Gmsh.y"
+#line 2688 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_POINT, (int)(yyvsp[(4) - (12)].d), 
@@ -6805,14 +6804,14 @@ yyreduce:
     break;
 
   case 205:
-#line 2696 "Gmsh.y"
+#line 2695 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 206:
-#line 2700 "Gmsh.y"
+#line 2699 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SEGM_LINE, (int)(yyvsp[(4) - (12)].d), 
@@ -6822,14 +6821,14 @@ yyreduce:
     break;
 
   case 207:
-#line 2707 "Gmsh.y"
+#line 2706 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 208:
-#line 2711 "Gmsh.y"
+#line 2710 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SURF_PLAN, (int)(yyvsp[(4) - (12)].d), 
@@ -6839,14 +6838,14 @@ yyreduce:
     break;
 
   case 209:
-#line 2718 "Gmsh.y"
+#line 2717 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 210:
-#line 2722 "Gmsh.y"
+#line 2721 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_POINT, (int)(yyvsp[(4) - (16)].d), 
@@ -6856,14 +6855,14 @@ yyreduce:
     break;
 
   case 211:
-#line 2729 "Gmsh.y"
+#line 2728 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 212:
-#line 2733 "Gmsh.y"
+#line 2732 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SEGM_LINE, (int)(yyvsp[(4) - (16)].d), 
@@ -6873,14 +6872,14 @@ yyreduce:
     break;
 
   case 213:
-#line 2740 "Gmsh.y"
+#line 2739 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 214:
-#line 2744 "Gmsh.y"
+#line 2743 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SURF_PLAN, (int)(yyvsp[(4) - (16)].d), 
@@ -6890,14 +6889,14 @@ yyreduce:
     break;
 
   case 215:
-#line 2751 "Gmsh.y"
+#line 2750 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 216:
-#line 2755 "Gmsh.y"
+#line 2754 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_POINT, (int)(yyvsp[(4) - (18)].d), 
@@ -6907,14 +6906,14 @@ yyreduce:
     break;
 
   case 217:
-#line 2762 "Gmsh.y"
+#line 2761 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 218:
-#line 2766 "Gmsh.y"
+#line 2765 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SEGM_LINE, (int)(yyvsp[(4) - (18)].d), 
@@ -6924,14 +6923,14 @@ yyreduce:
     break;
 
   case 219:
-#line 2773 "Gmsh.y"
+#line 2772 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
     ;}
     break;
 
   case 220:
-#line 2777 "Gmsh.y"
+#line 2776 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SURF_PLAN, (int)(yyvsp[(4) - (18)].d), 
@@ -6941,19 +6940,19 @@ yyreduce:
     break;
 
   case 221:
-#line 2788 "Gmsh.y"
+#line 2787 "Gmsh.y"
     {
     ;}
     break;
 
   case 222:
-#line 2791 "Gmsh.y"
+#line 2790 "Gmsh.y"
     {
     ;}
     break;
 
   case 223:
-#line 2797 "Gmsh.y"
+#line 2796 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = true;
       extr.mesh.NbLayer = 1;
@@ -6965,7 +6964,7 @@ yyreduce:
     break;
 
   case 224:
-#line 2806 "Gmsh.y"
+#line 2805 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = true;
       extr.mesh.NbLayer = List_Nbr((yyvsp[(3) - (7)].l));
@@ -6988,7 +6987,7 @@ yyreduce:
     break;
 
   case 225:
-#line 2826 "Gmsh.y"
+#line 2825 "Gmsh.y"
     {
       yymsg(0, "Explicit region numbers in layers are deprecated");
       extr.mesh.ExtrudeMesh = true;
@@ -7014,14 +7013,14 @@ yyreduce:
     break;
 
   case 226:
-#line 2849 "Gmsh.y"
+#line 2848 "Gmsh.y"
     {
       extr.mesh.Recombine = true;
     ;}
     break;
 
   case 227:
-#line 2853 "Gmsh.y"
+#line 2852 "Gmsh.y"
     {
       int num = (int)(yyvsp[(3) - (9)].d);
       if(FindSurface(num)){
@@ -7043,14 +7042,14 @@ yyreduce:
     break;
 
   case 228:
-#line 2876 "Gmsh.y"
+#line 2875 "Gmsh.y"
     {
       (yyval.v)[0] = (yyval.v)[1] = 1.;
     ;}
     break;
 
   case 229:
-#line 2880 "Gmsh.y"
+#line 2879 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (3)].c), "Progression") || !strcmp((yyvsp[(2) - (3)].c), "Power"))
         (yyval.v)[0] = 1.;
@@ -7066,14 +7065,14 @@ yyreduce:
     break;
 
   case 230:
-#line 2895 "Gmsh.y"
+#line 2894 "Gmsh.y"
     {
       (yyval.i) = -1; // left
     ;}
     break;
 
   case 231:
-#line 2899 "Gmsh.y"
+#line 2898 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(1) - (1)].c), "Right"))
         (yyval.i) = 1;
@@ -7086,35 +7085,35 @@ yyreduce:
     break;
 
   case 232:
-#line 2911 "Gmsh.y"
+#line 2910 "Gmsh.y"
     {
      (yyval.l) = List_Create(1, 1, sizeof(double));
    ;}
     break;
 
   case 233:
-#line 2915 "Gmsh.y"
+#line 2914 "Gmsh.y"
     {
      (yyval.l) = (yyvsp[(2) - (2)].l);
    ;}
     break;
 
   case 234:
-#line 2920 "Gmsh.y"
+#line 2919 "Gmsh.y"
     {
       (yyval.i) = 45;
     ;}
     break;
 
   case 235:
-#line 2924 "Gmsh.y"
+#line 2923 "Gmsh.y"
     {
       (yyval.i) = (int)(yyvsp[(2) - (2)].d);
     ;}
     break;
 
   case 236:
-#line 2931 "Gmsh.y"
+#line 2930 "Gmsh.y"
     {
       int type = (int)(yyvsp[(6) - (7)].v)[0];
       double coef = fabs((yyvsp[(6) - (7)].v)[1]);
@@ -7173,7 +7172,7 @@ yyreduce:
     break;
 
   case 237:
-#line 2987 "Gmsh.y"
+#line 2986 "Gmsh.y"
     {
       int k = List_Nbr((yyvsp[(4) - (6)].l));
       if(k != 0 && k != 3 && k != 4){
@@ -7246,7 +7245,7 @@ yyreduce:
     break;
 
   case 238:
-#line 3057 "Gmsh.y"
+#line 3056 "Gmsh.y"
     {
       yymsg(1, "Elliptic Surface is deprecated: use Transfinite instead (with smoothing)");
       List_Delete((yyvsp[(7) - (8)].l));
@@ -7254,7 +7253,7 @@ yyreduce:
     break;
 
   case 239:
-#line 3062 "Gmsh.y"
+#line 3061 "Gmsh.y"
     {
       int k = List_Nbr((yyvsp[(4) - (5)].l));
       if(k != 0 && k != 6 && k != 8){
@@ -7324,7 +7323,7 @@ yyreduce:
     break;
 
   case 240:
-#line 3129 "Gmsh.y"
+#line 3128 "Gmsh.y"
     {
       if(!(yyvsp[(3) - (5)].l)){
 	List_T *tmp = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
@@ -7370,7 +7369,7 @@ yyreduce:
     break;
 
   case 241:
-#line 3172 "Gmsh.y"
+#line 3171 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (6)].l)); i++){
 	double d;
@@ -7393,7 +7392,7 @@ yyreduce:
     break;
 
   case 242:
-#line 3198 "Gmsh.y"
+#line 3197 "Gmsh.y"
     { 
       Surface *s = FindSurface((int)(yyvsp[(8) - (10)].d));
       if(s){
@@ -7419,7 +7418,7 @@ yyreduce:
     break;
 
   case 243:
-#line 3221 "Gmsh.y"
+#line 3220 "Gmsh.y"
     {
       Surface *s = FindSurface((int)(yyvsp[(8) - (10)].d));
       if(s){
@@ -7445,26 +7444,26 @@ yyreduce:
     break;
 
   case 244:
-#line 3244 "Gmsh.y"
+#line 3243 "Gmsh.y"
     {
     ;}
     break;
 
   case 245:
-#line 3247 "Gmsh.y"
+#line 3246 "Gmsh.y"
     {
     ;}
     break;
 
   case 246:
-#line 3256 "Gmsh.y"
+#line 3255 "Gmsh.y"
     { 
       ReplaceAllDuplicates();
     ;}
     break;
 
   case 247:
-#line 3260 "Gmsh.y"
+#line 3259 "Gmsh.y"
     { 
       if(!strcmp((yyvsp[(2) - (3)].c), "Geometry"))
         ReplaceAllDuplicates();
@@ -7477,7 +7476,7 @@ yyreduce:
     break;
 
   case 248:
-#line 3277 "Gmsh.y"
+#line 3276 "Gmsh.y"
     {
     
     List_T *temp = ListOfDouble2ListOfInt((yyvsp[(3) - (7)].l));
@@ -7512,7 +7511,7 @@ yyreduce:
     break;
 
   case 249:
-#line 3310 "Gmsh.y"
+#line 3309 "Gmsh.y"
     {
     List_T *temp = ListOfDouble2ListOfInt((yyvsp[(7) - (11)].l));
     std::vector<int> domain;
@@ -7539,7 +7538,7 @@ yyreduce:
     
     #if defined(HAVE_KBIPACK)
     Homology* homology = new Homology(GModel::current(), domain, subdomain);
-    homology->findGenerators(fileName);
+    homology->findGenerators(fileName);  
     delete homology;
     #else
     yymsg(0, "Gmsh needs to be configured with option Kbipack to use homology computation.");
@@ -7548,7 +7547,7 @@ yyreduce:
     break;
 
   case 250:
-#line 3344 "Gmsh.y"
+#line 3343 "Gmsh.y"
     {
     List_T *temp = ListOfDouble2ListOfInt((yyvsp[(7) - (11)].l));
     std::vector<int> domain;
@@ -7584,47 +7583,47 @@ yyreduce:
     break;
 
   case 251:
-#line 3381 "Gmsh.y"
+#line 3380 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (1)].d);           ;}
     break;
 
   case 252:
-#line 3382 "Gmsh.y"
+#line 3381 "Gmsh.y"
     { (yyval.d) = (yyvsp[(2) - (3)].d);           ;}
     break;
 
   case 253:
-#line 3383 "Gmsh.y"
+#line 3382 "Gmsh.y"
     { (yyval.d) = -(yyvsp[(2) - (2)].d);          ;}
     break;
 
   case 254:
-#line 3384 "Gmsh.y"
+#line 3383 "Gmsh.y"
     { (yyval.d) = (yyvsp[(2) - (2)].d);           ;}
     break;
 
   case 255:
-#line 3385 "Gmsh.y"
+#line 3384 "Gmsh.y"
     { (yyval.d) = !(yyvsp[(2) - (2)].d);          ;}
     break;
 
   case 256:
-#line 3386 "Gmsh.y"
+#line 3385 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) - (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 257:
-#line 3387 "Gmsh.y"
+#line 3386 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) + (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 258:
-#line 3388 "Gmsh.y"
+#line 3387 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) * (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 259:
-#line 3390 "Gmsh.y"
+#line 3389 "Gmsh.y"
     { 
       if(!(yyvsp[(3) - (3)].d))
 	yymsg(0, "Division by zero in '%g / %g'", (yyvsp[(1) - (3)].d), (yyvsp[(3) - (3)].d));
@@ -7634,307 +7633,307 @@ yyreduce:
     break;
 
   case 260:
-#line 3396 "Gmsh.y"
+#line 3395 "Gmsh.y"
     { (yyval.d) = (int)(yyvsp[(1) - (3)].d) % (int)(yyvsp[(3) - (3)].d);  ;}
     break;
 
   case 261:
-#line 3397 "Gmsh.y"
+#line 3396 "Gmsh.y"
     { (yyval.d) = pow((yyvsp[(1) - (3)].d), (yyvsp[(3) - (3)].d));  ;}
     break;
 
   case 262:
-#line 3398 "Gmsh.y"
+#line 3397 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) < (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 263:
-#line 3399 "Gmsh.y"
+#line 3398 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) > (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 264:
-#line 3400 "Gmsh.y"
+#line 3399 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) <= (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 265:
-#line 3401 "Gmsh.y"
+#line 3400 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) >= (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 266:
-#line 3402 "Gmsh.y"
+#line 3401 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) == (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 267:
-#line 3403 "Gmsh.y"
+#line 3402 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) != (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 268:
-#line 3404 "Gmsh.y"
+#line 3403 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) && (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 269:
-#line 3405 "Gmsh.y"
+#line 3404 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) || (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 270:
-#line 3406 "Gmsh.y"
+#line 3405 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (5)].d) ? (yyvsp[(3) - (5)].d) : (yyvsp[(5) - (5)].d); ;}
     break;
 
   case 271:
-#line 3407 "Gmsh.y"
+#line 3406 "Gmsh.y"
     { (yyval.d) = exp((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 272:
-#line 3408 "Gmsh.y"
+#line 3407 "Gmsh.y"
     { (yyval.d) = log((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 273:
-#line 3409 "Gmsh.y"
+#line 3408 "Gmsh.y"
     { (yyval.d) = log10((yyvsp[(3) - (4)].d));    ;}
     break;
 
   case 274:
-#line 3410 "Gmsh.y"
+#line 3409 "Gmsh.y"
     { (yyval.d) = sqrt((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 275:
-#line 3411 "Gmsh.y"
+#line 3410 "Gmsh.y"
     { (yyval.d) = sin((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 276:
-#line 3412 "Gmsh.y"
+#line 3411 "Gmsh.y"
     { (yyval.d) = asin((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 277:
-#line 3413 "Gmsh.y"
+#line 3412 "Gmsh.y"
     { (yyval.d) = cos((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 278:
-#line 3414 "Gmsh.y"
+#line 3413 "Gmsh.y"
     { (yyval.d) = acos((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 279:
-#line 3415 "Gmsh.y"
+#line 3414 "Gmsh.y"
     { (yyval.d) = tan((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 280:
-#line 3416 "Gmsh.y"
+#line 3415 "Gmsh.y"
     { (yyval.d) = atan((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 281:
-#line 3417 "Gmsh.y"
+#line 3416 "Gmsh.y"
     { (yyval.d) = atan2((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d));;}
     break;
 
   case 282:
-#line 3418 "Gmsh.y"
+#line 3417 "Gmsh.y"
     { (yyval.d) = sinh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 283:
-#line 3419 "Gmsh.y"
+#line 3418 "Gmsh.y"
     { (yyval.d) = cosh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 284:
-#line 3420 "Gmsh.y"
+#line 3419 "Gmsh.y"
     { (yyval.d) = tanh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 285:
-#line 3421 "Gmsh.y"
+#line 3420 "Gmsh.y"
     { (yyval.d) = fabs((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 286:
-#line 3422 "Gmsh.y"
+#line 3421 "Gmsh.y"
     { (yyval.d) = floor((yyvsp[(3) - (4)].d));    ;}
     break;
 
   case 287:
-#line 3423 "Gmsh.y"
+#line 3422 "Gmsh.y"
     { (yyval.d) = ceil((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 288:
-#line 3424 "Gmsh.y"
+#line 3423 "Gmsh.y"
     { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 289:
-#line 3425 "Gmsh.y"
+#line 3424 "Gmsh.y"
     { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 290:
-#line 3426 "Gmsh.y"
+#line 3425 "Gmsh.y"
     { (yyval.d) = sqrt((yyvsp[(3) - (6)].d) * (yyvsp[(3) - (6)].d) + (yyvsp[(5) - (6)].d) * (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 291:
-#line 3427 "Gmsh.y"
+#line 3426 "Gmsh.y"
     { (yyval.d) = (yyvsp[(3) - (4)].d) * (double)rand() / (double)RAND_MAX; ;}
     break;
 
   case 292:
-#line 3429 "Gmsh.y"
+#line 3428 "Gmsh.y"
     { (yyval.d) = exp((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 293:
-#line 3430 "Gmsh.y"
+#line 3429 "Gmsh.y"
     { (yyval.d) = log((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 294:
-#line 3431 "Gmsh.y"
+#line 3430 "Gmsh.y"
     { (yyval.d) = log10((yyvsp[(3) - (4)].d));    ;}
     break;
 
   case 295:
-#line 3432 "Gmsh.y"
+#line 3431 "Gmsh.y"
     { (yyval.d) = sqrt((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 296:
-#line 3433 "Gmsh.y"
+#line 3432 "Gmsh.y"
     { (yyval.d) = sin((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 297:
-#line 3434 "Gmsh.y"
+#line 3433 "Gmsh.y"
     { (yyval.d) = asin((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 298:
-#line 3435 "Gmsh.y"
+#line 3434 "Gmsh.y"
     { (yyval.d) = cos((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 299:
-#line 3436 "Gmsh.y"
+#line 3435 "Gmsh.y"
     { (yyval.d) = acos((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 300:
-#line 3437 "Gmsh.y"
+#line 3436 "Gmsh.y"
     { (yyval.d) = tan((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 301:
-#line 3438 "Gmsh.y"
+#line 3437 "Gmsh.y"
     { (yyval.d) = atan((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 302:
-#line 3439 "Gmsh.y"
+#line 3438 "Gmsh.y"
     { (yyval.d) = atan2((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d));;}
     break;
 
   case 303:
-#line 3440 "Gmsh.y"
+#line 3439 "Gmsh.y"
     { (yyval.d) = sinh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 304:
-#line 3441 "Gmsh.y"
+#line 3440 "Gmsh.y"
     { (yyval.d) = cosh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 305:
-#line 3442 "Gmsh.y"
+#line 3441 "Gmsh.y"
     { (yyval.d) = tanh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 306:
-#line 3443 "Gmsh.y"
+#line 3442 "Gmsh.y"
     { (yyval.d) = fabs((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 307:
-#line 3444 "Gmsh.y"
+#line 3443 "Gmsh.y"
     { (yyval.d) = floor((yyvsp[(3) - (4)].d));    ;}
     break;
 
   case 308:
-#line 3445 "Gmsh.y"
+#line 3444 "Gmsh.y"
     { (yyval.d) = ceil((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 309:
-#line 3446 "Gmsh.y"
+#line 3445 "Gmsh.y"
     { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 310:
-#line 3447 "Gmsh.y"
+#line 3446 "Gmsh.y"
     { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 311:
-#line 3448 "Gmsh.y"
+#line 3447 "Gmsh.y"
     { (yyval.d) = sqrt((yyvsp[(3) - (6)].d) * (yyvsp[(3) - (6)].d) + (yyvsp[(5) - (6)].d) * (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 312:
-#line 3449 "Gmsh.y"
+#line 3448 "Gmsh.y"
     { (yyval.d) = (yyvsp[(3) - (4)].d) * (double)rand() / (double)RAND_MAX; ;}
     break;
 
   case 313:
-#line 3458 "Gmsh.y"
+#line 3457 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (1)].d); ;}
     break;
 
   case 314:
-#line 3459 "Gmsh.y"
+#line 3458 "Gmsh.y"
     { (yyval.d) = 3.141592653589793; ;}
     break;
 
   case 315:
-#line 3460 "Gmsh.y"
+#line 3459 "Gmsh.y"
     { (yyval.d) = Msg::GetCommRank(); ;}
     break;
 
   case 316:
-#line 3461 "Gmsh.y"
+#line 3460 "Gmsh.y"
     { (yyval.d) = Msg::GetCommSize(); ;}
     break;
 
   case 317:
-#line 3462 "Gmsh.y"
+#line 3461 "Gmsh.y"
     { (yyval.d) = GetGmshMajorVersion(); ;}
     break;
 
   case 318:
-#line 3463 "Gmsh.y"
+#line 3462 "Gmsh.y"
     { (yyval.d) = GetGmshMinorVersion(); ;}
     break;
 
   case 319:
-#line 3464 "Gmsh.y"
+#line 3463 "Gmsh.y"
     { (yyval.d) = GetGmshPatchVersion(); ;}
     break;
 
   case 320:
-#line 3469 "Gmsh.y"
+#line 3468 "Gmsh.y"
     {
       if(!gmsh_yysymbols.count((yyvsp[(1) - (1)].c))){
 	yymsg(0, "Unknown variable '%s'", (yyvsp[(1) - (1)].c));
@@ -7947,7 +7946,7 @@ yyreduce:
     break;
 
   case 321:
-#line 3482 "Gmsh.y"
+#line 3481 "Gmsh.y"
     {
       char tmpstring[1024];
       sprintf(tmpstring, "%s_%d", (yyvsp[(1) - (5)].c), (int)(yyvsp[(4) - (5)].d)) ;
@@ -7962,7 +7961,7 @@ yyreduce:
     break;
 
   case 322:
-#line 3494 "Gmsh.y"
+#line 3493 "Gmsh.y"
     {
       int index = (int)(yyvsp[(3) - (4)].d);
       if(!gmsh_yysymbols.count((yyvsp[(1) - (4)].c))){
@@ -7980,7 +7979,7 @@ yyreduce:
     break;
 
   case 323:
-#line 3509 "Gmsh.y"
+#line 3508 "Gmsh.y"
     {
       if(!gmsh_yysymbols.count((yyvsp[(2) - (4)].c))){
 	yymsg(0, "Unknown variable '%s'", (yyvsp[(2) - (4)].c));
@@ -7993,7 +7992,7 @@ yyreduce:
     break;
 
   case 324:
-#line 3519 "Gmsh.y"
+#line 3518 "Gmsh.y"
     {
       if(!gmsh_yysymbols.count((yyvsp[(1) - (2)].c))){
 	yymsg(0, "Unknown variable '%s'", (yyvsp[(1) - (2)].c));
@@ -8006,7 +8005,7 @@ yyreduce:
     break;
 
   case 325:
-#line 3529 "Gmsh.y"
+#line 3528 "Gmsh.y"
     {
       int index = (int)(yyvsp[(3) - (5)].d);
       if(!gmsh_yysymbols.count((yyvsp[(1) - (5)].c))){
@@ -8024,7 +8023,7 @@ yyreduce:
     break;
 
   case 326:
-#line 3547 "Gmsh.y"
+#line 3546 "Gmsh.y"
     {
       NumberOption(GMSH_GET, (yyvsp[(1) - (3)].c), 0, (yyvsp[(3) - (3)].c), (yyval.d));
       Free((yyvsp[(1) - (3)].c)); Free((yyvsp[(3) - (3)].c));
@@ -8032,7 +8031,7 @@ yyreduce:
     break;
 
   case 327:
-#line 3552 "Gmsh.y"
+#line 3551 "Gmsh.y"
     {
       NumberOption(GMSH_GET, (yyvsp[(1) - (6)].c), (int)(yyvsp[(3) - (6)].d), (yyvsp[(6) - (6)].c), (yyval.d));
       Free((yyvsp[(1) - (6)].c)); Free((yyvsp[(6) - (6)].c));
@@ -8040,7 +8039,7 @@ yyreduce:
     break;
 
   case 328:
-#line 3557 "Gmsh.y"
+#line 3556 "Gmsh.y"
     {
       double d = 0.;
       if(NumberOption(GMSH_GET, (yyvsp[(1) - (4)].c), 0, (yyvsp[(3) - (4)].c), d)){
@@ -8053,7 +8052,7 @@ yyreduce:
     break;
 
   case 329:
-#line 3567 "Gmsh.y"
+#line 3566 "Gmsh.y"
     {
       double d = 0.;
       if(NumberOption(GMSH_GET, (yyvsp[(1) - (7)].c), (int)(yyvsp[(3) - (7)].d), (yyvsp[(6) - (7)].c), d)){
@@ -8066,7 +8065,7 @@ yyreduce:
     break;
 
   case 330:
-#line 3577 "Gmsh.y"
+#line 3576 "Gmsh.y"
     { 
       (yyval.d) = Msg::GetValue((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].d));
       Free((yyvsp[(3) - (6)].c));
@@ -8074,70 +8073,70 @@ yyreduce:
     break;
 
   case 331:
-#line 3585 "Gmsh.y"
+#line 3584 "Gmsh.y"
     {
       memcpy((yyval.v), (yyvsp[(1) - (1)].v), 5*sizeof(double));
     ;}
     break;
 
   case 332:
-#line 3589 "Gmsh.y"
+#line 3588 "Gmsh.y"
     {
       for(int i = 0; i < 5; i++) (yyval.v)[i] = -(yyvsp[(2) - (2)].v)[i];
     ;}
     break;
 
   case 333:
-#line 3593 "Gmsh.y"
+#line 3592 "Gmsh.y"
     { 
       for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(2) - (2)].v)[i];
     ;}
     break;
 
   case 334:
-#line 3597 "Gmsh.y"
+#line 3596 "Gmsh.y"
     { 
       for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(1) - (3)].v)[i] - (yyvsp[(3) - (3)].v)[i];
     ;}
     break;
 
   case 335:
-#line 3601 "Gmsh.y"
+#line 3600 "Gmsh.y"
     {
       for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(1) - (3)].v)[i] + (yyvsp[(3) - (3)].v)[i];
     ;}
     break;
 
   case 336:
-#line 3608 "Gmsh.y"
+#line 3607 "Gmsh.y"
     { 
       (yyval.v)[0] = (yyvsp[(2) - (11)].d);  (yyval.v)[1] = (yyvsp[(4) - (11)].d);  (yyval.v)[2] = (yyvsp[(6) - (11)].d);  (yyval.v)[3] = (yyvsp[(8) - (11)].d); (yyval.v)[4] = (yyvsp[(10) - (11)].d);
     ;}
     break;
 
   case 337:
-#line 3612 "Gmsh.y"
+#line 3611 "Gmsh.y"
     { 
       (yyval.v)[0] = (yyvsp[(2) - (9)].d);  (yyval.v)[1] = (yyvsp[(4) - (9)].d);  (yyval.v)[2] = (yyvsp[(6) - (9)].d);  (yyval.v)[3] = (yyvsp[(8) - (9)].d); (yyval.v)[4] = 1.0;
     ;}
     break;
 
   case 338:
-#line 3616 "Gmsh.y"
+#line 3615 "Gmsh.y"
     {
       (yyval.v)[0] = (yyvsp[(2) - (7)].d);  (yyval.v)[1] = (yyvsp[(4) - (7)].d);  (yyval.v)[2] = (yyvsp[(6) - (7)].d);  (yyval.v)[3] = 0.0; (yyval.v)[4] = 1.0;
     ;}
     break;
 
   case 339:
-#line 3620 "Gmsh.y"
+#line 3619 "Gmsh.y"
     {
       (yyval.v)[0] = (yyvsp[(2) - (7)].d);  (yyval.v)[1] = (yyvsp[(4) - (7)].d);  (yyval.v)[2] = (yyvsp[(6) - (7)].d);  (yyval.v)[3] = 0.0; (yyval.v)[4] = 1.0;
     ;}
     break;
 
   case 340:
-#line 3627 "Gmsh.y"
+#line 3626 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(List_T*));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].l)));
@@ -8145,14 +8144,14 @@ yyreduce:
     break;
 
   case 341:
-#line 3632 "Gmsh.y"
+#line 3631 "Gmsh.y"
     {
       List_Add((yyval.l), &((yyvsp[(3) - (3)].l)));
     ;}
     break;
 
   case 342:
-#line 3639 "Gmsh.y"
+#line 3638 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].d)));
@@ -8160,14 +8159,14 @@ yyreduce:
     break;
 
   case 343:
-#line 3644 "Gmsh.y"
+#line 3643 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(1) - (1)].l);
     ;}
     break;
 
   case 344:
-#line 3648 "Gmsh.y"
+#line 3647 "Gmsh.y"
     {
       // creates an empty list
       (yyval.l) = List_Create(2, 1, sizeof(double));
@@ -8175,14 +8174,14 @@ yyreduce:
     break;
 
   case 345:
-#line 3653 "Gmsh.y"
+#line 3652 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(2) - (3)].l);
     ;}
     break;
 
   case 346:
-#line 3657 "Gmsh.y"
+#line 3656 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(3) - (4)].l);
       for(int i = 0; i < List_Nbr((yyval.l)); i++){
@@ -8193,7 +8192,7 @@ yyreduce:
     break;
 
   case 347:
-#line 3665 "Gmsh.y"
+#line 3664 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(4) - (5)].l);
       for(int i = 0; i < List_Nbr((yyval.l)); i++){
@@ -8204,14 +8203,14 @@ yyreduce:
     break;
 
   case 348:
-#line 3676 "Gmsh.y"
+#line 3675 "Gmsh.y"
     { 
       (yyval.l) = (yyvsp[(1) - (1)].l); 
     ;}
     break;
 
   case 349:
-#line 3680 "Gmsh.y"
+#line 3679 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(1) - (1)].c), "*") || !strcmp((yyvsp[(1) - (1)].c), "all"))
         (yyval.l) = 0;
@@ -8223,7 +8222,7 @@ yyreduce:
     break;
 
   case 350:
-#line 3692 "Gmsh.y"
+#line 3691 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(2) - (2)].l);
       for(int i = 0; i < List_Nbr((yyval.l)); i++){
@@ -8234,7 +8233,7 @@ yyreduce:
     break;
 
   case 351:
-#line 3700 "Gmsh.y"
+#line 3699 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(3) - (3)].l);
       for(int i = 0; i < List_Nbr((yyval.l)); i++){
@@ -8245,7 +8244,7 @@ yyreduce:
     break;
 
   case 352:
-#line 3708 "Gmsh.y"
+#line 3707 "Gmsh.y"
     { 
       (yyval.l) = List_Create(2, 1, sizeof(double)); 
       for(double d = (yyvsp[(1) - (3)].d); ((yyvsp[(1) - (3)].d) < (yyvsp[(3) - (3)].d)) ? (d <= (yyvsp[(3) - (3)].d)) : (d >= (yyvsp[(3) - (3)].d)); 
@@ -8255,7 +8254,7 @@ yyreduce:
     break;
 
   case 353:
-#line 3715 "Gmsh.y"
+#line 3714 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double)); 
       if(!(yyvsp[(5) - (5)].d) || ((yyvsp[(1) - (5)].d) < (yyvsp[(3) - (5)].d) && (yyvsp[(5) - (5)].d) < 0) || ((yyvsp[(1) - (5)].d) > (yyvsp[(3) - (5)].d) && (yyvsp[(5) - (5)].d) > 0)){
@@ -8269,7 +8268,7 @@ yyreduce:
     break;
 
   case 354:
-#line 3726 "Gmsh.y"
+#line 3725 "Gmsh.y"
     {
       // Returns the coordinates of a point and fills a list with it.
       // This allows to ensure e.g. that relative point positions are
@@ -8292,7 +8291,7 @@ yyreduce:
     break;
 
   case 355:
-#line 3746 "Gmsh.y"
+#line 3745 "Gmsh.y"
     {
       (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double));
       for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){
@@ -8305,7 +8304,7 @@ yyreduce:
     break;
 
   case 356:
-#line 3756 "Gmsh.y"
+#line 3755 "Gmsh.y"
     {
       (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double));
       for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){
@@ -8318,7 +8317,7 @@ yyreduce:
     break;
 
   case 357:
-#line 3766 "Gmsh.y"
+#line 3765 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       if(!gmsh_yysymbols.count((yyvsp[(1) - (3)].c)))
@@ -8331,7 +8330,7 @@ yyreduce:
     break;
 
   case 358:
-#line 3776 "Gmsh.y"
+#line 3775 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       if(!gmsh_yysymbols.count((yyvsp[(1) - (6)].c)))
@@ -8351,7 +8350,7 @@ yyreduce:
     break;
 
   case 359:
-#line 3796 "Gmsh.y"
+#line 3795 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].d)));
@@ -8359,21 +8358,21 @@ yyreduce:
     break;
 
   case 360:
-#line 3801 "Gmsh.y"
+#line 3800 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(1) - (1)].l);
     ;}
     break;
 
   case 361:
-#line 3805 "Gmsh.y"
+#line 3804 "Gmsh.y"
     {
       List_Add((yyval.l), &((yyvsp[(3) - (3)].d)));
     ;}
     break;
 
   case 362:
-#line 3809 "Gmsh.y"
+#line 3808 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (3)].l)); i++){
 	double d;
@@ -8385,21 +8384,21 @@ yyreduce:
     break;
 
   case 363:
-#line 3821 "Gmsh.y"
+#line 3820 "Gmsh.y"
     {
       (yyval.u) = CTX::instance()->packColor((int)(yyvsp[(2) - (9)].d), (int)(yyvsp[(4) - (9)].d), (int)(yyvsp[(6) - (9)].d), (int)(yyvsp[(8) - (9)].d));
     ;}
     break;
 
   case 364:
-#line 3825 "Gmsh.y"
+#line 3824 "Gmsh.y"
     {
       (yyval.u) = CTX::instance()->packColor((int)(yyvsp[(2) - (7)].d), (int)(yyvsp[(4) - (7)].d), (int)(yyvsp[(6) - (7)].d), 255);
     ;}
     break;
 
   case 365:
-#line 3837 "Gmsh.y"
+#line 3836 "Gmsh.y"
     {
       int flag;
       (yyval.u) = GetColorForString(ColorString, -1, (yyvsp[(1) - (1)].c), &flag);
@@ -8409,7 +8408,7 @@ yyreduce:
     break;
 
   case 366:
-#line 3844 "Gmsh.y"
+#line 3843 "Gmsh.y"
     {
       unsigned int val = 0;
       ColorOption(GMSH_GET, (yyvsp[(1) - (5)].c), 0, (yyvsp[(5) - (5)].c), val);
@@ -8419,14 +8418,14 @@ yyreduce:
     break;
 
   case 367:
-#line 3854 "Gmsh.y"
+#line 3853 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(2) - (3)].l);
     ;}
     break;
 
   case 368:
-#line 3858 "Gmsh.y"
+#line 3857 "Gmsh.y"
     {
       (yyval.l) = List_Create(256, 10, sizeof(unsigned int));
       GmshColorTable *ct = GetColorTable((int)(yyvsp[(3) - (6)].d));
@@ -8441,7 +8440,7 @@ yyreduce:
     break;
 
   case 369:
-#line 3873 "Gmsh.y"
+#line 3872 "Gmsh.y"
     {
       (yyval.l) = List_Create(256, 10, sizeof(unsigned int));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].u)));
@@ -8449,21 +8448,21 @@ yyreduce:
     break;
 
   case 370:
-#line 3878 "Gmsh.y"
+#line 3877 "Gmsh.y"
     {
       List_Add((yyval.l), &((yyvsp[(3) - (3)].u)));
     ;}
     break;
 
   case 371:
-#line 3885 "Gmsh.y"
+#line 3884 "Gmsh.y"
     {
       (yyval.c) = (yyvsp[(1) - (1)].c);
     ;}
     break;
 
   case 372:
-#line 3889 "Gmsh.y"
+#line 3888 "Gmsh.y"
     {
       if(!gmsh_yystringsymbols.count((yyvsp[(1) - (1)].c))){
 	yymsg(0, "Unknown string variable '%s'", (yyvsp[(1) - (1)].c));
@@ -8479,7 +8478,7 @@ yyreduce:
     break;
 
   case 373:
-#line 3902 "Gmsh.y"
+#line 3901 "Gmsh.y"
     { 
       std::string out;
       StringOption(GMSH_GET, (yyvsp[(1) - (3)].c), 0, (yyvsp[(3) - (3)].c), out);
@@ -8490,7 +8489,7 @@ yyreduce:
     break;
 
   case 374:
-#line 3910 "Gmsh.y"
+#line 3909 "Gmsh.y"
     { 
       std::string out;
       StringOption(GMSH_GET, (yyvsp[(1) - (6)].c), (int)(yyvsp[(3) - (6)].d), (yyvsp[(6) - (6)].c), out);
@@ -8501,14 +8500,14 @@ yyreduce:
     break;
 
   case 375:
-#line 3921 "Gmsh.y"
+#line 3920 "Gmsh.y"
     {
       (yyval.c) = (yyvsp[(1) - (1)].c);
     ;}
     break;
 
   case 376:
-#line 3925 "Gmsh.y"
+#line 3924 "Gmsh.y"
     {
       (yyval.c) = (char *)Malloc(32 * sizeof(char));
       time_t now;
@@ -8519,7 +8518,7 @@ yyreduce:
     break;
 
   case 377:
-#line 3933 "Gmsh.y"
+#line 3932 "Gmsh.y"
     {
       (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (6)].c)) + strlen((yyvsp[(5) - (6)].c)) + 1) * sizeof(char));
       strcpy((yyval.c), (yyvsp[(3) - (6)].c));
@@ -8530,7 +8529,7 @@ yyreduce:
     break;
 
   case 378:
-#line 3941 "Gmsh.y"
+#line 3940 "Gmsh.y"
     {
       (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char));
       int i;
@@ -8547,7 +8546,7 @@ yyreduce:
     break;
 
   case 379:
-#line 3955 "Gmsh.y"
+#line 3954 "Gmsh.y"
     {
       (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char));
       int i;
@@ -8564,14 +8563,14 @@ yyreduce:
     break;
 
   case 380:
-#line 3969 "Gmsh.y"
+#line 3968 "Gmsh.y"
     {
       (yyval.c) = (yyvsp[(3) - (4)].c);
     ;}
     break;
 
   case 381:
-#line 3973 "Gmsh.y"
+#line 3972 "Gmsh.y"
     {
       char tmpstring[1024];
       int i = PrintListOfDouble((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].l), tmpstring);
@@ -8594,7 +8593,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 8598 "Gmsh.tab.cpp"
+#line 8597 "Gmsh.tab.cpp"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -8808,7 +8807,7 @@ yyreturn:
 }
 
 
-#line 3993 "Gmsh.y"
+#line 3992 "Gmsh.y"
 
 
 int PrintListOfDouble(char *format, List_T *list, char *buffer)
diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y
index dd1cf5962c28f125a76e5e18ee03e20795a85955..9f2963c5c168a8bb86b2fc479dffb3e977d932f1 100644
--- a/Parser/Gmsh.y
+++ b/Parser/Gmsh.y
@@ -1459,80 +1459,79 @@ Shape :
   | tCompound tVolume '(' FExpr ')' tAFFECT ListOfDouble tEND
     {
       int num = (int)$4;
-      if(FindPhysicalGroup(num, MSH_PHYSICAL_VOLUME)){
-	yymsg(0, "Physical volume %d already exists", num);
+      if(FindVolume(num)){
+	yymsg(0, "Volume %d already exists", num);
       }
       else{
-	List_T *temp = ListOfDouble2ListOfInt($7);
-	List_T *S[4] = {temp, 0, 0, 0};
-	PhysicalGroup *p = Create_PhysicalGroup(num, MSH_PHYSICAL_VOLUME, temp, S);
-	List_Delete(temp);
-        List_Add(GModel::current()->getGEOInternals()->PhysicalGroups, &p);
+	Volume *v = Create_Volume(num, MSH_VOLUME_COMPOUND);
+        for(int i = 0; i < List_Nbr($7); i++)
+          v->compound.push_back((int)*(double*)List_Pointer($7, i));
+	Tree_Add(GModel::current()->getGEOInternals()->Volumes, &v);
       }
       List_Delete($7);
-      $$.Type = MSH_PHYSICAL_VOLUME;
+      $$.Type = MSH_VOLUME_COMPOUND;
       $$.Num = num;
     }
   | tCompound tSurface '(' FExpr ')' tAFFECT ListOfDouble tSTRING 
       '{' RecursiveListOfListOfDouble '}' tEND
     {
       int num = (int)$4;
-      if(FindPhysicalGroup(num, MSH_PHYSICAL_SURFACE)){
-	yymsg(0, "Physical surface %d already exists", num);
+      if(FindSurface(num)){
+	yymsg(0, "Surface %d already exists", num);
       }
       else{
-	List_T *temp = ListOfDouble2ListOfInt($7);
-	List_T *S[4] = {0, 0, 0, 0};
+        Surface *s = Create_Surface(num, MSH_SURF_COMPOUND);
+        for(int i = 0; i < List_Nbr($7); i++)
+          s->compound.push_back((int)*(double*)List_Pointer($7, i));
 	for (int i = 0; i < List_Nbr($10); i++){
-	  List_T *ll;
-	  List_Read($10, i, &ll);
-	  S[i] = ListOfDouble2ListOfInt(ll);
-          List_Delete(ll);
+          if(i > 3){
+            yymsg(0, "Too many boundary specifiers in compound surface");
+            break;
+          }
+	  List_T *l = *(List_T**)List_Pointer($10, i);
+          for (int j = 0; j < List_Nbr(l); j++)
+            s->compoundBoundary[i].push_back((int)*(double*)List_Pointer(l, j));
 	}
-	PhysicalGroup *p = Create_PhysicalGroup(num, MSH_PHYSICAL_SURFACE, temp, S);
-	List_Delete(temp);
-	for (int i = 0; i < List_Nbr($10); i++)
-	  List_Delete(S[i]);
-        List_Add(GModel::current()->getGEOInternals()->PhysicalGroups, &p);
+	Tree_Add(GModel::current()->getGEOInternals()->Surfaces, &s);
       }
       List_Delete($7);
+      for (int i = 0; i < List_Nbr($10); i++)
+        List_Delete(*(List_T**)List_Pointer($10, i));
       List_Delete($10);
       Free($8);
-      $$.Type = MSH_PHYSICAL_SURFACE;
+      $$.Type = MSH_SURF_COMPOUND;
       $$.Num = num;
     }
-    | tCompound tSurface '(' FExpr ')' tAFFECT ListOfDouble tEND
+  | tCompound tSurface '(' FExpr ')' tAFFECT ListOfDouble tEND
     {
       int num = (int)$4;
-      if(FindPhysicalGroup(num, MSH_PHYSICAL_SURFACE)){
-	yymsg(0, "Physical surface %d already exists", num);
+      if(FindSurface(num)){
+	yymsg(0, "Surface %d already exists", num);
       }
       else{
-	List_T *temp = ListOfDouble2ListOfInt($7);
-	List_T *S[4] = {0, 0, 0, 0};
-	PhysicalGroup *p = Create_PhysicalGroup(num, MSH_PHYSICAL_SURFACE, temp, S);
-	List_Delete(temp);
-	List_Add(GModel::current()->getGEOInternals()->PhysicalGroups, &p);
+        Surface *s = Create_Surface(num, MSH_SURF_COMPOUND);
+        for(int i = 0; i < List_Nbr($7); i++)
+          s->compound.push_back((int)*(double*)List_Pointer($7, i));
+	Tree_Add(GModel::current()->getGEOInternals()->Surfaces, &s);
       }
       List_Delete($7);
-      $$.Type = MSH_PHYSICAL_SURFACE;
+      $$.Type = MSH_SURF_COMPOUND;
       $$.Num = num;
     }
-    | tCompound tLine '(' FExpr ')' tAFFECT ListOfDouble tEND
+  | tCompound tLine '(' FExpr ')' tAFFECT ListOfDouble tEND
     {
       int num = (int)$4;
-      if(FindPhysicalGroup(num, MSH_PHYSICAL_LINE)){
-	yymsg(0, "Physical line %d already exists", num);
+      if(FindCurve(num)){
+	yymsg(0, "Curve %d already exists", num);
       }
       else{
-	List_T *temp = ListOfDouble2ListOfInt($7);
-	List_T *S[4] = {temp, 0, 0, 0};
-	PhysicalGroup *p = Create_PhysicalGroup(num, MSH_PHYSICAL_LINE, temp, S);
-	List_Delete(temp);
-	List_Add(GModel::current()->getGEOInternals()->PhysicalGroups, &p);
+        Curve *c = Create_Curve(num, MSH_SEGM_COMPOUND, 1, NULL, NULL, -1, -1, 0., 1.);
+        for(int i = 0; i < List_Nbr($7); i++)
+          c->compound.push_back((int)*(double*)List_Pointer($7, i));
+	Tree_Add(GModel::current()->getGEOInternals()->Curves, &c);
       }
       List_Delete($7);
-      $$.Type = MSH_PHYSICAL_LINE;
+      $$.Type = MSH_SEGM_COMPOUND;
       $$.Num = num;
     }
 
diff --git a/Parser/Gmsh.yy.cpp b/Parser/Gmsh.yy.cpp
index aa4102361bf1774498929a06948b1e892c6b4aa6..abb57f38cd569844f77a5479dc0dd3de1eb3b258 100644
--- a/Parser/Gmsh.yy.cpp
+++ b/Parser/Gmsh.yy.cpp
@@ -6,10 +6,29 @@
 
 /* A lexical scanner generated by flex */
 
+#define yy_create_buffer gmsh_yy_create_buffer
+#define yy_delete_buffer gmsh_yy_delete_buffer
+#define yy_flex_debug gmsh_yy_flex_debug
+#define yy_init_buffer gmsh_yy_init_buffer
+#define yy_flush_buffer gmsh_yy_flush_buffer
+#define yy_load_buffer_state gmsh_yy_load_buffer_state
+#define yy_switch_to_buffer gmsh_yy_switch_to_buffer
+#define yyin gmsh_yyin
+#define yyleng gmsh_yyleng
+#define yylex gmsh_yylex
+#define yylineno gmsh_yylineno
+#define yyout gmsh_yyout
+#define yyrestart gmsh_yyrestart
+#define yytext gmsh_yytext
+#define yywrap gmsh_yywrap
+#define yyalloc gmsh_yyalloc
+#define yyrealloc gmsh_yyrealloc
+#define yyfree gmsh_yyfree
+
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 33
+#define YY_FLEX_SUBMINOR_VERSION 35
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -31,7 +50,7 @@
 
 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
-#if __STDC_VERSION__ >= 199901L
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 
 /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
  * if you want the limit (max/min) macros for int types. 
@@ -94,11 +113,12 @@ typedef unsigned int flex_uint32_t;
 
 #else	/* ! __cplusplus */
 
-#if __STDC__
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
 
 #define YY_USE_CONST
 
-#endif	/* __STDC__ */
+#endif	/* defined (__STDC__) */
 #endif	/* ! __cplusplus */
 
 #ifdef YY_USE_CONST
@@ -152,7 +172,12 @@ typedef unsigned int flex_uint32_t;
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
 #endif
 
-extern int gmsh_yyleng;
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern yy_size_t gmsh_yyleng;
 
 extern FILE *gmsh_yyin, *gmsh_yyout;
 
@@ -178,16 +203,6 @@ extern FILE *gmsh_yyin, *gmsh_yyout;
 
 #define unput(c) yyunput( c, (yytext_ptr)  )
 
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
-#endif
-
 #ifndef YY_STRUCT_YY_BUFFER_STATE
 #define YY_STRUCT_YY_BUFFER_STATE
 struct yy_buffer_state
@@ -205,7 +220,7 @@ struct yy_buffer_state
 	/* Number of characters read into yy_ch_buf, not including EOB
 	 * characters.
 	 */
-	int yy_n_chars;
+	yy_size_t yy_n_chars;
 
 	/* Whether we "own" the buffer - i.e., we know we created it,
 	 * and can realloc() it to grow it, and should free() it to
@@ -275,8 +290,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
 
 /* yy_hold_char holds the character lost when gmsh_yytext is formed. */
 static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int gmsh_yyleng;
+static yy_size_t yy_n_chars;		/* number of characters read into yy_ch_buf */
+yy_size_t gmsh_yyleng;
 
 /* Points to current character in buffer. */
 static char *yy_c_buf_p = (char *) 0;
@@ -304,7 +319,7 @@ static void gmsh_yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
 
 YY_BUFFER_STATE gmsh_yy_scan_buffer (char *base,yy_size_t size  );
 YY_BUFFER_STATE gmsh_yy_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE gmsh_yy_scan_bytes (yyconst char *bytes,int len  );
+YY_BUFFER_STATE gmsh_yy_scan_bytes (yyconst char *bytes,yy_size_t len  );
 
 void *gmsh_yyalloc (yy_size_t  );
 void *gmsh_yyrealloc (void *,yy_size_t  );
@@ -888,7 +903,7 @@ void   skipline(void);
 #define YY_NO_UNISTD_H
 #endif
 
-#line 892 "Gmsh.yy.cpp"
+#line 907 "Gmsh.yy.cpp"
 
 #define INITIAL 0
 
@@ -906,6 +921,35 @@ void   skipline(void);
 
 static int yy_init_globals (void );
 
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int gmsh_yylex_destroy (void );
+
+int gmsh_yyget_debug (void );
+
+void gmsh_yyset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE gmsh_yyget_extra (void );
+
+void gmsh_yyset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *gmsh_yyget_in (void );
+
+void gmsh_yyset_in  (FILE * in_str  );
+
+FILE *gmsh_yyget_out (void );
+
+void gmsh_yyset_out  (FILE * out_str  );
+
+yy_size_t gmsh_yyget_leng (void );
+
+char *gmsh_yyget_text (void );
+
+int gmsh_yyget_lineno (void );
+
+void gmsh_yyset_lineno (int line_number  );
+
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  */
@@ -948,7 +992,7 @@ static int input (void );
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO (void) fwrite( gmsh_yytext, gmsh_yyleng, 1, gmsh_yyout )
+#define ECHO fwrite( gmsh_yytext, gmsh_yyleng, 1, gmsh_yyout )
 #endif
 
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
@@ -959,7 +1003,7 @@ static int input (void );
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		size_t n; \
+		yy_size_t n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( gmsh_yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -1044,7 +1088,7 @@ YY_DECL
 #line 49 "Gmsh.l"
 
 
-#line 1048 "Gmsh.yy.cpp"
+#line 1092 "Gmsh.yy.cpp"
 
 	if ( !(yy_init) )
 		{
@@ -1869,7 +1913,7 @@ YY_RULE_SETUP
 #line 224 "Gmsh.l"
 ECHO;
 	YY_BREAK
-#line 1873 "Gmsh.yy.cpp"
+#line 1917 "Gmsh.yy.cpp"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -2055,7 +2099,7 @@ static int yy_get_next_buffer (void)
 
 	else
 		{
-			int num_to_read =
+			yy_size_t num_to_read =
 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
 		while ( num_to_read <= 0 )
@@ -2069,7 +2113,7 @@ static int yy_get_next_buffer (void)
 
 			if ( b->yy_is_our_buffer )
 				{
-				int new_size = b->yy_buf_size * 2;
+				yy_size_t new_size = b->yy_buf_size * 2;
 
 				if ( new_size <= 0 )
 					b->yy_buf_size += b->yy_buf_size / 8;
@@ -2124,6 +2168,14 @@ static int yy_get_next_buffer (void)
 	else
 		ret_val = EOB_ACT_CONTINUE_SCAN;
 
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) gmsh_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
 	(yy_n_chars) += number_to_move;
 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
@@ -2202,7 +2254,7 @@ static int yy_get_next_buffer (void)
 	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
 		{ /* need to shift things up to make room */
 		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
+		register yy_size_t number_to_move = (yy_n_chars) + 2;
 		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
 					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
 		register char *source =
@@ -2251,7 +2303,7 @@ static int yy_get_next_buffer (void)
 
 		else
 			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
+			yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
 			++(yy_c_buf_p);
 
 			switch ( yy_get_next_buffer(  ) )
@@ -2527,7 +2579,7 @@ void gmsh_yypop_buffer_state (void)
  */
 static void gmsh_yyensure_buffer_stack (void)
 {
-	int num_to_alloc;
+	yy_size_t num_to_alloc;
     
 	if (!(yy_buffer_stack)) {
 
@@ -2539,7 +2591,9 @@ static void gmsh_yyensure_buffer_stack (void)
 		(yy_buffer_stack) = (struct yy_buffer_state**)gmsh_yyalloc
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
 								);
-		
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in gmsh_yyensure_buffer_stack()" );
+								  
 		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
 				
 		(yy_buffer_stack_max) = num_to_alloc;
@@ -2557,6 +2611,8 @@ static void gmsh_yyensure_buffer_stack (void)
 								((yy_buffer_stack),
 								num_to_alloc * sizeof(struct yy_buffer_state*)
 								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in gmsh_yyensure_buffer_stack()" );
 
 		/* zero only the new slots.*/
 		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -2601,7 +2657,7 @@ YY_BUFFER_STATE gmsh_yy_scan_buffer  (char * base, yy_size_t  size )
 
 /** Setup the input buffer state to scan a string. The next call to gmsh_yylex() will
  * scan from a @e copy of @a str.
- * @param str a NUL-terminated string to scan
+ * @param yystr a NUL-terminated string to scan
  * 
  * @return the newly allocated buffer state object.
  * @note If you want to scan bytes that may contain NUL values, then use
@@ -2620,12 +2676,11 @@ YY_BUFFER_STATE gmsh_yy_scan_string (yyconst char * yystr )
  * 
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE gmsh_yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+YY_BUFFER_STATE gmsh_yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len )
 {
 	YY_BUFFER_STATE b;
 	char *buf;
-	yy_size_t n;
-	int i;
+	yy_size_t n, i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
 	n = _yybytes_len + 2;
@@ -2707,7 +2762,7 @@ FILE *gmsh_yyget_out  (void)
 /** Get the length of the current token.
  * 
  */
-int gmsh_yyget_leng  (void)
+yy_size_t gmsh_yyget_leng  (void)
 {
         return gmsh_yyleng;
 }
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index a36bcf915891ecadb2d428010816c8dd96c69ab0..fae66e96b4aabd548dc3467c96316c512d9c01d3 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -4871,7 +4871,7 @@ libraries. See @ref{License} for more information.
 Nothing... The name was derived from a previous version called ``msh''
 (a shortcut for ``mesh''), with the ``g'' prefix added to differentiate
 it. The default mesh file format used by Gmsh still uses the @file{.msh}
-extention.
+extension.
 
 In English people tend to pronounce `Gmsh' as ``gee-mesh''.