Select Git revision
Forked from
gmsh / gmsh
Source project has a limited visibility.
-
Patrick Dular authoredPatrick Dular authored
Gmsh.y 199.93 KiB
%{
// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to the public mailing list <gmsh@onelab.info>.
#include <sstream>
#include <map>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include "GmshConfig.h"
#include "GmshMessage.h"
#include "fullMatrix.h"
#include "MallocUtils.h"
#include "ListUtils.h"
#include "TreeUtils.h"
#include "StringUtils.h"
#include "Numeric.h"
#include "Context.h"
#include "GModel.h"
#include "GModelIO_GEO.h"
#include "GModelIO_OCC.h"
#include "GeoDefines.h"
#include "ExtrudeParams.h"
#include "Options.h"
#include "Parser.h"
#include "OpenFile.h"
#include "CommandLine.h"
#include "FunctionManager.h"
#include "ColorTable.h"
#include "OS.h"
#include "CreateFile.h"
#include "gmshSurface.h"
#include "gmshLevelset.h"
#include "fullMatrix.h"
#if defined(HAVE_MESH)
#include "Generator.h"
#include "Field.h"
#include "BackgroundMesh.h"
#include "HighOrder.h"
#endif
#if defined(HAVE_POST)
#include "PView.h"
#include "PViewDataList.h"
#endif
#if defined(HAVE_PLUGINS)
#include "PluginManager.h"
#endif
#if defined(HAVE_OPENGL)
#include "drawContext.h"
#endif
#if defined(HAVE_POPPLER)
#include "gmshPopplerWrapper.h"
#endif
#define MAX_RECUR_TESTS 100
#define MAX_RECUR_LOOPS 100
// global parser variables
std::string gmsh_yyname;
int gmsh_yyerrorstate = 0;
int gmsh_yyviewindex = 0;
std::map<std::string, gmsh_yysymbol> gmsh_yysymbols;
std::map<std::string, std::vector<std::string> > gmsh_yystringsymbols;
// static parser variables (accessible only in this file)
#if defined(HAVE_POST)
static PViewDataList *ViewData = 0;
#endif
static std::vector<double> ViewCoord;
static std::vector<double> *ViewValueList = 0;
static int *ViewNumList = 0;
static ExtrudeParams extr;
static gmshSurface *myGmshSurface = 0;
static int statusImbricatedTests[MAX_RECUR_TESTS];
static int ImbricatedLoop = 0, ImbricatedTest = 0;
static gmshfpos_t yyposImbricatedLoopsTab[MAX_RECUR_LOOPS];
static int yylinenoImbricatedLoopsTab[MAX_RECUR_LOOPS];
static double LoopControlVariablesTab[MAX_RECUR_LOOPS][3];
static std::string LoopControlVariablesNameTab[MAX_RECUR_LOOPS];
static std::string factory;
static NameSpaces nameSpaces;
static std::string struct_name, struct_namespace;
static int flag_tSTRING_alloc = 0;
static std::map<std::string, std::vector<double> > floatOptions;
static std::map<std::string, std::vector<std::string> > charOptions;
static int flag_Enum, member_ValMax;
void init_options(int member_ValMax_ = 0)
{
floatOptions.clear(); charOptions.clear();
flag_Enum = 0; member_ValMax = member_ValMax_;
}
// parser functions defined at the end of this file
void yyerror(const char *s);
void yymsg(int level, const char *fmt, ...);
char *strsave(char *ptr);
void skip(const char *skip, const char *until);
void skipTest(const char *skip, const char *until,
const char *until2, int l_until2_sub, int *type_until2);
void assignVariable(const std::string &name, int index, int assignType,
double value);
void assignVariables(const std::string &name, List_T *indices, int assignType,
List_T *values);
void incrementVariable(const std::string &name, int index, double value);
int printListOfDouble(char *format, List_T *list, char *buffer);
fullMatrix<double> ListOfListOfDouble2Matrix(List_T *list);
void ListOfDouble2Vector(List_T *list, std::vector<int> &v);
void ListOfDouble2Vector(List_T *list, std::vector<double> &v);
void ListOfShapes2VectorOfPairs(List_T *list, std::vector<std::pair<int, int> > &v);
void VectorOfPairs2ListOfShapes(const std::vector<std::pair<int, int> > &v, List_T *list);
void addPeriodicEdge(int, int, const std::vector<double>&);
void addPeriodicFace(int, int, const std::map<int, int>&);
void addPeriodicFace(int, int, const std::vector<double>&);
void computeAffineTransformation(SPoint3&, SPoint3&, double, SPoint3&,
std::vector<double>&);
void addEmbedded(int dim, std::vector<int> tags, int dim2, int tag2);
void getAllElementaryTags(int dim, List_T *in);
void getAllPhysicalTags(int dim, List_T *in);
void getElementaryTagsForPhysicalGroups(int dim, List_T *in, List_T *out);
void getElementaryTagsInBoundingBox(int dim, double x1, double y1, double z1,
double x2, double y2, double z2, List_T *out);
void setVisibility(int dim, int visible, bool recursive);
void setVisibility(const std::vector<std::pair<int, int> > &dimTags, int visible,
bool recursive);
void setColor(const std::vector<std::pair<int, int> > &dimTags, unsigned int val,
bool recursive);
double treat_Struct_FullName_dot_tSTRING_Float(char* c1, char* c2, char* c3);
char* treat_Struct_FullName_dot_tSTRING_String(char* c1, char* c2, char* c3);
struct doubleXstring{
double d;
char *s;
};
%}
%union {
char *c;
int i;
unsigned int u;
double d;
double v[5];
Shape s;
List_T *l;
struct TwoChar c2;
}
%token <d> tDOUBLE
%token <c> tSTRING tBIGSTR
%token tEND tAFFECT tDOTS tSCOPE tPi tMPI_Rank tMPI_Size tEuclidian tCoordinates tTestLevel
%token tExp tLog tLog10 tSqrt tSin tAsin tCos tAcos tTan tRand
%token tAtan tAtan2 tSinh tCosh tTanh tFabs tAbs tFloor tCeil tRound
%token tFmod tModulo tHypot tList tLinSpace tLogSpace tListFromFile tCatenary
%token tPrintf tError tStr tSprintf tStrCat tStrPrefix tStrRelative tStrReplace
%token tAbsolutePath tDirName tStrSub tStrLen
%token tFind tStrFind tStrCmp tStrChoice tUpperCase tLowerCase tLowerCaseIn
%token tTextAttributes
%token tBoundingBox tDraw tSetChanged tToday tFixRelativePath tCurrentDirectory
%token tSyncModel tNewModel
%token tOnelabAction tOnelabRun tCodeName
%token tCpu tMemory tTotalMemory
%token tCreateTopology tCreateTopologyNoHoles
%token tDistanceFunction tDefineConstant tUndefineConstant
%token tDefineNumber tDefineStruct tNameStruct tAppend
%token tDefineString tSetNumber tSetString
%token tPoint tCircle tEllipse tLine tSphere tPolarSphere tSurface tSpline tVolume
%token tBlock tCylinder tCone tTorus tEllipsoid tQuadric tShapeFromFile
%token tRectangle tDisk tWire
%token tCharacteristic tLength tParametric tElliptic tRefineMesh tAdaptMesh
%token tRelocateMesh tSetFactory tThruSections tWedge tFillet tChamfer
%token tPlane tRuled tTransfinite tPhysical tCompound tPeriodic
%token tUsing tPlugin tDegenerated tRecursive
%token tRotate tTranslate tSymmetry tDilate tExtrude tLevelset tAffine
%token tBooleanUnion tBooleanIntersection tBooleanDifference tBooleanSection
%token tBooleanFragments tThickSolid
%token tRecombine tSmoother tSplit tDelete tCoherence
%token tIntersect tMeshAlgorithm tReverse
%token tLayers tScaleLast tHole tAlias tAliasWithOptions tCopyOptions
%token tQuadTriAddVerts tQuadTriNoNewVerts
%token tRecombLaterals tTransfQuadTri
%token tText2D tText3D tInterpolationScheme tTime tCombine
%token tBSpline tBezier tNurbs tNurbsOrder tNurbsKnots
%token tColor tColorTable tFor tIn tEndFor tIf tElseIf tElse tEndIf tExit tAbort
%token tField tReturn tCall tSlide tMacro tShow tHide tGetValue tGetStringValue tGetEnv
%token tGetString tGetNumber tUnique
%token tHomology tCohomology tBetti tExists tFileExists
%token tGMSH_MAJOR_VERSION tGMSH_MINOR_VERSION tGMSH_PATCH_VERSION
%token tGmshExecutableName tSetPartition
%token tNameToString tStringToName
%type <d> FExpr FExpr_Single DefineStruct NameStruct_Arg
%type <v> VExpr VExpr_Single CircleOptions TransfiniteType
%type <i> NumericAffectation NumericIncrement BooleanOperator BooleanOption
%type <i> PhysicalId0 PhysicalId1 PhysicalId2 PhysicalId3
%type <i> TransfiniteArrangement RecombineAngle InSphereCenter
%type <i> Append AppendOrNot
%type <u> ColorExpr
%type <c> StringExpr StringExprVar SendToFile tSTRING_Member_Float HomologyCommand
%type <c> LP RP
%type <c> StringIndex String__Index
%type <l> RecursiveListOfStringExprVar
%type <l> FExpr_Multi ListOfDouble ListOfDoubleOrAll RecursiveListOfDouble
%type <l> RecursiveListOfListOfDouble Enumeration
%type <l> ListOfColor RecursiveListOfColor
%type <l> ListOfShapes Transform Extrude MultipleShape Boolean
%type <l> TransfiniteCorners PeriodicTransform
%type <s> Shape
%type <c2> Struct_FullName
// Operators (with ascending priority): cf. C language
//
// Notes: - associativity (%left, %right)
// - UNARYPREC is a dummy terminal to resolve ambiguous cases
// for + and - (which exist in both unary and binary form)
%right tAFFECT tAFFECTPLUS tAFFECTMINUS tAFFECTTIMES tAFFECTDIVIDE
%right '?' tDOTS
%left tOR
%left tAND
%left tEQUAL tNOTEQUAL
%left '<' tLESSOREQUAL '>' tGREATEROREQUAL
%left '+' '-'
%left '*' '/' '%'
%right '!' tPLUSPLUS tMINUSMINUS UNARYPREC
%right '^'
%left '(' ')' '[' ']' '{' '}' '.' '#'
%left '~'
%left tSCOPE
%start All
%%
All :
GeoFormatItems
| error tEND { yyerrok; return 1; }
;
// G E O F I L E F O R M A T
GeoFormatItems :
// nothing
| GeoFormatItems GeoFormatItem
;
GeoFormatItem :
Printf { return 1; }
| View { return 1; }
| Affectation { return 1; }
| tSetFactory '(' StringExprVar ')' tEND
{
factory = $3;
if(factory == "OpenCASCADE"){
if(!GModel::current()->getOCCInternals())
GModel::current()->createOCCInternals();
for(int dim = -2; dim <= 3; dim++)
GModel::current()->getOCCInternals()->setMaxTag
(dim, std::max(GModel::current()->getOCCInternals()->getMaxTag(dim),
GModel::current()->getGEOInternals()->getMaxTag(dim)));
}
else if(GModel::current()->getOCCInternals()){
for(int dim = -2; dim <= 3; dim++)
GModel::current()->getGEOInternals()->setMaxTag
(dim, std::max(GModel::current()->getGEOInternals()->getMaxTag(dim),
GModel::current()->getOCCInternals()->getMaxTag(dim)));
}
Free($3);
}
| Shape { return 1; }
| Transform { List_Delete($1); return 1; }
| Delete { return 1; }
| Colorify { return 1; }
| SetPartition{ return 1; }
| Visibility { return 1; }
| Extrude { List_Delete($1); return 1; }
| Boolean { List_Delete($1); return 1; }
| BooleanShape{ return 1; }
| Constraints { return 1; }
| Coherence { return 1; }
| Loop { return 1; }
| Slide { return 1; }
| Command { return 1; }
| LevelSet { return 1; }
| Homology { return 1; }
;
SendToFile :
'>'
{
$$ = (char*)"w";
}
| '>' '>'
{
$$ = (char*)"a";
}
;
Printf :
tPrintf '(' StringExprVar ')' tEND
{
Msg::Direct($3);
Free($3);
}
| tError '(' StringExprVar ')' tEND
{
Msg::Error($3);
Free($3);
}
| tPrintf '(' StringExprVar ')' SendToFile StringExprVar tEND
{
std::string tmp = FixRelativePath(gmsh_yyname, $6);
FILE *fp = Fopen(tmp.c_str(), $5);
if(!fp){
yymsg(0, "Unable to open file '%s'", tmp.c_str());
}
else{
fprintf(fp, "%s\n", $3);
fclose(fp);
}
Free($3);
Free($6);
}
| tPrintf '(' StringExprVar ',' RecursiveListOfDouble ')' tEND
{
char tmpstring[5000];
int i = printListOfDouble($3, $5, tmpstring);
if(i < 0)
yymsg(0, "Too few arguments in Printf");
else if(i > 0)
yymsg(0, "%d extra argument%s in Printf", i, (i > 1) ? "s" : "");
else
Msg::Direct(tmpstring);
Free($3);
List_Delete($5);
}
| tError '(' StringExprVar ',' RecursiveListOfDouble ')' tEND
{
char tmpstring[5000];
int i = printListOfDouble($3, $5, tmpstring);
if(i < 0)
yymsg(0, "Too few arguments in Error");
else if(i > 0)
yymsg(0, "%d extra argument%s in Error", i, (i > 1) ? "s" : "");
else
Msg::Error(tmpstring);
Free($3);
List_Delete($5);
}
| tPrintf '(' StringExprVar ',' RecursiveListOfDouble ')' SendToFile StringExprVar tEND
{
char tmpstring[5000];
int i = printListOfDouble($3, $5, tmpstring);
if(i < 0)
yymsg(0, "Too few arguments in Printf");
else if(i > 0)
yymsg(0, "%d extra argument%s in Printf", i, (i > 1) ? "s" : "");
else{
std::string tmp = FixRelativePath(gmsh_yyname, $8);
FILE *fp = Fopen(tmp.c_str(), $7);
if(!fp){
yymsg(0, "Unable to open file '%s'", tmp.c_str());
}
else{
fprintf(fp, "%s\n", tmpstring);
fclose(fp);
}
}
Free($3);
Free($8);
List_Delete($5);
}
;
// V I E W
View :
String__Index StringExprVar '{' Views '}' tEND
{
#if defined(HAVE_POST)
if(!strcmp($1, "View") && ViewData->finalize()){
ViewData->setName($2);
ViewData->setFileName(gmsh_yyname);
ViewData->setFileIndex(gmsh_yyviewindex++);
new PView(ViewData);
}
else
delete ViewData;
#endif
Free($1); Free($2);
}
| tAlias tSTRING '[' FExpr ']' tEND
{
#if defined(HAVE_POST)
if(!strcmp($2, "View")){
int index = (int)$4;
if(index >= 0 && index < (int)PView::list.size())
new PView(PView::list[index], false);
else
yymsg(0, "Unknown view %d", index);
}
#endif
Free($2);
}
| tAliasWithOptions tSTRING '[' FExpr ']' tEND
{
#if defined(HAVE_POST)
if(!strcmp($2, "View")){
int index = (int)$4;
if(index >= 0 && index < (int)PView::list.size())
new PView(PView::list[index], true);
else
yymsg(0, "Unknown view %d", index);
}
#endif
Free($2);
}
| tCopyOptions tSTRING '[' FExpr ',' FExpr ']' tEND
{
#if defined(HAVE_POST)
if(!strcmp($2, "View")){
int index = (int)$4, index2 = (int)$6;
if(index >= 0 && index < (int)PView::list.size() &&
index2 >= 0 && index2 < (int)PView::list.size()){
PView::list[index2]->setOptions(PView::list[index]->getOptions());
}
else
yymsg(0, "Unknown view %d or %d", index, index2);
}
#endif
Free($2);
}
;
Views :
// nothing
{
#if defined(HAVE_POST)
ViewData = new PViewDataList();
#endif
}
| Views Element
| Views Text2D
| Views Text3D
| Views InterpolationMatrix
| Views Time
;
ElementCoords :
FExpr
{ ViewCoord.push_back($1); }
| ElementCoords ',' FExpr
{ ViewCoord.push_back($3); }
;
ElementValues :
FExpr
{ if(ViewValueList) ViewValueList->push_back($1); }
| ElementValues ',' FExpr
{ if(ViewValueList) ViewValueList->push_back($3); }
;
Element :
tSTRING
{
#if defined(HAVE_POST)
if(!strncmp($1, "SP", 2)){
ViewValueList = &ViewData->SP; ViewNumList = &ViewData->NbSP;
}
else if(!strncmp($1, "VP", 2)){
ViewValueList = &ViewData->VP; ViewNumList = &ViewData->NbVP;
}
else if(!strncmp($1, "TP", 2)){
ViewValueList = &ViewData->TP; ViewNumList = &ViewData->NbTP;
}
else if(!strncmp($1, "SL", 2)){
ViewValueList = &ViewData->SL; ViewNumList = &ViewData->NbSL;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_LIN);
}
else if(!strncmp($1, "VL", 2)){
ViewValueList = &ViewData->VL; ViewNumList = &ViewData->NbVL;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_LIN);
}
else if(!strncmp($1, "TL", 2)){
ViewValueList = &ViewData->TL; ViewNumList = &ViewData->NbTL;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_LIN);
}
else if(!strncmp($1, "ST", 2)){
ViewValueList = &ViewData->ST; ViewNumList = &ViewData->NbST;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_TRI);
}
else if(!strncmp($1, "VT", 2)){
ViewValueList = &ViewData->VT; ViewNumList = &ViewData->NbVT;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_TRI);
}
else if(!strncmp($1, "TT", 2)){
ViewValueList = &ViewData->TT; ViewNumList = &ViewData->NbTT;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_TRI);
}
else if(!strncmp($1, "SQ", 2)){
ViewValueList = &ViewData->SQ; ViewNumList = &ViewData->NbSQ;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_QUA);
}
else if(!strncmp($1, "VQ", 2)){
ViewValueList = &ViewData->VQ; ViewNumList = &ViewData->NbVQ;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_QUA);
}
else if(!strncmp($1, "TQ", 2)){
ViewValueList = &ViewData->TQ; ViewNumList = &ViewData->NbTQ;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_QUA);
}
else if(!strncmp($1, "SS", 2)){
ViewValueList = &ViewData->SS; ViewNumList = &ViewData->NbSS;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_TET);
}
else if(!strncmp($1, "VS", 2)){
ViewValueList = &ViewData->VS; ViewNumList = &ViewData->NbVS;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_TET);
}
else if(!strncmp($1, "TS", 2)){
ViewValueList = &ViewData->TS; ViewNumList = &ViewData->NbTS;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_TET);
}
else if(!strncmp($1, "SH", 2)){
ViewValueList = &ViewData->SH; ViewNumList = &ViewData->NbSH;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_HEX);
}
else if(!strncmp($1, "VH", 2)){
ViewValueList = &ViewData->VH; ViewNumList = &ViewData->NbVH;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_HEX);
}
else if(!strncmp($1, "TH", 2)){
ViewValueList = &ViewData->TH; ViewNumList = &ViewData->NbTH;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_HEX);
}
else if(!strncmp($1, "SI", 2)){
ViewValueList = &ViewData->SI; ViewNumList = &ViewData->NbSI;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_PRI);
}
else if(!strncmp($1, "VI", 2)){
ViewValueList = &ViewData->VI; ViewNumList = &ViewData->NbVI;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_PRI);
}
else if(!strncmp($1, "TI", 2)){
ViewValueList = &ViewData->TI; ViewNumList = &ViewData->NbTI;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_PRI);
}
else if(!strncmp($1, "SY", 2)){
ViewValueList = &ViewData->SY; ViewNumList = &ViewData->NbSY;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_PYR);
}
else if(!strncmp($1, "VY", 2)){
ViewValueList = &ViewData->VY; ViewNumList = &ViewData->NbVY;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_PYR);
}
else if(!strncmp($1, "TY", 2)){
ViewValueList = &ViewData->TY; ViewNumList = &ViewData->NbTY;
if(strlen($1) > 2) ViewData->setOrder2(TYPE_PYR);
}
else{
yymsg(0, "Unknown element type '%s'", $1);
ViewValueList = 0; ViewNumList = 0;
}
#endif
ViewCoord.clear();
Free($1);
}
'(' ElementCoords ')'
{
#if defined(HAVE_POST)
if(ViewValueList){
for(int i = 0; i < 3; i++)
for(unsigned int j = 0; j < ViewCoord.size() / 3; j++)
ViewValueList->push_back(ViewCoord[3 * j + i]);
}
#endif
}
'{' ElementValues '}' tEND
{
#if defined(HAVE_POST)
if(ViewValueList) (*ViewNumList)++;
#endif
}
;
Text2DValues :
StringExprVar
{
#if defined(HAVE_POST)
for(int i = 0; i < (int)strlen($1) + 1; i++) ViewData->T2C.push_back($1[i]);
#endif
Free($1);
}
| Text2DValues ',' StringExprVar
{
#if defined(HAVE_POST)
for(int i = 0; i < (int)strlen($3) + 1; i++) ViewData->T2C.push_back($3[i]);
#endif
Free($3);
}
;
Text2D :
tText2D '(' FExpr ',' FExpr ',' FExpr ')'
{
#if defined(HAVE_POST)
ViewData->T2D.push_back($3);
ViewData->T2D.push_back($5);
ViewData->T2D.push_back($7);
ViewData->T2D.push_back(ViewData->T2C.size());
#endif
}
'{' Text2DValues '}' tEND
{
#if defined(HAVE_POST)
ViewData->NbT2++;
#endif
}
;
Text3DValues :
StringExprVar
{
#if defined(HAVE_POST)
for(int i = 0; i < (int)strlen($1) + 1; i++) ViewData->T3C.push_back($1[i]);
#endif
Free($1);
}
| Text3DValues ',' StringExprVar
{
#if defined(HAVE_POST)
for(int i = 0; i < (int)strlen($3) + 1; i++) ViewData->T3C.push_back($3[i]);
#endif
Free($3);
}
;
Text3D :
tText3D '(' FExpr ',' FExpr ',' FExpr ',' FExpr ')'
{
#if defined(HAVE_POST)
ViewData->T3D.push_back($3); ViewData->T3D.push_back($5);
ViewData->T3D.push_back($7); ViewData->T3D.push_back($9);
ViewData->T3D.push_back(ViewData->T3C.size());
#endif
}
'{' Text3DValues '}' tEND
{
#if defined(HAVE_POST)
ViewData->NbT3++;
#endif
}
;
InterpolationMatrix :
tInterpolationScheme '{' RecursiveListOfListOfDouble '}'
'{' RecursiveListOfListOfDouble '}' tEND
{
#if defined(HAVE_POST)
int type =
(ViewData->NbSL || ViewData->NbVL) ? TYPE_LIN :
(ViewData->NbST || ViewData->NbVT) ? TYPE_TRI :
(ViewData->NbSQ || ViewData->NbVQ) ? TYPE_QUA :
(ViewData->NbSS || ViewData->NbVS) ? TYPE_TET :
(ViewData->NbSY || ViewData->NbVY) ? TYPE_PYR :
(ViewData->NbSI || ViewData->NbVI) ? TYPE_PRI :
(ViewData->NbSH || ViewData->NbVH) ? TYPE_HEX :
0;
ViewData->setInterpolationMatrices(type, ListOfListOfDouble2Matrix($3),
ListOfListOfDouble2Matrix($6));
#endif
}
| tInterpolationScheme '{' RecursiveListOfListOfDouble '}'
'{' RecursiveListOfListOfDouble '}'
'{' RecursiveListOfListOfDouble '}'
'{' RecursiveListOfListOfDouble '}' tEND
{
#if defined(HAVE_POST)
int type =
(ViewData->NbSL || ViewData->NbVL) ? TYPE_LIN :
(ViewData->NbST || ViewData->NbVT) ? TYPE_TRI :
(ViewData->NbSQ || ViewData->NbVQ) ? TYPE_QUA :
(ViewData->NbSS || ViewData->NbVS) ? TYPE_TET :
(ViewData->NbSH || ViewData->NbVH) ? TYPE_HEX :
0;
ViewData->setInterpolationMatrices(type, ListOfListOfDouble2Matrix($3),
ListOfListOfDouble2Matrix($6),
ListOfListOfDouble2Matrix($9),
ListOfListOfDouble2Matrix($12));
#endif
}
;
Time :
tTime
{
#if defined(HAVE_POST)
ViewValueList = &ViewData->Time;
#endif
}
'{' ElementValues '}' tEND
{
}
;
// A F F E C T A T I O N
NumericAffectation :
tAFFECT { $$ = 0; }
| tAFFECTPLUS { $$ = 1; }
| tAFFECTMINUS { $$ = 2; }
| tAFFECTTIMES { $$ = 3; }
| tAFFECTDIVIDE { $$ = 4; }
;
NumericIncrement :
tPLUSPLUS { $$ = 1; }
| tMINUSMINUS { $$ = -1; }
;
// these are for compatibility with the syntax in GetDP (square brackets instead
// of parentheses)
LP : '(' { $$ = (char*)"("; } | '[' { $$ = (char*)"["; } ;
RP : ')' { $$ = (char*)")"; } | ']' { $$ = (char*)"]"; } ;
Affectation :
// Variables
tDefineConstant '[' DefineConstants ']' tEND
| tUndefineConstant '[' UndefineConstants ']' tEND
| DefineStruct tEND
| tSetNumber LP StringExpr ',' FExpr RP tEND
{
Msg::SetOnelabNumber($3, $5);
Free($3);
}
| tSetString LP String__Index ',' StringExpr RP tEND
{
Msg::SetOnelabString($3, $5);
Free($3);
Free($5);
}
| String__Index NumericAffectation ListOfDouble tEND
{
if(!gmsh_yysymbols.count($1) && $2 && List_Nbr($3) == 1){
yymsg(0, "Unknown variable '%s'", $1);
}
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
if(!$2) s.list = (List_Nbr($3) != 1); // list if 0 or > 1 elements
if(!s.list){ // single expression
if(List_Nbr($3) != 1){
yymsg(0, "Cannot assign list to variable '%s'", $1);
}
else{
double d;
List_Read($3, 0, &d);
if(s.value.empty()){
if($2) yymsg(1, "Uninitialized variable '%s'", $1);
s.value.resize(1, 0.);
}
switch($2){
case 0 : s.value[0] = d; break;
case 1 : s.value[0] += d; break;
case 2 : s.value[0] -= d; break;
case 3 : s.value[0] *= d; break;
case 4 :
if(d) s.value[0] /= d;
else yymsg(0, "Division by zero in '%s /= %g'", $1, d);
break;
}
}
}
else{
// list of expressions; this is not recommended (should use [] or ()
// notation instead)
switch($2){
case 0: // affect
s.value.clear(); // fall-through
case 1: // append
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
s.value.push_back(d);
}
break;
case 2: // remove
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
std::vector<double>::iterator it = std::find(s.value.begin(),
s.value.end(), d);
if(it != s.value.end()) s.value.erase(it);
}
break;
default:
yymsg(0, "Operators *= and /= not available for lists");
break;
}
}
}
Free($1);
List_Delete($3);
}
| String__Index NumericIncrement tEND
{
if(!gmsh_yysymbols.count($1))
yymsg(0, "Unknown variable '%s'", $1);
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
if(!s.list && s.value.empty())
yymsg(0, "Uninitialized variable '%s'", $1);
else if(!s.list)
s.value[0] += $2;
else
yymsg(0, "Variable '%s' is a list", $1);
}
Free($1);
}
| String__Index LP RP NumericAffectation ListOfDouble tEND
{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
s.list = true;
double d;
switch($4){
case 0: // affect
s.value.clear(); // fall-through
case 1: // append
for(int i = 0; i < List_Nbr($5); i++){
List_Read($5, i, &d);
s.value.push_back(d);
}
break;
case 2: // remove
for(int i = 0; i < List_Nbr($5); i++){
List_Read($5, i, &d);
std::vector<double>::iterator it = std::find(s.value.begin(),
s.value.end(), d);
if(it != s.value.end()) s.value.erase(it);
}
break;
default:
yymsg(0, "Operators *= and /= not available for lists");
break;
}
Free($1);
List_Delete($5);
}
| String__Index LP '{' RecursiveListOfDouble '}' RP NumericAffectation ListOfDouble tEND
{
assignVariables($1, $4, $7, $8);
Free($1);
List_Delete($4);
List_Delete($8);
}
//+++ TO FIX
// lists of numbers with bracket notation
| String__Index '[' FExpr ']' NumericAffectation FExpr tEND
{
assignVariable($1, (int)$3, $5, $6);
Free($1);
}
| String__Index '[' FExpr ']' NumericIncrement tEND
{
incrementVariable($1, $3, $5);
Free($1);
}
// lists of numbers with parentheses notation
| String__Index '(' FExpr ')' NumericAffectation FExpr tEND
{
assignVariable($1, (int)$3, $5, $6);
Free($1);
}
| String__Index '(' FExpr ')' NumericIncrement tEND
{
incrementVariable($1, $3, $5);
Free($1);
}
// strings
| String__Index tAFFECT StringExpr tEND
{
gmsh_yystringsymbols[$1] = std::vector<std::string>(1, $3);
Free($1);
Free($3);
}
// lists of strings
| String__Index LP RP tAFFECT tStr LP RP tEND
{
gmsh_yystringsymbols[$1] = std::vector<std::string>();
Free($1);
}
| String__Index LP RP tAFFECT tStr LP RecursiveListOfStringExprVar RP tEND
{
std::vector<std::string> s;
for(int i = 0; i < List_Nbr($7); i++){
char **c = (char**)List_Pointer($7, i);
s.push_back(*c);
Free(*c);
}
gmsh_yystringsymbols[$1] = s;
Free($1);
List_Delete($7);
}
| String__Index LP RP tAFFECTPLUS tStr LP RecursiveListOfStringExprVar RP tEND
{
if(gmsh_yystringsymbols.count($1)){
for(int i = 0; i < List_Nbr($7); i++){
char **c = (char**)List_Pointer($7, i);
gmsh_yystringsymbols[$1].push_back(*c);
Free(*c);
}
}
else
yymsg(0, "Uninitialized variable '%s'", $1);
Free($1);
List_Delete($7);
}
// Option Strings
| String__Index '.' tSTRING tAFFECT StringExpr tEND
{
std::string tmp($5);
StringOption(GMSH_SET|GMSH_GUI, $1, 0, $3, tmp);
Free($1); Free($3); Free($5);
}
| String__Index '[' FExpr ']' '.' tSTRING tAFFECT StringExpr tEND
{
std::string tmp($8);
StringOption(GMSH_SET|GMSH_GUI, $1, (int)$3, $6, tmp);
Free($1); Free($6); Free($8);
}
// Option Numbers
| String__Index '.' tSTRING NumericAffectation FExpr tEND
{
double d = 0.;
if(NumberOption(GMSH_GET, $1, 0, $3, d)){
switch($4){
case 0 : d = $5; break;
case 1 : d += $5; break;
case 2 : d -= $5; break;
case 3 : d *= $5; break;
case 4 :
if($5) d /= $5;
else yymsg(0, "Division by zero in '%s.%s /= %g'", $1, $3, $5);
break;
}
NumberOption(GMSH_SET|GMSH_GUI, $1, 0, $3, d);
}
Free($1); Free($3);
}
| String__Index '[' FExpr ']' '.' tSTRING NumericAffectation FExpr tEND
{
double d = 0.;
if(NumberOption(GMSH_GET, $1, (int)$3, $6, d)){
switch($7){
case 0 : d = $8; break;
case 1 : d += $8; break;
case 2 : d -= $8; break;
case 3 : d *= $8; break;
case 4 :
if($8) d /= $8;
else yymsg(0, "Division by zero in '%s[%d].%s /= %g'", $1, (int)$3, $6, $8);
break;
}
NumberOption(GMSH_SET|GMSH_GUI, $1, (int)$3, $6, d);
}
Free($1); Free($6);
}
| String__Index '.' tSTRING NumericIncrement tEND
{
double d = 0.;
if(NumberOption(GMSH_GET, $1, 0, $3, d)){
d += $4;
NumberOption(GMSH_SET|GMSH_GUI, $1, 0, $3, d);
}
Free($1); Free($3);
}
| String__Index '[' FExpr ']' '.' tSTRING NumericIncrement tEND
{
double d = 0.;
if(NumberOption(GMSH_GET, $1, (int)$3, $6, d)){
d += $7;
NumberOption(GMSH_SET|GMSH_GUI, $1, (int)$3, $6, d);
}
Free($1); Free($6);
}
// Option Colors
| String__Index '.' tColor '.' tSTRING tAFFECT ColorExpr tEND
{
ColorOption(GMSH_SET|GMSH_GUI, $1, 0, $5, $7);
Free($1); Free($5);
}
| String__Index '[' FExpr ']' '.' tColor '.' tSTRING tAFFECT ColorExpr tEND
{
ColorOption(GMSH_SET|GMSH_GUI, $1, (int)$3, $8, $10);
Free($1); Free($8);
}
// ColorTable
| String__Index '.' tColorTable tAFFECT ListOfColor tEND
{
GmshColorTable *ct = GetColorTable(0);
if(!ct)
yymsg(0, "View[%d] does not exist", 0);
else{
ct->size = List_Nbr($5);
if(ct->size > COLORTABLE_NBMAX_COLOR)
yymsg(0, "Too many (%d>%d) colors in View[%d].ColorTable",
ct->size, COLORTABLE_NBMAX_COLOR, 0);
else
for(int i = 0; i < ct->size; i++) List_Read($5, i, &ct->table[i]);
if(ct->size == 1){
ct->size = 2;
ct->table[1] = ct->table[0];
}
}
Free($1);
List_Delete($5);
}
| String__Index '[' FExpr ']' '.' tColorTable tAFFECT ListOfColor tEND
{
GmshColorTable *ct = GetColorTable((int)$3);
if(!ct)
yymsg(0, "View[%d] does not exist", (int)$3);
else{
ct->size = List_Nbr($8);
if(ct->size > COLORTABLE_NBMAX_COLOR)
yymsg(0, "Too many (%d>%d) colors in View[%d].ColorTable",
ct->size, COLORTABLE_NBMAX_COLOR, (int)$3);
else
for(int i = 0; i < ct->size; i++) List_Read($8, i, &ct->table[i]);
if(ct->size == 1){
ct->size = 2;
ct->table[1] = ct->table[0];
}
}
Free($1);
List_Delete($8);
}
// Fields
| String__Index tField tAFFECT FExpr tEND
{
#if defined(HAVE_MESH)
if(!strcmp($1,"Background"))
GModel::current()->getFields()->setBackgroundFieldId((int)$4);
else if(!strcmp($1,"BoundaryLayer"))
GModel::current()->getFields()->setBoundaryLayerFieldId((int)$4);
else
yymsg(0, "Unknown command %s Field", $1);
#endif
}
| tField '[' FExpr ']' tAFFECT tSTRING tEND
{
#if defined(HAVE_MESH)
if(!GModel::current()->getFields()->newField((int)$3, $6))
yymsg(0, "Cannot create field %i of type '%s'", (int)$3, $6);
#endif
Free($6);
}
| tField '[' FExpr ']' '.' tSTRING tAFFECT FExpr tEND
{
#if defined(HAVE_MESH)
Field *field = GModel::current()->getFields()->get((int)$3);
if(field){
FieldOption *option = field->options[$6];
if(option){
try { option->numericalValue($8); }
catch(...){
yymsg(0, "Cannot assign a numerical value to option '%s' "
"in field %i of type '%s'", $6, (int)$3, field->getName());
}
}
else
yymsg(0, "Unknown option '%s' in field %i of type '%s'",
$6, (int)$3, field->getName());
}
else
yymsg(0, "No field with id %i", (int)$3);
#endif
Free($6);
}
| tField '[' FExpr ']' '.' tSTRING tAFFECT StringExpr tEND
{
#if defined(HAVE_MESH)
Field *field = GModel::current()->getFields()->get((int)$3);
if(field){
FieldOption *option = field->options[$6];
if(option){
try { option->string($8); }
catch (...){
yymsg(0, "Cannot assign a string value to option '%s' "
"in field %i of type '%s'", $6, (int)$3, field->getName());
}
}
else
yymsg(0, "Unknown option '%s' in field %i of type '%s'",
$6, (int)$3, field->getName());
}
else
yymsg(0, "No field with id %i", (int)$3);
#endif
Free($6);
Free($8);
}
| tField '[' FExpr ']' '.' tSTRING tAFFECT '{' RecursiveListOfDouble '}' tEND
{
#if defined(HAVE_MESH)
Field *field = GModel::current()->getFields()->get((int)$3);
if(field){
FieldOption *option = field->options[$6];
if(option){
if (option->getType() == FIELD_OPTION_LIST) {
std::list<int> vl = option->list();
vl.clear();
for(int i = 0; i < List_Nbr($9); i++){
double id;
List_Read($9, i, &id);
vl.push_back((int)id);
}
option->list(vl);
}
else {
std::list<double> vl = option->listdouble();
vl.clear();
for(int i = 0; i < List_Nbr($9); i++){
double id;
List_Read($9, i, &id);
vl.push_back(id);
}
option->listdouble(vl);
}
}
else
yymsg(0, "Unknown option '%s' in field %i of type '%s'",
$6, (int)$3, field->getName());
}
else
yymsg(0, "No field with id %i", (int)$3);
#endif
Free($6);
List_Delete($9);
}
| tField '[' FExpr ']' '.' tSTRING tEND
{
#if defined(HAVE_MESH)
Field *field = GModel::current()->getFields()->get((int)$3);
if(field){
FieldCallback *callback = field->callbacks[$6];
if(callback) {
callback->run();
}
else
yymsg(0, "Unknown callback '%s' in field %i of type '%s'",
$6, (int)$3, field->getName());
}
else
yymsg(0, "No field with id %i", (int)$3);
#endif
Free($6);
}
// Plugins
| tPlugin '(' tSTRING ')' '.' tSTRING tAFFECT FExpr tEND
{
#if defined(HAVE_PLUGINS)
try {
PluginManager::instance()->setPluginOption($3, $6, $8);
}
catch (...) {
yymsg(0, "Unknown option '%s' or plugin '%s'", $6, $3);
}
#endif
Free($3); Free($6);
}
| tPlugin '(' tSTRING ')' '.' tSTRING tAFFECT StringExpr tEND
{
#if defined(HAVE_PLUGINS)
try {
PluginManager::instance()->setPluginOption($3, $6, $8);
}
catch (...) {
yymsg(0, "Unknown option '%s' or plugin '%s'", $6, $3);
}
#endif
Free($3); Free($6); Free($8);
}
;
Comma : /* none */ | ',' ;
DefineConstants :
/* none */
| DefineConstants Comma String__Index
{
std::string key($3);
std::vector<double> val(1, 0.);
if(!gmsh_yysymbols.count(key)){
gmsh_yysymbols[key].value = val;
}
Free($3);
}
| DefineConstants Comma String__Index tAFFECT FExpr
{
std::string key($3);
std::vector<double> val(1, $5);
if(!gmsh_yysymbols.count(key)){
gmsh_yysymbols[key].value = val;
}
Free($3);
}
| DefineConstants Comma String__Index tAFFECT '{' ListOfDouble
{ init_options(); }
FloatParameterOptionsOrNone '}'
{
if(List_Nbr($6) != 1)
yymsg(1, "List notation should be used to define list '%s[]'", $3);
std::string key($3);
std::vector<double> val;
for(int i = 0; i < List_Nbr($6); i++){
double d;
List_Read($6, i, &d);
val.push_back(d);
}
if(!gmsh_yysymbols.count(key)){
Msg::ExchangeOnelabParameter(key, val, floatOptions, charOptions);
gmsh_yysymbols[key].value = val;
}
Free($3);
Free($6);
}
| DefineConstants Comma String__Index LP RP tAFFECT '{' ListOfDouble
{ init_options(); }
FloatParameterOptionsOrNone '}'
{
std::string key($3);
std::vector<double> val;
for(int i = 0; i < List_Nbr($8); i++){
double d;
List_Read($8, i, &d);
val.push_back(d);
}
if(!gmsh_yysymbols.count(key)){
Msg::ExchangeOnelabParameter(key, val, floatOptions, charOptions);
gmsh_yysymbols[key].value = val;
}
Free($3);
Free($8);
}
| DefineConstants Comma String__Index tAFFECT StringExpr
{
std::string key($3), val($5);
if(!gmsh_yystringsymbols.count(key)){
gmsh_yystringsymbols[key] = std::vector<std::string>(1, val);
}
Free($3);
Free($5);
}
| DefineConstants Comma String__Index tAFFECT '{' StringExpr
{ init_options(); }
CharParameterOptionsOrNone '}'
{
std::string key($3), val($6);
if(!gmsh_yysymbols.count(key)){
Msg::ExchangeOnelabParameter(key, val, floatOptions, charOptions);
gmsh_yystringsymbols[key] = std::vector<std::string>(1, val);
}
Free($3);
Free($6);
}
;
UndefineConstants :
/* none */
| UndefineConstants Comma StringExprVar
{
std::string name($3);
Msg::UndefineOnelabParameter(name);
Free($3);
}
Enumeration :
FExpr tAFFECT StringExpr
{
$$ = List_Create(20,20,sizeof(doubleXstring));
doubleXstring v = {$1, $3};
List_Add($$, &v);
}
| Enumeration ',' FExpr tAFFECT StringExpr
{
doubleXstring v = {$3, $5};
List_Add($$, &v);
}
| FExpr_Multi tAFFECT String__Index '(' ')'
{
$$ = List_Create(20,20,sizeof(doubleXstring));
int n = List_Nbr($1);
if(!gmsh_yystringsymbols.count($3)){
yymsg(0, "Unknown string variable '%s'", $3);
}
else{
std::vector<std::string> &s(gmsh_yystringsymbols[$3]);
int m = s.size();
if(n == m){
for(int i = 0; i < n; i++){
double d;
List_Read($1, i, &d);
doubleXstring v = {d, strsave((char*)s[i].c_str())};
List_Add($$, &v);
}
}
else{
yymsg(0, "Size mismatch in enumeration: %d != %d", n, m);
}
}
List_Delete($1);
}
;
FloatParameterOptionsOrNone :
// none
| ',' FloatParameterOptions
;
FloatParameterOptionsOrNone_NoComma :
// none
| FloatParameterOptions
;
FloatParameterOptions :
FloatParameterOption
| FloatParameterOptions ',' FloatParameterOption
;
FloatParameterOption :
tSTRING ListOfDouble
{
std::string key($1);
for(int i = 0; i < List_Nbr($2); i++){
double v;
List_Read($2, i, &v);
floatOptions[key].push_back(v);
if (flag_Enum && !i) { member_ValMax = (int)v; }
}
Free($1);
List_Delete($2);
}
| tSTRING
{
std::string key($1);
double v;
if (!flag_Enum) {
v = 1.;
if (key == "Enum") flag_Enum = 1;
}
else
v = (double)++member_ValMax;
floatOptions[key].push_back(v);
Free($1);
}
| tSTRING '{' Enumeration '}'
{
std::string key($1);
for(int i = 0; i < List_Nbr($3); i++){
doubleXstring v;
List_Read($3, i, &v);
floatOptions[key].push_back(v.d);
charOptions[key].push_back(v.s);
}
Free($1);
for(int i = 0; i < List_Nbr($3); i++)
Free(((doubleXstring*)List_Pointer($3, i))->s);
List_Delete($3);
}
| tSTRING StringExpr
{
std::string key($1);
std::string val($2);
charOptions[key].push_back(val);
Free($1);
Free($2);
}
;
CharParameterOptionsOrNone :
// none
| ',' CharParameterOptions
;
CharParameterOptions :
CharParameterOption
| CharParameterOptions ',' CharParameterOption
;
CharParameterOption :
tSTRING FExpr
{
std::string key($1);
double val = $2;
floatOptions[key].push_back(val);
Free($1);
}
| tSTRING StringExpr
{
std::string key($1);
std::string val($2);
charOptions[key].push_back(val);
Free($1);
Free($2);
}
| tMacro StringExpr // Macro is already a reserved keyword
{
std::string key("Macro");
std::string val($2);
charOptions[key].push_back(val);
Free($2);
}
| tSTRING '{' RecursiveListOfStringExprVar '}'
{
std::string key($1);
for(int i = 0; i < List_Nbr($3); i++){
char *s;
List_Read($3, i, &s);
std::string val(s);
Free(s);
charOptions[key].push_back(val);
}
Free($1);
List_Delete($3);
}
;
// S H A P E
PhysicalId0 :
FExpr
{
$$ = (int)$1;
}
| StringExpr
{
int t = GModel::current()->getGEOInternals()->getMaxPhysicalTag();
GModel::current()->getGEOInternals()->setMaxPhysicalTag(t + 1);
$$ = GModel::current()->setPhysicalName(std::string($1), 0, t + 1);
Free($1);
}
| StringExpr ',' FExpr
{
$$ = GModel::current()->setPhysicalName(std::string($1), 0, $3);
Free($1);
}
;
PhysicalId1 :
FExpr
{
$$ = (int)$1;
}
| StringExpr
{
int t = GModel::current()->getGEOInternals()->getMaxPhysicalTag();
GModel::current()->getGEOInternals()->setMaxPhysicalTag(t + 1);
$$ = GModel::current()->setPhysicalName(std::string($1), 1, t + 1);
Free($1);
}
| StringExpr ',' FExpr
{
$$ = GModel::current()->setPhysicalName(std::string($1), 1, $3);
Free($1);
}
;
PhysicalId2 :
FExpr
{
$$ = (int)$1;
}
| StringExpr
{
int t = GModel::current()->getGEOInternals()->getMaxPhysicalTag();
GModel::current()->getGEOInternals()->setMaxPhysicalTag(t + 1);
$$ = GModel::current()->setPhysicalName(std::string($1), 2, t + 1);
Free($1);
}
| StringExpr ',' FExpr
{
$$ = GModel::current()->setPhysicalName(std::string($1), 2, $3);
Free($1);
}
;
PhysicalId3 :
FExpr
{
$$ = (int)$1;
}
| StringExpr
{
int t = GModel::current()->getGEOInternals()->getMaxPhysicalTag();
GModel::current()->getGEOInternals()->setMaxPhysicalTag(t + 1);
$$ = GModel::current()->setPhysicalName(std::string($1), 3, t + 1);
Free($1);
}
| StringExpr ',' FExpr
{
$$ = GModel::current()->setPhysicalName(std::string($1), 3, $3);
Free($1);
}
;
InSphereCenter :
// nothing
{
$$ = -1;
}
| tIn tSphere '{' FExpr '}'
{
$$ = (int)$4;
}
;
CircleOptions :
{
for(int i = 0; i < 4; i++) $$[i] = 0.;
}
| tPlane VExpr
{
for(int i = 0; i < 4; i++) $$[i] = $2[i];
}
;
Shape :
tPoint '(' FExpr ')' tAFFECT VExpr tEND
{
int num = (int)$3;
double x = CTX::instance()->geom.scalingFactor * $6[0];
double y = CTX::instance()->geom.scalingFactor * $6[1];
double z = CTX::instance()->geom.scalingFactor * $6[2];
double lc = CTX::instance()->geom.scalingFactor * $6[3];
if(lc == 0.) lc = MAX_LC; // no mesh size given at the point
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addVertex(num, x, y, z, lc);
}
else{
if(!myGmshSurface)
GModel::current()->getGEOInternals()->addVertex(num, x, y, z, lc);
else
GModel::current()->getGEOInternals()->addVertex(num, x, y, myGmshSurface, lc);
}
AddToTemporaryBoundingBox(x, y, z);
$$.Type = MSH_POINT;
$$.Num = num;
}
| tLine '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addLine(num, tags);
}
else{
GModel::current()->getGEOInternals()->addLine(num, tags);
}
List_Delete($6);
$$.Type = MSH_SEGM_LINE;
$$.Num = num;
}
| tSpline '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Spline not available with OpenCASCADE factory");
}
else{
GModel::current()->getGEOInternals()->addSpline(num, tags);
}
List_Delete($6);
$$.Type = MSH_SEGM_SPLN;
$$.Num = num;
}
| tCircle '(' FExpr ')' tAFFECT ListOfDouble CircleOptions tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(tags.size() == 3){
GModel::current()->getOCCInternals()->addCircleArc
(num, tags[0], tags[1], tags[2]);
}
else if(param.size() >= 4 && param.size() <= 6){
double r = param[3];
double a1 = (param.size() == 6) ? param[4] : 0.;
double a2 = (param.size() == 6) ? param[5] :
(param.size() == 5) ? param[4] : 2.*M_PI;
GModel::current()->getOCCInternals()->addCircle
(num, param[0], param[1], param[2], r, a1, a2);
}
else{
yymsg(0, "Circle requires 3 points or 4 to 6 parameters");
}
}
else{
if(tags.size() == 3){
GModel::current()->getGEOInternals()->addCircleArc
(num, tags[0], tags[1], tags[2], $7[0], $7[1], $7[2]);
}
else{
yymsg(0, "Circle requires 3 points");
}
}
List_Delete($6);
$$.Type = MSH_SEGM_CIRC;
$$.Num = num;
}
| tEllipse '(' FExpr ')' tAFFECT ListOfDouble CircleOptions tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(tags.size() == 3){
GModel::current()->getOCCInternals()->addEllipseArc
(num, tags[0], tags[1], tags[2]);
}
else if(tags.size() == 4){
GModel::current()->getOCCInternals()->addEllipseArc
(num, tags[0], tags[1], tags[3]);
}
else if(param.size() >= 5 && param.size() <= 7){
double a1 = (param.size() == 7) ? param[5] : 0.;
double a2 = (param.size() == 7) ? param[6] :
(param.size() == 6) ? param[5] : 2.*M_PI;
GModel::current()->getOCCInternals()->addEllipse
(num, param[0], param[1], param[2], param[3], param[4], a1, a2);
}
else{
yymsg(0, "Ellipse requires 3 or 4 points, or 5 to 7 parameters");
}
}
else{
if(tags.size() == 4){
GModel::current()->getGEOInternals()->addEllipseArc
(num, tags[0], tags[1], tags[2], tags[3], $7[0], $7[1], $7[2]);
}
else{
yymsg(0, "Ellipse requires 4 points");
}
}
List_Delete($6);
$$.Type = MSH_SEGM_ELLI;
$$.Num = num;
}
| tBSpline '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addBSpline(num, tags);
}
else{
GModel::current()->getGEOInternals()->addBSpline(num, tags);
}
List_Delete($6);
$$.Type = MSH_SEGM_BSPLN;
$$.Num = num;
}
| tBezier '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addBezier(num, tags);
}
else{
GModel::current()->getGEOInternals()->addBezier(num, tags);
}
List_Delete($6);
$$.Type = MSH_SEGM_BEZIER;
$$.Num = num;
}
| tNurbs '(' FExpr ')' tAFFECT ListOfDouble tNurbsKnots ListOfDouble
tNurbsOrder FExpr tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
std::vector<double> knots; ListOfDouble2Vector($8, knots);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Nurbs not available yet with OpenCASCADE factory");
}
else{
int order = knots.size() - tags.size() - 1;
if(order != (int)$10)
yymsg(1, "Incompatible Nurbs order: using %d", order);
GModel::current()->getGEOInternals()->addNurbs(num, tags, knots);
}
List_Delete($6);
List_Delete($8);
$$.Type = MSH_SEGM_NURBS;
$$.Num = num;
}
| tCompound tLine '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$4;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
GModel::current()->getGEOInternals()->addCompoundLine(num, tags);
List_Delete($7);
$$.Type = MSH_SEGM_COMPOUND;
$$.Num = num;
}
| tWire '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addWire(num, tags, false);
}
else{
yymsg(0, "Wire only available using OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_SEGM_LOOP;
$$.Num = num;
}
| tLine tSTRING '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$4;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addLineLoop(num, tags);
}
else{
GModel::current()->getGEOInternals()->addLineLoop(num, tags);
}
List_Delete($7);
Free($2);
$$.Type = MSH_SEGM_LOOP;
$$.Num = num;
}
| tPlane tSurface '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$4;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addPlaneSurface(num, tags);
}
else{
GModel::current()->getGEOInternals()->addPlaneSurface(num, tags);
}
List_Delete($7);
$$.Type = MSH_SURF_PLAN;
$$.Num = num;
}
| tSurface '(' FExpr ')' tAFFECT ListOfDouble InSphereCenter tEND
{
int num = (int)$3;
std::vector<int> wires; ListOfDouble2Vector($6, wires);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(wires.size() != 1){
yymsg(0, "OpenCASCADE face filling requires a single line loop");
}
else{
GModel::current()->getOCCInternals()->addSurfaceFilling(num, wires[0]);
}
}
else{
GModel::current()->getGEOInternals()->addSurfaceFilling(num, wires, $7);
}
List_Delete($6);
$$.Type = MSH_SURF_REGL;
$$.Num = num;
}
| tRuled tSurface '(' FExpr ')' tAFFECT ListOfDouble InSphereCenter tEND
{
yymsg(2, "'Ruled Surface' command is deprecated: use 'Surface' instead");
int num = (int)$4;
std::vector<int> wires; ListOfDouble2Vector($7, wires);
GModel::current()->getGEOInternals()->addSurfaceFilling(num, wires, $8);
List_Delete($7);
$$.Type = MSH_SURF_REGL;
$$.Num = num;
}
| tEuclidian tCoordinates tEND
{
myGmshSurface = 0;
$$.Type = 0;
$$.Num = 0;
}
| tCoordinates tSurface FExpr tEND
{
myGmshSurface = gmshSurface::getSurface((int)$3);
$$.Type = 0;
$$.Num = 0;
}
| tParametric tSurface '(' FExpr ')' tAFFECT tBIGSTR tBIGSTR tBIGSTR tEND
{
int num = (int)$4;
myGmshSurface = gmshParametricSurface::NewParametricSurface(num, $7, $8, $9);
$$.Type = 0;
$$.Num = num;
}
| tSphere '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
std::vector<double> param; ListOfDouble2Vector($6, param);
$$.Type = 0;
if(param.size() >= 4 && param.size() <= 7){
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
double a1 = (param.size() >= 5) ? param[4] : -M_PI/2;
double a2 = (param.size() >= 6) ? param[5] : M_PI/2;
double a3 = (param.size() >= 7) ? param[6] : 2.*M_PI;
GModel::current()->getOCCInternals()->addSphere
(num, param[0], param[1], param[2], param[3], a1, a2, a3);
}
else{
yymsg(0, "Sphere only available with OpenCASCADE factory");
}
$$.Type = MSH_VOLUME;
}
else if(tags.size() == 2){
myGmshSurface = GModel::current()->getGEOInternals()->newGeometrySphere
(num, tags[0], tags[1]);
}
else{
yymsg(0, "Sphere requires 2 points or from 4 to 7 parameters");
}
List_Delete($6);
$$.Num = num;
}
| tPolarSphere '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
if(tags.size() == 2){
myGmshSurface = GModel::current()->getGEOInternals()->newGeometryPolarSphere
(num, tags[0], tags[1]);
}
else{
yymsg(0, "PolarSphere requires 2 points");
}
List_Delete($6);
$$.Type = 0;
$$.Num = num;
}
| tBlock '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(param.size() == 6){
GModel::current()->getOCCInternals()->addBlock
(num, param[0], param[1], param[2], param[3], param[4], param[5]);
}
else{
yymsg(0, "Block requires 6 parameters");
}
}
else{
yymsg(0, "Block only available with OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_VOLUME;
$$.Num = num;
}
| tTorus '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(param.size() == 5 || param.size() == 6){
double alpha = (param.size() == 6) ? param[5] : 2*M_PI;
GModel::current()->getOCCInternals()->addTorus
(num, param[0], param[1], param[2], param[3], param[4], alpha);
}
else{
yymsg(0, "Torus requires 5 ou 6 parameters");
}
}
else{
yymsg(0, "Torus only available with OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_VOLUME;
$$.Num = num;
}
| tRectangle '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(param.size() == 6 || param.size() == 7){
double r = (param.size() == 7) ? param[6] : 0.;
GModel::current()->getOCCInternals()->addRectangle
(num, param[0], param[1], param[2], param[3], param[4], param[5], r);
}
else{
yymsg(0, "Rectangle requires 6 ou 7 parameters");
}
}
else{
yymsg(0, "Rectangle only available with OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_SURF_PLAN;
$$.Num = num;
}
| tDisk '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(param.size() == 4 || param.size() == 5){
double ry = (param.size() == 5) ? param[4] : param[3];
GModel::current()->getOCCInternals()->addDisk
(num, param[0], param[1], param[2], param[3], ry);
}
else{
yymsg(0, "Disk requires 4 or 5 parameters");
}
}
else{
yymsg(0, "Disk only available with OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_SURF_PLAN;
$$.Num = num;
}
| tCylinder '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(param.size() == 7 || param.size() == 8){
double angle = (param.size() == 8) ? param[7] : 2*M_PI;
GModel::current()->getOCCInternals()->addCylinder
(num, param[0], param[1], param[2], param[3], param[4], param[5],
param[6], angle);
}
else{
yymsg(0, "Cylinder requires 7 or 8 parameters");
}
}
else{
yymsg(0, "Cylinder only available with OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_VOLUME;
$$.Num = num;
}
| tCone '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(param.size() == 8 || param.size() == 9){
double alpha = (param.size() == 9) ? param[8] : 2*M_PI;
GModel::current()->getOCCInternals()->addCone
(num, param[0], param[1], param[2], param[3], param[4], param[5],
param[6], param[7], alpha);
}
else{
yymsg(0, "Cone requires 8 or 9 parameters");
}
}
else{
yymsg(0, "Cone only available with OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_VOLUME;
$$.Num = num;
}
| tWedge '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(param.size() == 7){
GModel::current()->getOCCInternals()->addWedge
(num, param[0], param[1], param[2], param[3], param[4], param[5],
param[6]);
}
else{
yymsg(0, "Wedge requires 7 parameters");
}
}
else{
yymsg(0, "Wedge only available with OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_VOLUME;
$$.Num = num;
}
| tThickSolid '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<double> param; ListOfDouble2Vector($6, param);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
if(param.size() >= 2){
int in = (int)param[0];
double offset = param[1];
std::vector<int> exclude;
for(unsigned int i = 2; i < param.size(); i++)
exclude.push_back(param[i]);
GModel::current()->getOCCInternals()->addThickSolid
(num, in, exclude, offset);
}
else{
yymsg(0, "ThickSolid requires at least 2 parameters");
}
}
else{
yymsg(0, "ThickSolid only available with OpenCASCADE factory");
}
List_Delete($6);
}
| tCompound tSurface '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$4;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
GModel::current()->getGEOInternals()->addCompoundSurface(num, tags);
List_Delete($7);
$$.Type = MSH_SURF_COMPOUND;
$$.Num = num;
}
| tCompound tSurface '(' FExpr ')' tAFFECT ListOfDouble tSTRING
'{' RecursiveListOfListOfDouble '}' tEND
{
int num = (int)$4;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
std::vector<int> bndTags[4];
for(int i = 0; i < List_Nbr($10); i++){
if(i < 4)
ListOfDouble2Vector(*(List_T**)List_Pointer($10, i), bndTags[i]);
else
break;
}
GModel::current()->getGEOInternals()->addCompoundSurface(num, tags, bndTags);
List_Delete($7);
Free($8);
for (int i = 0; i < List_Nbr($10); i++)
List_Delete(*(List_T**)List_Pointer($10, i));
List_Delete($10);
$$.Type = MSH_SURF_COMPOUND;
$$.Num = num;
}
| tSurface tSTRING '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$4;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addSurfaceLoop(num, tags);
}
else{
GModel::current()->getGEOInternals()->addSurfaceLoop(num, tags);
}
List_Delete($7);
Free($2);
$$.Type = MSH_SURF_LOOP;
$$.Num = num;
}
| tVolume '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> tags; ListOfDouble2Vector($6, tags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addVolume(num, tags);
}
else{
GModel::current()->getGEOInternals()->addVolume(num, tags);
}
List_Delete($6);
$$.Type = MSH_VOLUME;
$$.Num = num;
}
| tThruSections '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$3;
std::vector<int> wires; ListOfDouble2Vector($6, wires);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
std::vector<std::pair<int, int> > outDimTags;
GModel::current()->getOCCInternals()->addThruSections
(num, wires, outDimTags, true, false);
}
else{
yymsg(0, "ThruSections only available with OpenCASCADE factory");
}
List_Delete($6);
$$.Type = MSH_VOLUME;
$$.Num = num;
}
| tRuled tThruSections '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$4;
std::vector<int> wires; ListOfDouble2Vector($7, wires);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
std::vector<std::pair<int, int> > outDimTags;
GModel::current()->getOCCInternals()->addThruSections
(num, wires, outDimTags, true, true);
}
else{
yymsg(0, "ThruSections only available with OpenCASCADE factory");
}
List_Delete($7);
$$.Type = MSH_VOLUME;
$$.Num = num;
}
| tCompound tVolume '(' FExpr ')' tAFFECT ListOfDouble tEND
{
int num = (int)$4;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
GModel::current()->getGEOInternals()->addCompoundVolume(num, tags);
List_Delete($7);
$$.Type = MSH_VOLUME_COMPOUND;
$$.Num = num;
}
| tPhysical tPoint '(' PhysicalId0 ')' NumericAffectation ListOfDouble tEND
{
int num = (int)$4;
int op = $6;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
GModel::current()->getGEOInternals()->modifyPhysicalGroup(0, num, op, tags);
List_Delete($7);
$$.Type = MSH_PHYSICAL_POINT;
$$.Num = num;
}
| tPhysical tLine '(' PhysicalId1 ')' NumericAffectation ListOfDouble tEND
{
int num = (int)$4;
int op = $6;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
GModel::current()->getGEOInternals()->modifyPhysicalGroup(1, num, op, tags);
List_Delete($7);
$$.Type = MSH_PHYSICAL_LINE;
$$.Num = num;
}
| tPhysical tSurface '(' PhysicalId2 ')' NumericAffectation ListOfDouble tEND
{
int num = (int)$4;
int op = $6;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
GModel::current()->getGEOInternals()->modifyPhysicalGroup(2, num, op, tags);
List_Delete($7);
$$.Type = MSH_PHYSICAL_SURFACE;
$$.Num = num;
}
| tPhysical tVolume '(' PhysicalId3 ')' NumericAffectation ListOfDouble tEND
{
int num = (int)$4;
int op = $6;
std::vector<int> tags; ListOfDouble2Vector($7, tags);
GModel::current()->getGEOInternals()->modifyPhysicalGroup(3, num, op, tags);
List_Delete($7);
$$.Type = MSH_PHYSICAL_VOLUME;
$$.Num = num;
}
;
// T R A N S F O R M
Transform :
tTranslate VExpr '{' MultipleShape '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($4, dimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->translate(dimTags, $2[0], $2[1], $2[2]);
}
else{
GModel::current()->getGEOInternals()->translate(dimTags, $2[0], $2[1], $2[2]);
}
$$ = $4;
}
| tRotate '{' VExpr ',' VExpr ',' FExpr '}' '{' MultipleShape '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($10, dimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->rotate
(dimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7);
}
else{
GModel::current()->getGEOInternals()->rotate
(dimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7);
}
$$ = $10;
}
| tSymmetry VExpr '{' MultipleShape '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($4, dimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
Msg::Error("Symmetry not implemented yet with OpenCASCADE factory");
}
else{
GModel::current()->getGEOInternals()->symmetry
(dimTags, $2[0], $2[1], $2[2], $2[3]);
}
$$ = $4;
}
| tDilate '{' VExpr ',' FExpr '}' '{' MultipleShape '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($8, dimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Dilate not implemented yet with OpenCASCADE factory");
}
else{
GModel::current()->getGEOInternals()->dilate
(dimTags, $3[0], $3[1], $3[2], $5, $5, $5);
}
$$ = $8;
}
| tDilate '{' VExpr ',' VExpr '}' '{' MultipleShape '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($8, dimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Dilate not implemented yet with OpenCASCADE factory");
}
else{
GModel::current()->getGEOInternals()->dilate
(dimTags, $3[0], $3[1], $3[2], $5[0], $5[1], $5[2]);
}
$$ = $8;
}
| tSTRING '{' MultipleShape '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($3, inDimTags);
$$ = $3;
List_Reset($$);
std::string action($1);
if(action == "Duplicata"){
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->copy(inDimTags, outDimTags);
}
else{
GModel::current()->getGEOInternals()->copy(inDimTags, outDimTags);
}
}
else if(action == "Boundary" || action == "CombinedBoundary"){
// boundary operations are performed directly on GModel, which enables
// to compute the boundary of hybrid CAD models; this also automatically
// binds all boundary entities for OCC models
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
GModel::current()->getBoundaryTags
(inDimTags, outDimTags, action == "CombinedBoundary");
}
else{
yymsg(0, "Unknown action on multiple shapes: %s", $1);
}
VectorOfPairs2ListOfShapes(outDimTags, $$);
Free($1);
}
| tIntersect tLine '{' RecursiveListOfDouble '}' tSurface '{' FExpr '}'
{
$$ = List_Create(2, 1, sizeof(Shape));
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Intersect line not available with OpenCASCADE");
}
else{
std::vector<int> in, out; ListOfDouble2Vector($4, in);
GModel::current()->getGEOInternals()->intersectCurvesWithSurface
(in, (int)$8, out);
for(unsigned int i = 0; i < out.size(); i++){
Shape s;
s.Type = MSH_POINT;
s.Num = out[i];
List_Add($$, &s);
}
}
List_Delete($4);
}
// syntax is wrong: should use {} around FExpr
| tSplit tLine '(' FExpr ')' '{' RecursiveListOfDouble '}' tEND
{
$$ = List_Create(2, 1, sizeof(Shape));
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Split Line not available with OpenCASCADE");
}
else{
std::vector<int> vertices, curves; ListOfDouble2Vector($7, vertices);
GModel::current()->getGEOInternals()->splitCurve
((int)$4, vertices, curves);
for(unsigned int i = 0; i < curves.size(); i++){
Shape s;
s.Type = MSH_SEGM_LINE;
s.Num = curves[i];
List_Add($$, &s);
}
}
List_Delete($7);
}
;
MultipleShape :
ListOfShapes { $$ = $1; }
| Transform { $$ = $1; }
;
ListOfShapes :
// nothing
{
$$ = List_Create(3, 3, sizeof(Shape));
}
| ListOfShapes Shape
{
List_Add($$, &$2);
}
| ListOfShapes tPoint '{' RecursiveListOfDouble '}' tEND
{
for(int i = 0; i < List_Nbr($4); i++){
double d;
List_Read($4, i, &d);
Shape s;
s.Num = (int)d;
s.Type = MSH_POINT;
List_Add($$, &s);
}
}
| ListOfShapes tLine '{' RecursiveListOfDouble '}' tEND
{
for(int i = 0; i < List_Nbr($4); i++){
double d;
List_Read($4, i, &d);
Shape s;
s.Num = (int)d;
s.Type = MSH_SEGM_LINE;
List_Add($$, &s);
}
}
| ListOfShapes tSurface '{' RecursiveListOfDouble '}' tEND
{
for(int i = 0; i < List_Nbr($4); i++){
double d;
List_Read($4, i, &d);
Shape s;
s.Num = (int)d;
s.Type = MSH_SURF_PLAN; // we don't care about the actual type
List_Add($$, &s);
}
}
| ListOfShapes tVolume '{' RecursiveListOfDouble '}' tEND
{
for(int i = 0; i < List_Nbr($4); i++){
double d;
List_Read($4, i, &d);
Shape s;
s.Num = (int)d;
s.Type = MSH_VOLUME;
List_Add($$, &s);
}
}
;
// L E V E L S E T S
LevelSet :
tLevelset tPlane '(' FExpr ')' tAFFECT ListOfDouble tEND
{
if(List_Nbr($7) == 4){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d[4];
for(int i = 0; i < 4; i++)
List_Read($7, i, &d[i]);
gLevelset *ls = new gLevelsetPlane(d[0], d[1], d[2], d[3], t);
gLevelset::add(ls);
}
}
else
yymsg(0, "Wrong number of arguments for levelset definition");
List_Delete($7);
}
| tLevelset tPoint '(' FExpr ')' tAFFECT '{' RecursiveListOfListOfDouble '}' tEND
{
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
fullMatrix<double> centers(List_Nbr($8),3);
for (int i = 0; i < List_Nbr($8); i++){
List_T *l = *(List_T**)List_Pointer($8, i);
for (int j = 0; j < List_Nbr(l); j++){
centers(i,j) = (double)(*(double*)List_Pointer(l, j));
}
}
gLevelset *ls = new gLevelsetPoints(centers, t);
gLevelset::add(ls);
}
for(int i = 0; i < List_Nbr($8); i++)
List_Delete(*(List_T**)List_Pointer($8, i));
List_Delete($8);
}
| tLevelset tPlane '(' FExpr ')' tAFFECT '{' VExpr ',' VExpr ','
RecursiveListOfDouble '}' tEND
{
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double pt[3] = {$8[0], $8[1], $8[2]};
double n[3] = {$10[0], $10[1], $10[2]};
gLevelset *ls = new gLevelsetPlane(pt, n, t);
gLevelset::add(ls);
}
List_Delete($12);
}
| tLevelset tPlane '(' FExpr ')' tAFFECT '{' VExpr ',' VExpr ',' VExpr ','
RecursiveListOfDouble '}' tEND
{
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double pt1[3] = {$8[0], $8[1], $8[2]};
double pt2[3] = {$10[0], $10[1], $10[2]};
double pt3[3] = {$12[0], $12[1], $12[2]};
gLevelset *ls = new gLevelsetPlane(pt1, pt2, pt3, t);
gLevelset::add(ls);
}
List_Delete($14);
}
| tLevelset tSphere '(' FExpr ')' tAFFECT '{' VExpr ',' RecursiveListOfDouble '}' tEND
{
if(List_Nbr($10) == 1){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d;
List_Read($10, 0, &d);
gLevelset *ls = new gLevelsetSphere($8[0], $8[1], $8[2], d, t);
gLevelset::add(ls);
}
}
else
yymsg(0, "Wrong number of arguments for levelset definition");
List_Delete($10);
}
| tLevelset tCylinder '(' FExpr ')' tAFFECT '{' VExpr ',' VExpr ','
RecursiveListOfDouble '}' tEND
{
if(List_Nbr($12) == 1){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d;
List_Read($12, 0, &d);
double pt[3] = {$8[0], $8[1], $8[2]};
double dir[3] = {$10[0], $10[1], $10[2]};
gLevelset *ls = new gLevelsetGenCylinder(pt, dir, d, t);
gLevelset::add(ls);
}
}
else if(List_Nbr($12) == 2){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d[2];
for(int i = 0; i < 2; i++)
List_Read($12, i, &d[i]);
double pt[3] = {$8[0], $8[1], $8[2]};
double dir[3] = {$10[0], $10[1], $10[2]};
gLevelset *ls = new gLevelsetCylinder(pt, dir, d[0], d[1], t);
gLevelset::add(ls);
}
}
else if(List_Nbr($12) == 3){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d[3];
for(int i = 0; i < 3; i++)
List_Read($12, i, &d[i]);
double pt[3] = {$8[0], $8[1], $8[2]};
double dir[3] = {$10[0], $10[1], $10[2]};
gLevelset *ls = new gLevelsetCylinder(pt, dir, d[0], d[1], d[2], t);
gLevelset::add(ls);
}
}
else
yymsg(0, "Wrong number of arguments for levelset definition");
List_Delete($12);
}
| tLevelset tCone '(' FExpr ')' tAFFECT '{' VExpr ',' VExpr ','
RecursiveListOfDouble '}' tEND
{
if(List_Nbr($12) == 1){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d;
List_Read($12, 0, &d);
double pt[3] = {$8[0], $8[1], $8[2]};
double dir[3] = {$10[0], $10[1], $10[2]};
gLevelset *ls = new gLevelsetCone(pt, dir, d, t);
gLevelset::add(ls);
}
}
else
yymsg(0, "Wrong number of arguments for levelset definition");
List_Delete($12);
}
| tLevelset tEllipsoid '(' FExpr ')' tAFFECT '{' VExpr ',' VExpr ','
RecursiveListOfDouble '}' tEND
{
if(List_Nbr($12) == 3){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d[3];
for(int i = 0; i < 3; i++)
List_Read($12, i, &d[i]);
double pt[3] = {$8[0], $8[1], $8[2]};
double dir[3] = {$10[0], $10[1], $10[2]};
gLevelset *ls = new gLevelsetEllipsoid(pt, dir, d[0], d[1], d[2], t);
gLevelset::add(ls);
}
}
else
yymsg(0, "Wrong number of arguments for levelset definition");
List_Delete($12);
}
| tLevelset tQuadric '(' FExpr ')' tAFFECT '{' VExpr ',' VExpr ','
RecursiveListOfDouble '}' tEND
{
if(List_Nbr($12) == 5){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d[5];
for(int i = 0; i < 5; i++)
List_Read($12, i, &d[i]);
double pt[3] = {$8[0], $8[1], $8[2]};
double dir[3] = {$10[0], $10[1], $10[2]};
gLevelset *ls = new gLevelsetGeneralQuadric(pt, dir, d[0], d[1],
d[2], d[3], d[4], t);
gLevelset::add(ls);
}
}
else
yymsg(0, "Wrong number of arguments for levelset definition");
List_Delete($12);
}
| tLevelset tSTRING '(' FExpr ')' tAFFECT ListOfDouble tEND
{
if(!strcmp($2, "Union")){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
std::vector<gLevelset *> vl;
for(int i = 0; i < List_Nbr($7); i++) {
double d; List_Read($7, i, &d);
gLevelset *pl = gLevelset::find((int)d);
if(!pl) yymsg(0, "Unknown levelset %d", (int)d);
else vl.push_back(pl);
}
gLevelset *ls = new gLevelsetUnion(vl, true, t);
gLevelset::add(ls);
}
}
else if(!strcmp($2, "Intersection")){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
std::vector<gLevelset *> vl;
for(int i = 0; i < List_Nbr($7); i++) {
double d; List_Read($7, i, &d);
gLevelset *pl = gLevelset::find((int)d);
if(!pl) yymsg(0, "Unknown levelset %d", (int)d);
else vl.push_back(pl);
}
gLevelset *ls = new gLevelsetIntersection(vl, true, t);
gLevelset::add(ls);
}
}
else if(!strcmp($2, "Cut")){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
std::vector<gLevelset *> vl;
for(int i = 0; i < List_Nbr($7); i++) {
double d; List_Read($7, i, &d);
gLevelset *pl = gLevelset::find((int)d);
if(!pl) yymsg(0, "Unknown levelset %d", (int)d);
else vl.push_back(pl);
}
gLevelset *ls = new gLevelsetCut(vl, true, t);
gLevelset::add(ls);
}
}
else if(!strcmp($2, "Crack")){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
std::vector<gLevelset *> vl;
for(int i = 0; i < List_Nbr($7); i++) {
double d; List_Read($7, i, &d);
gLevelset *pl = gLevelset::find((int)d);
if(!pl) yymsg(0, "Unknown levelset %d", (int)d);
else vl.push_back(pl);
}
gLevelset *ls = new gLevelsetCrack(vl, false, t);
gLevelset::add(ls);
}
}
else if(!strcmp($2, "Reverse")){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
double d;
List_Read($7, 0, &d);
gLevelset *pl = gLevelset::find((int)d);
gLevelset *ls = NULL;
if(!pl) yymsg(0, "Unknown levelset %d", (int)d);
else ls = new gLevelsetReverse(pl, t);
if(ls) gLevelset::add(ls);
}
}
#if defined(HAVE_POST)
else if(!strcmp($2, "PostView")){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
if(List_Nbr($7) > 0){
double d; List_Read($7, 0, &d);
gLevelset *ls = new gLevelsetPostView((int)d, t);
gLevelset::add(ls);
}
}
}
#endif
else
yymsg(0, "Wrong number of arguments for levelset definition");
Free($2);
List_Delete($7);
}
| tLevelset tSTRING '(' FExpr ')' tAFFECT tBIGSTR tEND
{
if(!strcmp($2, "MathEval")){
int t = (int)$4;
if(gLevelset::find(t)){
yymsg(0, "Levelset %d already exists", t);
}
else {
gLevelset *ls = new gLevelsetMathEval($7, t);
gLevelset::add(ls);
}
}
else
yymsg(0, "Unknown levelset '%s'", $2);
Free($2); Free($7);
}
| tLevelset tSTRING '{' FExpr '}' tEND
{
if(!strcmp($2, "CutMesh")){
int t = (int)$4;
if(gLevelset::find(t)){
GModel::current()->buildCutGModel(gLevelset::find(t), true, false);
}
else
yymsg(0, "Unknown levelset %d", t);
}
else if(!strcmp($2, "CutMeshTri")){
int t = (int)$4;
if(gLevelset::find(t)){
GModel::current()->buildCutGModel(gLevelset::find(t), true, true);
}
else
yymsg(0, "Unknown levelset %d", t);
}
else if(!strcmp($2, "SplitMesh")){
int t = (int)$4;
if(gLevelset::find(t)){
GModel::current()->buildCutGModel(gLevelset::find(t), false, true);
}
else
yymsg(0, "Unknown levelset %d", t);
}
else
yymsg(0, "Unknown levelset '%s'", $2);
Free($2);
}
;
// D E L E T E
Delete :
tDelete '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($3, dimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->remove(dimTags);
}
GModel::current()->getGEOInternals()->remove(dimTags);
GModel::current()->remove(dimTags);
List_Delete($3);
}
| tRecursive tDelete '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($4, dimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->remove(dimTags, true);
}
GModel::current()->getGEOInternals()->remove(dimTags, true);
GModel::current()->remove(dimTags, true);
List_Delete($4);
}
| tDelete tField '[' FExpr ']' tEND
{
#if defined(HAVE_MESH)
GModel::current()->getFields()->deleteField((int)$4);
#endif
}
| tDelete tSTRING '[' FExpr ']' tEND
{
#if defined(HAVE_POST)
if(!strcmp($2, "View")){
int index = (int)$4;
if(index >= 0 && index < (int)PView::list.size())
delete PView::list[index];
else
yymsg(0, "Unknown view %d", index);
}
else
yymsg(0, "Unknown command 'Delete %s'", $2);
#endif
Free($2);
}
| tDelete String__Index tEND
{
if(!strcmp($2, "Meshes") || !strcmp($2, "All")){
ClearProject();
}
else if(!strcmp($2, "Model")){
GModel::current()->destroy(true); // destroy, but keep name/filename
GModel::current()->getGEOInternals()->destroy();
}
else if(!strcmp($2, "Physicals")){
GModel::current()->getGEOInternals()->resetPhysicalGroups();
GModel::current()->deletePhysicalGroups();
}
else if(!strcmp($2, "Variables")){
gmsh_yysymbols.clear();
}
else if(!strcmp($2, "Options")){
ReInitOptions(0);
InitOptionsGUI(0);
}
else{
if(gmsh_yysymbols.count($2))
gmsh_yysymbols.erase($2);
else
yymsg(0, "Unknown object or expression to delete '%s'", $2);
}
Free($2);
}
| tDelete tSTRING tSTRING tEND
{
#if defined(HAVE_POST)
if(!strcmp($2, "Empty") && !strcmp($3, "Views")){
for(int i = PView::list.size() - 1; i >= 0; i--)
if(PView::list[i]->getData()->empty()) delete PView::list[i];
}
else
yymsg(0, "Unknown command 'Delete %s %s'", $2, $3);
#endif
Free($2); Free($3);
}
| tDelete tDefineStruct tEND
{
nameSpaces.clear();
}
;
// C O L O R I F Y
Colorify :
tColor ColorExpr '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($4, dimTags);
setColor(dimTags, $2, false);
List_Delete($4);
}
| tRecursive tColor ColorExpr '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($5, dimTags);
setColor(dimTags, $3, true);
List_Delete($5);
}
;
// S E T P A R T I T I O N
SetPartition :
tSetPartition FExpr '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($4, dimTags);
for(unsigned int i = 0; i < dimTags.size(); i++){
GEntity *ge = GModel::current()->getEntityByTag
(dimTags[i].first, dimTags[i].second);
if(ge){
for(unsigned int j = 0; j < ge->getNumMeshElements(); j++)
ge->getMeshElement(j)->setPartition((int)$2);
}
}
List_Delete($4);
}
;
// V I S I B I L I T Y
Visibility :
tShow tBIGSTR tEND
{
std::string what = $2;
setVisibility(-1, 1, false);
Free($2);
}
| tHide tBIGSTR tEND
{
std::string what = $2;
setVisibility(-1, 0, false);
Free($2);
}
| tShow '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($3, dimTags);
setVisibility(dimTags, 1, false);
List_Delete($3);
}
| tRecursive tShow '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($4, dimTags);
setVisibility(dimTags, 1, true);
List_Delete($4);
}
| tHide '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($3, dimTags);
setVisibility(dimTags, 0, false);
List_Delete($3);
}
| tRecursive tHide '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > dimTags;
ListOfShapes2VectorOfPairs($4, dimTags);
setVisibility(dimTags, 0, true);
List_Delete($4);
}
;
// C O M M A N D
Command :
String__Index StringExpr tEND
{
if(!strcmp($1, "Include")){
std::string tmp = FixRelativePath(gmsh_yyname, $2);
Msg::StatusBar(true, "Reading '%s'...", tmp.c_str());
// Warning: we explicitly ask ParseFile not to fclose() the included
// file, in order to allow user functions definitions in these files.
// The files will be closed in the next time OpenFile terminates. If
// you need to include many many files and don't have functions in
// the files, use "Merge" instead of "Include", as some OSes limit
// the number of files a process can open simultaneously. (A better
// solution would be to modify FunctionManager to reopen the files
// instead of using the FILE pointer...)
ParseFile(tmp, false, true);
SetBoundingBox();
Msg::StatusBar(true, "Done reading '%s'", tmp.c_str());
}
else if(!strcmp($1, "Print")){
// make sure we have the latest data from CAD internals in GModel (fixes
// bug where we would have no geometry in the picture if the print
// command is in the same file as the geometry)
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
std::string tmp = FixRelativePath(gmsh_yyname, $2);
CreateOutputFile(tmp, CTX::instance()->print.fileFormat);
}
else if(!strcmp($1, "Save")){
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
std::string tmp = FixRelativePath(gmsh_yyname, $2);
CreateOutputFile(tmp, CTX::instance()->mesh.fileFormat);
}
else if(!strcmp($1, "Merge") || !strcmp($1, "MergeWithBoundingBox")){
// sync CAD internals here, so that if we e.g. import a STEP file, we
// have the correct entity tags and the numberings don't clash
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
std::string tmp = FixRelativePath(gmsh_yyname, $2);
MergeFile(tmp, true);
}
else if(!strcmp($1, "NonBlockingSystemCall")){
SystemCall($2);
}
else if(!strcmp($1, "System") || !strcmp($1, "SystemCall")){
SystemCall($2, true);
}
else if(!strcmp($1, "SetName")){
GModel::current()->setName($2);
}
else if(!strcmp($1, "CreateDir")){
std::string tmp = FixRelativePath(gmsh_yyname, $2);
CreateSingleDir(tmp);
}
else if(!strcmp($1, "OnelabRun")){
Msg::RunOnelabClient($2);
}
else if(!strcmp($1, "OptimizeMesh")){
GModel::current()->optimizeMesh($2);
}
else{
yymsg(0, "Unknown command '%s'", $1);
}
Free($1); Free($2);
}
| tOnelabRun '(' RecursiveListOfStringExprVar ')' tEND
{
int n = List_Nbr($3);
if(n == 1){
char *s; List_Read($3, 0, &s);
Msg::RunOnelabClient(s);
Free(s);
}
else if(n == 2){
char *s, *t; List_Read($3, 0, &s); List_Read($3, 1, &t);
Msg::RunOnelabClient(s, t);
Free(s); Free(t);
}
else{
yymsg(0, "OnelabRun takes one or two arguments");
}
List_Delete($3);
}
| String__Index String__Index '[' FExpr ']' StringExprVar tEND
{
#if defined(HAVE_POST)
if(!strcmp($1, "Save") && !strcmp($2, "View")){
int index = (int)$4;
if(index >= 0 && index < (int)PView::list.size()){
std::string tmp = FixRelativePath(gmsh_yyname, $6);
PView::list[index]->write(tmp, CTX::instance()->post.fileFormat);
}
else
yymsg(0, "Unknown view %d", index);
}
else
yymsg(0, "Unknown command '%s'", $1);
#endif
Free($1); Free($2); Free($6);
}
| String__Index String__Index String__Index '[' FExpr ']' tEND
{
#if defined(HAVE_POST) && defined(HAVE_MESH)
if(!strcmp($1, "Background") && !strcmp($2, "Mesh") && !strcmp($3, "View")){
int index = (int)$5;
if(index >= 0 && index < (int)PView::list.size())
GModel::current()->getFields()->setBackgroundMesh(index);
else
yymsg(0, "Unknown view %d", index);
}
else
yymsg(0, "Unknown command '%s'", $1);
#endif
Free($1); Free($2); Free($3);
}
| String__Index FExpr tEND
{
if(!strcmp($1, "Sleep")){
SleepInSeconds($2);
}
else if(!strcmp($1, "Remesh")){
yymsg(0, "Surface remeshing must be reinterfaced");
}
else if(!strcmp($1, "Mesh")){
int lock = CTX::instance()->lock;
CTX::instance()->lock = 0;
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
GModel::current()->mesh((int)$2);
CTX::instance()->lock = lock;
}
else if(!strcmp($1, "SetOrder")){
#if defined(HAVE_MESH)
SetOrderN(GModel::current(), $2, CTX::instance()->mesh.secondOrderLinear,
CTX::instance()->mesh.secondOrderIncomplete,
CTX::instance()->mesh.meshOnlyVisible);
#endif
}
else if(!strcmp($1, "PartitionMesh")){
GModel::current()->partitionMesh($2);
}
else
yymsg(0, "Unknown command '%s'", $1);
Free($1);
}
| tPlugin '(' tSTRING ')' '.' tSTRING tEND
{
#if defined(HAVE_PLUGINS)
try {
PluginManager::instance()->action($3, $6, 0);
}
catch(...) {
yymsg(0, "Unknown action '%s' or plugin '%s'", $6, $3);
}
#endif
Free($3); Free($6);
}
| tCombine tSTRING tEND
{
#if defined(HAVE_POST)
if(!strcmp($2, "ElementsFromAllViews"))
PView::combine(false, 1, CTX::instance()->post.combineRemoveOrig);
else if(!strcmp($2, "ElementsFromVisibleViews"))
PView::combine(false, 0, CTX::instance()->post.combineRemoveOrig);
else if(!strcmp($2, "ElementsByViewName"))
PView::combine(false, 2, CTX::instance()->post.combineRemoveOrig);
else if(!strcmp($2, "TimeStepsFromAllViews"))
PView::combine(true, 1, CTX::instance()->post.combineRemoveOrig);
else if(!strcmp($2, "TimeStepsFromVisibleViews"))
PView::combine(true, 0, CTX::instance()->post.combineRemoveOrig);
else if(!strcmp($2, "TimeStepsByViewName"))
PView::combine(true, 2, CTX::instance()->post.combineRemoveOrig);
else if(!strcmp($2, "Views"))
PView::combine(false, 1, CTX::instance()->post.combineRemoveOrig);
else if(!strcmp($2, "TimeSteps"))
PView::combine(true, 2, CTX::instance()->post.combineRemoveOrig);
else
yymsg(0, "Unknown 'Combine' command");
#endif
Free($2);
}
| tExit tEND
{
Msg::Exit(0);
}
| tAbort tEND
{
gmsh_yyerrorstate = 999; // this will be checked when yyparse returns
YYABORT;
}
| tSyncModel tEND
{
// force sync
if(GModel::current()->getOCCInternals())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
GModel::current()->getGEOInternals()->synchronize(GModel::current());
}
| tNewModel tEND
{
new GModel();
GModel::current(GModel::list.size() - 1);
}
| tBoundingBox tEND
{
CTX::instance()->forcedBBox = 0;
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
SetBoundingBox();
}
| tBoundingBox '{' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr '}' tEND
{
CTX::instance()->forcedBBox = 1;
SetBoundingBox($3, $5, $7, $9, $11, $13);
}
| tDraw tEND
{
#if defined(HAVE_OPENGL)
drawContext::global()->draw();
#endif
}
| tSetChanged tEND
{
#if defined(HAVE_OPENGL)
CTX::instance()->mesh.changed = ENT_ALL;
for(unsigned int index = 0; index < PView::list.size(); index++)
PView::list[index]->setChanged(true);
#endif
}
| tCreateTopology tEND
{
GModel::current()->createTopologyFromMesh();
}
| tCreateTopologyNoHoles tEND
{
GModel::current()->createTopologyFromMesh(1);
}
| tRefineMesh tEND
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
GModel::current()->refineMesh(CTX::instance()->mesh.secondOrderLinear);
}
| tAdaptMesh '{' RecursiveListOfDouble '}' '{' RecursiveListOfDouble '}'
'{' RecursiveListOfListOfDouble '}' '{' FExpr ',' FExpr '}' tEND
{
int lock = CTX::instance()->lock;
CTX::instance()->lock = 0;
std::vector<int> technique;
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
technique.push_back((int)d);
}
if(technique.empty()){
yyerror("Need at least one adaptation technique");
}
else{
std::vector<simpleFunction<double>*> f;
for(int i = 0; i < List_Nbr($6); i++){
double d;
List_Read($6, i, &d);
gLevelset *l = gLevelset::find((int)d);
if(l) f.push_back(l);
else yymsg(0, "Unknown Levelset %d", (int)d);
}
if(technique.size() != f.size()){
yyerror("Number of techniques != number of levelsets");
}
else{
if(List_Nbr($9) != (int)f.size()){
yyerror("Number of parameters != number of levelsets");
}
else{
std::vector<std::vector<double> > parameters;
parameters.resize(List_Nbr($9));
for(int i = 0; i < List_Nbr($9); i++){
List_T *l = *(List_T**)List_Pointer($9, i);
for(int j = 0; j < List_Nbr(l); j++){
double d;
List_Read(l, j, &d);
parameters[i].push_back(d);
}
}
int niter = (int)$12;
bool meshAll = ($14 == 0) ? false : true;
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
GModel::current()->adaptMesh(technique, f, parameters, niter, meshAll);
}
}
}
List_Delete($3);
List_Delete($6);
for(int i = 0; i < List_Nbr($9); i++)
List_Delete(*(List_T**)List_Pointer($9, i));
List_Delete($9);
CTX::instance()->lock = lock;
}
;
// S L I D E
Slide :
tSlide '(' '{' RecursiveListOfDouble '}' ',' StringExpr ',' StringExpr ')' tEND
{
#if defined(HAVE_POPPLER)
std::vector<int> is;
for(int i = 0; i < List_Nbr($4); i++){
double d;
List_Read($4, i, &d);
is.push_back ((int) d);
}
gmshPopplerWrapper::instance()->setMacroForPages(is, $7, $9 );
#endif
}
// L O O P
Loop :
tFor '(' FExpr tDOTS FExpr ')'
{
LoopControlVariablesTab[ImbricatedLoop][0] = $3;
LoopControlVariablesTab[ImbricatedLoop][1] = $5;
LoopControlVariablesTab[ImbricatedLoop][2] = 1.0;
LoopControlVariablesNameTab[ImbricatedLoop] = "";
gmshgetpos(gmsh_yyin, &yyposImbricatedLoopsTab[ImbricatedLoop]);
yylinenoImbricatedLoopsTab[ImbricatedLoop] = gmsh_yylineno;
if($3 > $5)
skip("For", "EndFor");
else
ImbricatedLoop++;
if(ImbricatedLoop > MAX_RECUR_LOOPS - 1){
yymsg(0, "Reached maximum number of imbricated loops");
ImbricatedLoop = MAX_RECUR_LOOPS - 1;
}
}
| tFor '(' FExpr tDOTS FExpr tDOTS FExpr ')'
{
LoopControlVariablesTab[ImbricatedLoop][0] = $3;
LoopControlVariablesTab[ImbricatedLoop][1] = $5;
LoopControlVariablesTab[ImbricatedLoop][2] = $7;
LoopControlVariablesNameTab[ImbricatedLoop] = "";
gmshgetpos(gmsh_yyin, &yyposImbricatedLoopsTab[ImbricatedLoop]);
yylinenoImbricatedLoopsTab[ImbricatedLoop] = gmsh_yylineno;
if(($7 > 0. && $3 > $5) || ($7 < 0. && $3 < $5))
skip("For", "EndFor");
else
ImbricatedLoop++;
if(ImbricatedLoop > MAX_RECUR_LOOPS - 1){
yymsg(0, "Reached maximum number of imbricated loops");
ImbricatedLoop = MAX_RECUR_LOOPS - 1;
}
}
| tFor tSTRING tIn '{' FExpr tDOTS FExpr '}'
{
LoopControlVariablesTab[ImbricatedLoop][0] = $5;
LoopControlVariablesTab[ImbricatedLoop][1] = $7;
LoopControlVariablesTab[ImbricatedLoop][2] = 1.0;
LoopControlVariablesNameTab[ImbricatedLoop] = $2;
gmsh_yysymbol &s(gmsh_yysymbols[$2]);
s.list = false;
s.value.resize(1);
s.value[0] = $5;
gmshgetpos(gmsh_yyin, &yyposImbricatedLoopsTab[ImbricatedLoop]);
yylinenoImbricatedLoopsTab[ImbricatedLoop] = gmsh_yylineno;
if($5 > $7)
skip("For", "EndFor");
else
ImbricatedLoop++;
if(ImbricatedLoop > MAX_RECUR_LOOPS - 1){
yymsg(0, "Reached maximum number of imbricated loops");
ImbricatedLoop = MAX_RECUR_LOOPS - 1;
}
Free($2);
}
| tFor tSTRING tIn '{' FExpr tDOTS FExpr tDOTS FExpr '}'
{
LoopControlVariablesTab[ImbricatedLoop][0] = $5;
LoopControlVariablesTab[ImbricatedLoop][1] = $7;
LoopControlVariablesTab[ImbricatedLoop][2] = $9;
LoopControlVariablesNameTab[ImbricatedLoop] = $2;
gmsh_yysymbol &s(gmsh_yysymbols[$2]);
s.list = false;
s.value.resize(1);
s.value[0] = $5;
gmshgetpos(gmsh_yyin, &yyposImbricatedLoopsTab[ImbricatedLoop]);
yylinenoImbricatedLoopsTab[ImbricatedLoop] = gmsh_yylineno;
if(($9 > 0. && $5 > $7) || ($9 < 0. && $5 < $7))
skip("For", "EndFor");
else
ImbricatedLoop++;
if(ImbricatedLoop > MAX_RECUR_LOOPS - 1){
yymsg(0, "Reached maximum number of imbricated loops");
ImbricatedLoop = MAX_RECUR_LOOPS - 1;
}
Free($2);
}
| tEndFor
{
if(ImbricatedLoop <= 0){
yymsg(0, "Invalid For/EndFor loop");
ImbricatedLoop = 0;
}
else{
double step = LoopControlVariablesTab[ImbricatedLoop - 1][2];
std::string name = LoopControlVariablesNameTab[ImbricatedLoop - 1];
if(name.size()){
if(!gmsh_yysymbols.count(name))
yymsg(0, "Unknown loop variable '%s'", name.c_str());
else{
gmsh_yysymbol &s(gmsh_yysymbols[name]);
if(!s.list && s.value.size()){
s.value[0] += step;
LoopControlVariablesTab[ImbricatedLoop - 1][0] = s.value[0];
}
else
yymsg(0, "Bad loop variable %s", name.c_str());
}
}
else{
LoopControlVariablesTab[ImbricatedLoop - 1][0] += step;
}
double x0 = LoopControlVariablesTab[ImbricatedLoop - 1][0];
double x1 = LoopControlVariablesTab[ImbricatedLoop - 1][1];
if((step > 0. && x0 <= x1) || (step < 0. && x0 >= x1)){
gmshsetpos(gmsh_yyin, &yyposImbricatedLoopsTab[ImbricatedLoop - 1]);
gmsh_yylineno = yylinenoImbricatedLoopsTab[ImbricatedLoop - 1];
}
else
ImbricatedLoop--;
}
}
| tMacro tSTRING
{
if(!FunctionManager::Instance()->createFunction
(std::string($2), gmsh_yyin, gmsh_yyname, gmsh_yylineno))
yymsg(0, "Redefinition of function %s", $2);
skip(NULL, "Return");
Free($2);
}
| tMacro StringExpr
{
if(!FunctionManager::Instance()->createFunction
(std::string($2), gmsh_yyin, gmsh_yyname, gmsh_yylineno))
yymsg(0, "Redefinition of function %s", $2);
skip(NULL, "Return");
Free($2);
}
| tReturn
{
if(!FunctionManager::Instance()->leaveFunction
(&gmsh_yyin, gmsh_yyname, gmsh_yylineno))
yymsg(0, "Error while exiting function");
}
| tCall String__Index tEND
{
if(!FunctionManager::Instance()->enterFunction
(std::string($2), &gmsh_yyin, gmsh_yyname, gmsh_yylineno))
yymsg(0, "Unknown function %s", $2);
Free($2);
}
| tCall StringExpr tEND
{
if(!FunctionManager::Instance()->enterFunction
(std::string($2), &gmsh_yyin, gmsh_yyname, gmsh_yylineno))
yymsg(0, "Unknown function %s", $2);
Free($2);
}
| tIf '(' FExpr ')'
{
ImbricatedTest++;
if(ImbricatedTest > MAX_RECUR_TESTS-1){
yymsg(0, "Reached maximum number of imbricated tests");
ImbricatedTest = MAX_RECUR_TESTS-1;
}
if($3){
// Current test is true
statusImbricatedTests[ImbricatedTest] = 1;
}
else{
statusImbricatedTests[ImbricatedTest] = 0;
// Go after the next ElseIf or Else or EndIf
int type_until2 = 0;
skipTest("If", "EndIf", "ElseIf", 4, &type_until2);
if(!type_until2) ImbricatedTest--; // EndIf reached
}
}
| tElseIf '(' FExpr ')'
{
if(ImbricatedTest > 0){
if (statusImbricatedTests[ImbricatedTest]){
// Last test (If or ElseIf) was true, thus go after EndIf (out of If EndIf)
skip("If", "EndIf");
ImbricatedTest--;
}
else{
// Previous test(s) (If and ElseIf) not yet true
if($3){
statusImbricatedTests[ImbricatedTest] = 1;
}
else{
// Current test still not true: statusImbricatedTests[ImbricatedTest] = 0;
// Go after the next ElseIf or Else or EndIf
int type_until2 = 0;
skipTest("If", "EndIf", "ElseIf", 4, &type_until2);
if(!type_until2) ImbricatedTest--;
}
}
}
else{
yymsg(0, "Orphan ElseIf");
}
}
| tElse
{
if(ImbricatedTest > 0){
if(statusImbricatedTests[ImbricatedTest]){
skip("If", "EndIf");
ImbricatedTest--;
}
}
else{
yymsg(0, "Orphan Else");
}
}
| tEndIf
{
ImbricatedTest--;
if(ImbricatedTest < 0)
yymsg(1, "Orphan EndIf");
}
;
// E X T R U D E
Extrude :
tExtrude VExpr '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($4, inDimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->extrude
(inDimTags, $2[0], $2[1], $2[2], outDimTags);
}
else{
GModel::current()->getGEOInternals()->extrude
(inDimTags, $2[0], $2[1], $2[2], outDimTags);
}
$$ = $4;
List_Reset($$);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
| tExtrude '{' VExpr ',' VExpr ',' FExpr '}' '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($10, inDimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->revolve
(inDimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7, outDimTags);
}
else{
GModel::current()->getGEOInternals()->revolve
(inDimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7, outDimTags);
}
$$ = $10;
List_Reset($$);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
| tExtrude '{' VExpr ',' VExpr ',' VExpr ',' FExpr '}' '{' ListOfShapes '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($12, inDimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Twisting extrude not available with OpenCASCADE factory");
}
else{
GModel::current()->getGEOInternals()->twist
(inDimTags, $7[0], $7[1], $7[2], $3[0], $3[1], $3[2], $5[0], $5[1], $5[2],
$9, outDimTags);
}
$$ = $12;
List_Reset($$);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
| tExtrude VExpr '{' ListOfShapes
{
extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
extr.mesh.QuadToTri = NO_QUADTRI;
extr.mesh.ScaleLast = false;
}
ExtrudeParameters '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($4, inDimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->extrude
(inDimTags, $2[0], $2[1], $2[2], outDimTags, &extr);
}
else{
GModel::current()->getGEOInternals()->extrude
(inDimTags, $2[0], $2[1], $2[2], outDimTags, &extr);
}
$$ = $4;
List_Reset($$);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
| tExtrude '{' VExpr ',' VExpr ',' FExpr '}' '{' ListOfShapes
{
extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
extr.mesh.QuadToTri = NO_QUADTRI;
extr.mesh.ScaleLast = false;
}
ExtrudeParameters '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($10, inDimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->revolve
(inDimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7, outDimTags,
&extr);
}
else{
GModel::current()->getGEOInternals()->revolve
(inDimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7, outDimTags,
&extr);
}
$$ = $10;
List_Reset($$);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
| tExtrude '{' VExpr ',' VExpr ',' VExpr ',' FExpr '}' '{' ListOfShapes
{
extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
extr.mesh.QuadToTri = NO_QUADTRI;
extr.mesh.ScaleLast = false;
}
ExtrudeParameters '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($12, inDimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Twisting extrude not available with OpenCASCADE factory");
}
else{
GModel::current()->getGEOInternals()->twist
(inDimTags, $7[0], $7[1], $7[2], $3[0], $3[1], $3[2], $5[0], $5[1], $5[2],
$9, outDimTags, &extr);
}
$$ = $12;
List_Reset($$);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
| tExtrude '{' ListOfShapes
{
extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
extr.mesh.QuadToTri = NO_QUADTRI;
extr.mesh.ScaleLast = false;
}
ExtrudeParameters '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($3, inDimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
yymsg(0, "Boundary layer extrusion not available with OpenCASCADE factory");
}
else{
GModel::current()->getGEOInternals()->boundaryLayer
(inDimTags, outDimTags, &extr);
}
$$ = $3;
List_Reset($$);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
| tExtrude '{' ListOfShapes '}' tUsing tWire '{' FExpr '}'
{
std::vector<std::pair<int, int> > inDimTags, outDimTags;
ListOfShapes2VectorOfPairs($3, inDimTags);
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
GModel::current()->getOCCInternals()->addPipe(inDimTags, (int)$8, outDimTags);
}
else{
yymsg(0, "Pipe only available with OpenCASCADE factory");
}
$$ = $3;
List_Reset($$);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
| tThruSections ListOfDouble
{
$$ = List_Create(2, 1, sizeof(Shape));
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
std::vector<int> wires; ListOfDouble2Vector($2, wires);
std::vector<std::pair<int, int> > outDimTags;
GModel::current()->getOCCInternals()->addThruSections
(-1, wires, outDimTags, false, false);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
else{
yymsg(0, "ThruSections only available with OpenCASCADE factory");
}
List_Delete($2);
}
| tRuled tThruSections ListOfDouble
{
$$ = List_Create(2, 1, sizeof(Shape));
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
std::vector<int> wires; ListOfDouble2Vector($3, wires);
std::vector<std::pair<int, int> > outDimTags;
GModel::current()->getOCCInternals()->addThruSections
(-1, wires, outDimTags, false, true);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
else{
yymsg(0, "ThruSections only available with OpenCASCADE factory");
}
List_Delete($3);
}
| tFillet '{' RecursiveListOfDouble '}' '{' RecursiveListOfDouble '}' '{' FExpr '}'
{
$$ = List_Create(2, 1, sizeof(Shape));
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
double radius = $9;
std::vector<int> regions, edges;
ListOfDouble2Vector($3, regions); ListOfDouble2Vector($6, edges);
std::vector<std::pair<int, int> > outDimTags;
GModel::current()->getOCCInternals()->fillet
(regions, edges, radius, outDimTags);
VectorOfPairs2ListOfShapes(outDimTags, $$);
}
else{
yymsg(0, "Fillet only available with OpenCASCADE factory");
}
List_Delete($3);
List_Delete($6);
}
;
ExtrudeParameters :
ExtrudeParameter
{
}
| ExtrudeParameters ExtrudeParameter
{
}
;
ExtrudeParameter :
tLayers '{' FExpr '}' tEND
{
int n = (int)fabs($3);
if(n){ // we accept n==0 to easily disable layers
extr.mesh.ExtrudeMesh = true;
extr.mesh.NbLayer = 1;
extr.mesh.NbElmLayer.clear();
extr.mesh.hLayer.clear();
extr.mesh.NbElmLayer.push_back((int)fabs($3));
extr.mesh.hLayer.push_back(1.);
}
}
| tLayers '{' ListOfDouble ',' ListOfDouble '}' tEND
{
extr.mesh.ExtrudeMesh = true;
extr.mesh.NbLayer = List_Nbr($3);
if(List_Nbr($3) == List_Nbr($5)){
extr.mesh.NbElmLayer.clear();
extr.mesh.hLayer.clear();
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
extr.mesh.NbElmLayer.push_back((d > 0) ? (int)d : 1);
List_Read($5, i, &d);
extr.mesh.hLayer.push_back(d);
}
}
else
yymsg(0, "Wrong layer definition {%d, %d}", List_Nbr($3), List_Nbr($5));
List_Delete($3);
List_Delete($5);
}
| tScaleLast tEND
{
extr.mesh.ScaleLast = true;
}
| tRecombine tEND
{
extr.mesh.Recombine = true;
}
| tRecombine FExpr tEND
{
extr.mesh.Recombine = $2 ? true : false;
}
| tQuadTriAddVerts tEND
{
extr.mesh.QuadToTri = QUADTRI_ADDVERTS_1;
}
| tQuadTriAddVerts tRecombLaterals tEND
{
extr.mesh.QuadToTri = QUADTRI_ADDVERTS_1_RECOMB;
}
| tQuadTriNoNewVerts tEND
{
extr.mesh.QuadToTri = QUADTRI_NOVERTS_1;
}
| tQuadTriNoNewVerts tRecombLaterals tEND
{
extr.mesh.QuadToTri = QUADTRI_NOVERTS_1_RECOMB;
}
| tHole '(' FExpr ')' tAFFECT ListOfDouble tUsing FExpr tEND
{
std::vector<int> tags; ListOfDouble2Vector($6, tags);
int num = (int)$3;
GModel::current()->getGEOInternals()->addDiscreteSurface(num);
extr.mesh.Holes[num].first = $8;
extr.mesh.Holes[num].second = tags;
List_Delete($6);
}
| tUsing tSTRING '[' FExpr ']' tEND
{
if(!strcmp($2, "Index"))
extr.mesh.BoundaryLayerIndex = $4;
else if(!strcmp($2, "View"))
extr.mesh.ViewIndex = $4;
Free($2);
}
;
// B O O L E A N
BooleanOperator :
tBooleanUnion { $$ = OCC_Internals::Union; }
| tBooleanIntersection { $$ = OCC_Internals::Intersection; }
| tBooleanDifference { $$ = OCC_Internals::Difference; }
| tBooleanSection { $$ = OCC_Internals::Section; }
| tBooleanFragments { $$ = OCC_Internals::Fragments; }
;
BooleanOption :
{ $$ = 0; }
| tDelete tEND { $$ = 1; }
| tRecursive tDelete tEND { $$ = 2; }
| tDelete FExpr tEND { $$ = $2 ? 1 : 0; }
| tRecursive tDelete FExpr tEND { $$ = $3 ? 2 : 0; }
Boolean :
BooleanOperator '{' ListOfShapes BooleanOption '}'
'{' ListOfShapes BooleanOption '}'
{
$$ = List_Create(2, 1, sizeof(Shape));
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
std::vector<std::pair<int, int > > object, tool, out;
ListOfShapes2VectorOfPairs($3, object);
ListOfShapes2VectorOfPairs($7, tool);
// currently we don't distinguish between Delete and Recursive Delete:
// we always delete recursively. Let us know if you have examples where
// having the choice would be interesting
GModel::current()->getOCCInternals()->applyBooleanOperator
(-1, (OCC_Internals::BooleanOperator)$1, object, tool, out, $4, $8);
VectorOfPairs2ListOfShapes(out, $$);
}
else{
yymsg(0, "Boolean operators only available with OpenCASCADE factory");
}
List_Delete($3);
List_Delete($7);
}
| tShapeFromFile '(' StringExprVar ')'
{
$$ = List_Create(2, 1, sizeof(Shape));
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
std::vector<std::pair<int, int> > out;
std::string tmp = FixRelativePath(gmsh_yyname, $3);
GModel::current()->getOCCInternals()->importShapes(tmp, true, out);
VectorOfPairs2ListOfShapes(out, $$);
}
else{
yymsg(0, "ShapeFromFile only available with OpenCASCADE factory");
}
Free($3);
}
;
BooleanShape :
BooleanOperator '(' FExpr ')' tAFFECT '{' ListOfShapes BooleanOption '}'
'{' ListOfShapes BooleanOption '}' tEND
{
if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
std::vector<std::pair<int, int> > object, tool, out;
ListOfShapes2VectorOfPairs($7, object);
ListOfShapes2VectorOfPairs($11, tool);
// currently we don't distinguish between Delete and Recursive Delete:
// we always delete recursively. Let us know if you have examples where
// having the choice would be interesting
GModel::current()->getOCCInternals()->applyBooleanOperator
((int)$3, (OCC_Internals::BooleanOperator)$1, object, tool, out, $8, $12);
}
List_Delete($7);
List_Delete($11);
}
// M E S H I N G C O N S T R A I N T S ( T R A N S F I N I T E , . . . )
TransfiniteType :
{
$$[0] = $$[1] = 1.;
}
| tUsing tSTRING FExpr
{
if(!strcmp($2, "Progression") || !strcmp($2, "Power"))
$$[0] = 1.;
else if(!strcmp($2, "Bump"))
$$[0] = 2.;
else{
yymsg(0, "Unknown transfinite mesh type");
$$[0] = 1.;
}
$$[1] = $3;
Free($2);
}
;
TransfiniteArrangement :
{
$$ = -1; // left
}
| tSTRING
{
if(!strcmp($1, "Right"))
$$ = 1;
else if(!strcmp($1, "Left"))
$$ = -1;
else if(!strcmp($1, "AlternateRight"))
$$ = 2;
else if(!strcmp($1, "AlternateLeft"))
$$ = -2;
else // "Alternate" -> "Alternate Right"
$$ = 2;
Free($1);
}
;
TransfiniteCorners :
{
$$ = List_Create(1, 1, sizeof(double));
}
| tAFFECT ListOfDouble
{
$$ = $2;
}
RecombineAngle :
{
$$ = 45;
}
| tAFFECT FExpr
{
$$ = (int)$2;
}
;
PeriodicTransform :
{
$$ = List_Create(1, 1, sizeof(double));
}
| tAffine ListOfDouble
{
$$ = $2;
}
;
Constraints :
tCharacteristic tLength ListOfDouble tAFFECT FExpr tEND
{
// mesh sizes at vertices are stored in internal CAD data, as they can be
// specified during vertex creation and copied around during CAD
// operations
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int tag = (int)d;
if(GModel::current()->getOCCInternals())
GModel::current()->getOCCInternals()->setMeshSize(0, tag, $5);
GModel::current()->getGEOInternals()->setMeshSize(0, tag, $5);
GVertex *gv = GModel::current()->getVertexByTag(tag);
if(gv) gv->setPrescribedMeshSizeAtVertex($5);
}
List_Delete($3);
}
| tTransfinite tLine ListOfDoubleOrAll tAFFECT FExpr TransfiniteType tEND
{
// transfinite constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
int type = (int)$6[0];
double coef = fabs($6[1]);
int npoints = ((int)$5 < 2) ? 2 : (int)$5;
if(!$3){
GModel::current()->getGEOInternals()->setTransfiniteLine
(0, npoints, type, coef);
for(GModel::eiter it = GModel::current()->firstEdge();
it != GModel::current()->lastEdge(); it++){
(*it)->meshAttributes.method = MESH_TRANSFINITE;
(*it)->meshAttributes.nbPointsTransfinite = npoints;
(*it)->meshAttributes.typeTransfinite = type;
(*it)->meshAttributes.coeffTransfinite = coef;
}
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int j = (int)fabs(d);
for(int sig = -1; sig <= 1; sig += 2){
GModel::current()->getGEOInternals()->setTransfiniteLine
(sig * j, npoints, type * gmsh_sign(d), coef);
GEdge *ge = GModel::current()->getEdgeByTag(sig * j);
if(ge){
ge->meshAttributes.method = MESH_TRANSFINITE;
ge->meshAttributes.nbPointsTransfinite = npoints;
ge->meshAttributes.typeTransfinite = type * gmsh_sign(d);
ge->meshAttributes.coeffTransfinite = coef;
}
}
}
List_Delete($3);
}
}
| tTransfinite tSurface ListOfDoubleOrAll TransfiniteCorners TransfiniteArrangement tEND
{
// transfinite constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
std::vector<int> corners; ListOfDouble2Vector($4, corners);
if(!$3){
GModel::current()->getGEOInternals()->setTransfiniteSurface(0, $5, corners);
for(GModel::fiter it = GModel::current()->firstFace();
it != GModel::current()->lastFace(); it++){
(*it)->meshAttributes.method = MESH_TRANSFINITE;
(*it)->meshAttributes.transfiniteArrangement = $5;
}
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int tag = (int)d;
GModel::current()->getGEOInternals()->setTransfiniteSurface(tag, $5, corners);
GFace *gf = GModel::current()->getFaceByTag(tag);
if(gf){
gf->meshAttributes.method = MESH_TRANSFINITE;
gf->meshAttributes.transfiniteArrangement = $5;
if(corners.empty() || corners.size() == 3 || corners.size() == 4){
for(unsigned int j = 0; j < corners.size(); j++){
GVertex *gv = GModel::current()->getVertexByTag(corners[j]);
if(gv)
gf->meshAttributes.corners.push_back(gv);
else
yymsg(0, "Unknown model vertex with tag %d", corners[j]);
}
}
else{
yymsg(0, "Transfinite surface requires 3 or 4 corners vertices");
}
}
}
List_Delete($3);
}
List_Delete($4);
}
| tTransfinite tVolume ListOfDoubleOrAll TransfiniteCorners tEND
{
// transfinite constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
std::vector<int> corners; ListOfDouble2Vector($4, corners);
if(!$3){
GModel::current()->getGEOInternals()->setTransfiniteVolume(0, corners);
for(GModel::riter it = GModel::current()->firstRegion();
it != GModel::current()->lastRegion(); it++){
(*it)->meshAttributes.method = MESH_TRANSFINITE;
}
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int tag = (int)d;
GModel::current()->getGEOInternals()->setTransfiniteVolume(tag, corners);
GRegion *gr = GModel::current()->getRegionByTag(tag);
if(gr){
gr->meshAttributes.method = MESH_TRANSFINITE;
if(corners.empty() || corners.size() == 6 || corners.size() == 8){
for(unsigned int i = 0; i < corners.size(); i++){
GVertex *gv = GModel::current()->getVertexByTag(corners[i]);
if(gv)
gr->meshAttributes.corners.push_back(gv);
else
yymsg(0, "Unknown model vertex with tag %d", corners[i]);
}
}
}
}
List_Delete($3);
}
List_Delete($4);
}
| tTransfQuadTri ListOfDoubleOrAll tEND
{
// transfinite constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(!$2){
GModel::current()->getGEOInternals()->setTransfiniteVolumeQuadTri(0);
for(GModel::riter it = GModel::current()->firstRegion();
it != GModel::current()->lastRegion(); it++)
(*it)->meshAttributes.QuadTri = TRANSFINITE_QUADTRI_1;
}
else{
for(int i = 0; i < List_Nbr($2); i++){
double d;
List_Read($2, i, &d);
int tag = (int)d;
GModel::current()->getGEOInternals()->setTransfiniteVolumeQuadTri(tag);
GRegion *gr = GModel::current()->getRegionByTag(tag);
if(gr) gr->meshAttributes.QuadTri = TRANSFINITE_QUADTRI_1;
}
List_Delete($2);
}
}
| tMeshAlgorithm tSurface '{' RecursiveListOfDouble '}' tAFFECT FExpr tEND
{
for(int i = 0; i < List_Nbr($4); i++){
double d;
List_Read($4, i, &d);
CTX::instance()->mesh.algo2d_per_face[(int)d] = (int)$7;
}
List_Delete($4);
}
| tRecombine tSurface ListOfDoubleOrAll RecombineAngle tEND
{
// recombine constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(!$3){
GModel::current()->getGEOInternals()->setRecombine(2, 0, $4);
for(GModel::fiter it = GModel::current()->firstFace();
it != GModel::current()->lastFace(); it++){
(*it)->meshAttributes.recombine = 1;
(*it)->meshAttributes.recombineAngle = $4;
}
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int tag = (int)d;
GModel::current()->getGEOInternals()->setRecombine(2, tag, $4);
GFace *gf = GModel::current()->getFaceByTag(tag);
if(gf){
gf->meshAttributes.recombine = 1;
gf->meshAttributes.recombineAngle = $4;
}
}
List_Delete($3);
}
}
| tRecombine tVolume ListOfDoubleOrAll tEND
{
// recombine constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(!$3){
GModel::current()->getGEOInternals()->setRecombine(3, 0, 0.);
for(GModel::riter it = GModel::current()->firstRegion();
it != GModel::current()->lastRegion(); it++){
(*it)->meshAttributes.recombine3D = 1;
}
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int tag = (int)d;
GModel::current()->getGEOInternals()->setRecombine(3, tag, 0.);
GRegion *gr = GModel::current()->getRegionByTag(tag);
if(gr) gr->meshAttributes.recombine3D = 1;
}
List_Delete($3);
}
}
| tSmoother tSurface ListOfDoubleOrAll tAFFECT FExpr tEND
{
// smoothing constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(!$3){
GModel::current()->getGEOInternals()->setSmoothing(0, (int)$5);
for(GModel::fiter it = GModel::current()->firstFace();
it != GModel::current()->lastFace(); it++){
(*it)->meshAttributes.transfiniteSmoothing = (int)$5;
}
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int tag = (int)d;
GModel::current()->getGEOInternals()->setSmoothing(tag, (int)$5);
GFace *gf = GModel::current()->getFaceByTag(tag);
if(gf) gf->meshAttributes.transfiniteSmoothing = (int)$5;
}
List_Delete($3);
}
}
| tPeriodic tLine '{' RecursiveListOfDouble '}' tAFFECT
'{' RecursiveListOfDouble '}' PeriodicTransform tEND
{
if (List_Nbr($4) != List_Nbr($8)){
yymsg(0, "Number of master lines (%d) different from number of "
"slaves (%d) ", List_Nbr($8), List_Nbr($4));
}
else{
std::vector<double> transfo;
if(List_Nbr($10) != 0) {
if (List_Nbr($10) < 12){
yymsg(0, "Affine transformation requires at least 12 entries (we have %d)",
List_Nbr($10));
}
else {
transfo.resize(List_Nbr($10));
for(int i = 0; i < List_Nbr($10); i++)
List_Read($10, i, &transfo[i]);
}
}
for(int i = 0; i < List_Nbr($4); i++){
double d_master, d_slave;
List_Read($8, i, &d_master);
List_Read($4, i, &d_slave);
int j_master = (int)d_master;
int j_slave = (int)d_slave;
addPeriodicEdge(j_slave, j_master, transfo);
}
}
List_Delete($4);
List_Delete($8);
}
| tPeriodic tSurface '{' RecursiveListOfDouble '}' tAFFECT
'{' RecursiveListOfDouble '}' PeriodicTransform tEND
{
if (List_Nbr($4) != List_Nbr($8)){
yymsg(0, "Number of master faces (%d) different from number of "
"slaves (%d) ", List_Nbr($8), List_Nbr($4));
}
else{
if (List_Nbr($10) < 12){
// FIXME full automatic case here if List_Nbr($10) == 0)
yymsg(0, "Affine transformation requires at least 12 entries");
}
else {
std::vector<double> transfo(16,0);
for(int i = 0; i < List_Nbr($10); i++)
List_Read($10, i, &transfo[i]);
for(int i = 0; i < List_Nbr($4); i++){
double d_master, d_slave;
List_Read($8, i, &d_master);
List_Read($4, i, &d_slave);
addPeriodicFace(d_slave, d_master, transfo);
}
}
}
List_Delete($4);
List_Delete($8);
}
| tPeriodic tLine '{' RecursiveListOfDouble '}' tAFFECT
'{' RecursiveListOfDouble '}' tRotate '{' VExpr ',' VExpr ',' FExpr '}' tEND
{
if (List_Nbr($4) != List_Nbr($8)){
yymsg(0, "Number of master edges (%d) different from number of "
"slaves (%d) ", List_Nbr($8), List_Nbr($4));
}
else{
SPoint3 axis($12[0],$12[1],$12[2]);
SPoint3 origin($14[0],$14[1],$14[2]);
double angle($16);
SPoint3 translation(0,0,0);
std::vector<double> transfo;
computeAffineTransformation(origin,axis,angle,translation,transfo);
for(int i = 0; i < List_Nbr($4); i++){
double d_master, d_slave;
List_Read($8, i, &d_master);
List_Read($4, i, &d_slave);
addPeriodicEdge(d_slave,d_master,transfo);
}
}
List_Delete($4);
List_Delete($8);
}
| tPeriodic tSurface '{' RecursiveListOfDouble '}' tAFFECT
'{' RecursiveListOfDouble '}' tRotate '{' VExpr ',' VExpr ',' FExpr '}' tEND
{
if (List_Nbr($4) != List_Nbr($8)){
yymsg(0, "Number of master faces (%d) different from number of "
"slaves (%d) ", List_Nbr($8), List_Nbr($4));
}
else{
SPoint3 origin($14[0],$14[1],$14[2]);
SPoint3 axis($12[0],$12[1],$12[2]);
double angle($16);
SPoint3 translation(0,0,0);
std::vector<double> transfo;
computeAffineTransformation(origin,axis,angle,translation,transfo);
for(int i = 0; i < List_Nbr($4); i++){
double d_master, d_slave;
List_Read($8, i, &d_master);
List_Read($4, i, &d_slave);
addPeriodicFace(d_slave, d_master, transfo);
}
}
List_Delete($4);
List_Delete($8);
}
| tPeriodic tLine '{' RecursiveListOfDouble '}' tAFFECT
'{' RecursiveListOfDouble '}' tTranslate VExpr tEND
{
if (List_Nbr($4) != List_Nbr($8)){
yymsg(0, "Number of master edges (%d) different from number of "
"slaves (%d) ", List_Nbr($8), List_Nbr($4));
}
else{
SPoint3 origin(0,0,0);
SPoint3 axis(0,0,0);
double angle(0);
SPoint3 translation($11[0],$11[1],$11[2]);
std::vector<double> transfo;
computeAffineTransformation(origin,axis,angle,translation,transfo);
for(int i = 0; i < List_Nbr($4); i++){
double d_master, d_slave;
List_Read($8, i, &d_master);
List_Read($4, i, &d_slave);
addPeriodicEdge(d_slave,d_master,transfo);
}
}
List_Delete($4);
List_Delete($8);
}
| tPeriodic tSurface '{' RecursiveListOfDouble '}' tAFFECT
'{' RecursiveListOfDouble '}' tTranslate VExpr tEND
{
if (List_Nbr($4) != List_Nbr($8)){
yymsg(0, "Number of master faces (%d) different from number of "
"slaves (%d) ", List_Nbr($8), List_Nbr($4));
}
else{
SPoint3 origin(0,0,0);
SPoint3 axis(0,0,0);
double angle(0);
SPoint3 translation($11[0],$11[1],$11[2]);
std::vector<double> transfo;
computeAffineTransformation(origin,axis,angle,translation,transfo);
for(int i = 0; i < List_Nbr($4); i++){
double d_master, d_slave;
List_Read($8, i, &d_master);
List_Read($4, i, &d_slave);
addPeriodicFace(d_slave, d_master, transfo);
}
}
List_Delete($4);
List_Delete($8);
}
| tPeriodic tSurface FExpr '{' RecursiveListOfDouble '}'
tAFFECT FExpr '{' RecursiveListOfDouble '}' tEND
{
if (List_Nbr($5) != List_Nbr($10)){
yymsg(0, "Number of master surface edges (%d) different from number of "
"slave (%d) edges", List_Nbr($10), List_Nbr($5));
}
else{
int j_master = (int)$8;
int j_slave = (int)$3;
std::map<int,int> edgeCounterParts;
for (int i = 0; i < List_Nbr($5); i++){
double ds,dm;
List_Read($5,i,&ds);
List_Read($10,i,&dm);
edgeCounterParts[(int) ds] = (int) dm;
}
addPeriodicFace(j_slave, j_master, edgeCounterParts);
}
List_Delete($5);
List_Delete($10);
}
| tPoint '{' RecursiveListOfDouble '}' tIn tSurface '{' FExpr '}' tEND
{
std::vector<int> tags; ListOfDouble2Vector($3, tags);
addEmbedded(0, tags, 2, (int)$8);
List_Delete($3);
}
| tLine '{' RecursiveListOfDouble '}' tIn tSurface '{' FExpr '}' tEND
{
std::vector<int> tags; ListOfDouble2Vector($3, tags);
addEmbedded(1, tags, 2, (int)$8);
List_Delete($3);
}
| tPoint '{' RecursiveListOfDouble '}' tIn tVolume '{' FExpr '}' tEND
{
std::vector<int> tags; ListOfDouble2Vector($3, tags);
addEmbedded(0, tags, 3, (int)$8);
List_Delete($3);
}
| tLine '{' RecursiveListOfDouble '}' tIn tVolume '{' FExpr '}' tEND
{
std::vector<int> tags; ListOfDouble2Vector($3, tags);
addEmbedded(1, tags, 3, (int)$8);
List_Delete($3);
}
| tSurface '{' RecursiveListOfDouble '}' tIn tVolume '{' FExpr '}' tEND
{
std::vector<int> tags; ListOfDouble2Vector($3, tags);
addEmbedded(2, tags, 3, (int)$8);
List_Delete($3);
}
| tReverse tSurface ListOfDoubleOrAll tEND
{
// reverse mesh constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(!$3){
GModel::current()->getGEOInternals()->setReverseMesh(2, 0);
for(GModel::fiter it = GModel::current()->firstFace();
it != GModel::current()->lastFace(); it++){
(*it)->meshAttributes.reverseMesh = 1;
}
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int num = (int)d;
GModel::current()->getGEOInternals()->setReverseMesh(2, num);
GFace *gf = GModel::current()->getFaceByTag(num);
if(gf) gf->meshAttributes.reverseMesh = 1;
}
List_Delete($3);
}
}
| tReverse tLine ListOfDoubleOrAll tEND
{
// reverse mesh constraints are stored in GEO internals in addition to
// GModel, as they can be copied around during GEO operations
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(!$3){
GModel::current()->getGEOInternals()->setReverseMesh(1, 0);
for(GModel::eiter it = GModel::current()->firstEdge();
it != GModel::current()->lastEdge(); it++){
(*it)->meshAttributes.reverseMesh = 1;
}
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
int num = (int)d;
GModel::current()->getGEOInternals()->setReverseMesh(1, num);
GEdge *ge = GModel::current()->getEdgeByTag(num);
if(ge) ge->meshAttributes.reverseMesh = 1;
}
List_Delete($3);
}
}
| tRelocateMesh tPoint ListOfDoubleOrAll tEND
{
if(!$3){
for(GModel::viter it = GModel::current()->firstVertex();
it != GModel::current()->lastVertex(); it++)
(*it)->relocateMeshVertices();
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
GVertex *gv = GModel::current()->getVertexByTag((int)d);
if(gv) gv->relocateMeshVertices();
}
List_Delete($3);
}
}
| tRelocateMesh tLine ListOfDoubleOrAll tEND
{
if(!$3){
for(GModel::eiter it = GModel::current()->firstEdge();
it != GModel::current()->lastEdge(); it++)
(*it)->relocateMeshVertices();
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
GEdge *ge = GModel::current()->getEdgeByTag((int)d);
if(ge) ge->relocateMeshVertices();
}
List_Delete($3);
}
}
| tRelocateMesh tSurface ListOfDoubleOrAll tEND
{
if(!$3){
for(GModel::fiter it = GModel::current()->firstFace();
it != GModel::current()->lastFace(); it++)
(*it)->relocateMeshVertices();
}
else{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
GFace *gf = GModel::current()->getFaceByTag((int)d);
if(gf) gf->relocateMeshVertices();
}
List_Delete($3);
}
}
| tDegenerated tLine ListOfDouble tEND
{
for(int i = 0; i < List_Nbr($3); i++){
double dnum;
List_Read($3, i, &dnum);
int num = (int)dnum;
GModel::current()->getGEOInternals()->setDegenerated(1, num);
GEdge *ge = GModel::current()->getEdgeByTag(num);
if(ge) ge->setTooSmall(true);
}
List_Delete($3);
}
| tCompound tLine ListOfDouble tEND
{
std::vector<int> tags; ListOfDouble2Vector($3, tags);
GModel::current()->getGEOInternals()->setCompoundMesh(1, tags);
List_Delete($3);
}
| tCompound tSurface ListOfDouble tEND
{
std::vector<int> tags; ListOfDouble2Vector($3, tags);
GModel::current()->getGEOInternals()->setCompoundMesh(2, tags);
List_Delete($3);
}
| tCompound tVolume ListOfDouble tEND
{
std::vector<int> tags; ListOfDouble2Vector($3, tags);
GModel::current()->getGEOInternals()->setCompoundMesh(3, tags);
List_Delete($3);
}
;
// C O H E R E N C E
Coherence :
tCoherence tEND
{
GModel::current()->getGEOInternals()->removeAllDuplicates();
}
| tCoherence tSTRING tEND
{
if(!strcmp($2, "Geometry"))
GModel::current()->getGEOInternals()->removeAllDuplicates();
else if(!strcmp($2, "Mesh"))
GModel::current()->removeDuplicateMeshVertices(CTX::instance()->geom.tolerance);
else
yymsg(0, "Unknown coherence command");
Free($2);
}
| tCoherence tPoint '{' RecursiveListOfDouble '}' tEND
{
std::vector<int> tags; ListOfDouble2Vector($4, tags);
GModel::current()->getGEOInternals()->mergeVertices(tags);
List_Delete($4);
}
;
// H O M O L O G Y
HomologyCommand :
tHomology { $$ = (char*)"Homology"; }
| tCohomology { $$ = (char*)"Cohomology"; }
| tBetti { $$ = (char*)"Betti"; }
;
Homology :
HomologyCommand tEND
{
std::vector<int> domain, subdomain, dim;
for(int i = 0; i < 4; i++) dim.push_back(i);
GModel::current()->addHomologyRequest($1, domain, subdomain, dim);
}
| HomologyCommand '{' ListOfDouble '}' tEND
{
std::vector<int> domain, subdomain, dim;
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
domain.push_back((int)d);
}
for(int i = 0; i < 4; i++) dim.push_back(i);
GModel::current()->addHomologyRequest($1, domain, subdomain, dim);
List_Delete($3);
}
| HomologyCommand '{' ListOfDouble ',' ListOfDouble '}' tEND
{
std::vector<int> domain, subdomain, dim;
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
domain.push_back((int)d);
}
for(int i = 0; i < List_Nbr($5); i++){
double d;
List_Read($5, i, &d);
subdomain.push_back((int)d);
}
for(int i = 0; i < 4; i++) dim.push_back(i);
GModel::current()->addHomologyRequest($1, domain, subdomain, dim);
List_Delete($3);
List_Delete($5);
}
| HomologyCommand '(' ListOfDouble ')' '{' ListOfDouble ',' ListOfDouble '}' tEND
{
std::vector<int> domain, subdomain, dim;
for(int i = 0; i < List_Nbr($6); i++){
double d;
List_Read($6, i, &d);
domain.push_back((int)d);
}
for(int i = 0; i < List_Nbr($8); i++){
double d;
List_Read($8, i, &d);
subdomain.push_back((int)d);
}
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
dim.push_back((int)d);
}
GModel::current()->addHomologyRequest($1, domain, subdomain, dim);
List_Delete($6);
List_Delete($8);
List_Delete($3);
}
;
// G E N E R A L
FExpr :
FExpr_Single { $$ = $1; }
| '(' FExpr ')' { $$ = $2; }
| '-' FExpr %prec UNARYPREC { $$ = -$2; }
| '+' FExpr %prec UNARYPREC { $$ = $2; }
| '!' FExpr { $$ = !$2; }
| FExpr '-' FExpr { $$ = $1 - $3; }
| FExpr '+' FExpr { $$ = $1 + $3; }
| FExpr '*' FExpr { $$ = $1 * $3; }
| FExpr '/' FExpr
{
if(!$3)
yymsg(0, "Division by zero in '%g / %g'", $1, $3);
else
$$ = $1 / $3;
}
| FExpr '%' FExpr { $$ = (int)$1 % (int)$3; }
| FExpr '^' FExpr { $$ = pow($1, $3); }
| FExpr '<' FExpr { $$ = $1 < $3; }
| FExpr '>' FExpr { $$ = $1 > $3; }
| FExpr tLESSOREQUAL FExpr { $$ = $1 <= $3; }
| FExpr tGREATEROREQUAL FExpr { $$ = $1 >= $3; }
| FExpr tEQUAL FExpr { $$ = $1 == $3; }
| FExpr tNOTEQUAL FExpr { $$ = $1 != $3; }
| FExpr tAND FExpr { $$ = $1 && $3; }
| FExpr tOR FExpr { $$ = $1 || $3; }
| FExpr '?' FExpr tDOTS FExpr { $$ = $1 ? $3 : $5; }
| tExp LP FExpr RP { $$ = exp($3); }
| tLog LP FExpr RP { $$ = log($3); }
| tLog10 LP FExpr RP { $$ = log10($3); }
| tSqrt LP FExpr RP { $$ = sqrt($3); }
| tSin LP FExpr RP { $$ = sin($3); }
| tAsin LP FExpr RP { $$ = asin($3); }
| tCos LP FExpr RP { $$ = cos($3); }
| tAcos LP FExpr RP { $$ = acos($3); }
| tTan LP FExpr RP { $$ = tan($3); }
| tAtan LP FExpr RP { $$ = atan($3); }
| tAtan2 LP FExpr ',' FExpr RP { $$ = atan2($3, $5);}
| tSinh LP FExpr RP { $$ = sinh($3); }
| tCosh LP FExpr RP { $$ = cosh($3); }
| tTanh LP FExpr RP { $$ = tanh($3); }
| tFabs LP FExpr RP { $$ = fabs($3); }
| tAbs LP FExpr RP { $$ = std::abs($3); }
| tFloor LP FExpr RP { $$ = floor($3); }
| tCeil LP FExpr RP { $$ = ceil($3); }
| tRound LP FExpr RP { $$ = floor($3 + 0.5); }
| tFmod LP FExpr ',' FExpr RP { $$ = fmod($3, $5); }
| tModulo LP FExpr ',' FExpr RP { $$ = fmod($3, $5); }
| tHypot LP FExpr ',' FExpr RP { $$ = sqrt($3 * $3 + $5 * $5); }
| tRand LP FExpr RP { $$ = $3 * (double)rand() / (double)RAND_MAX; }
;
// FIXME: add +=, -=, *= et /=
FExpr_Single :
// Constants
tDOUBLE { $$ = $1; }
| tPi { $$ = 3.141592653589793; }
| tTestLevel { $$ = (double)ImbricatedTest; }
| tMPI_Rank { $$ = Msg::GetCommRank(); }
| tMPI_Size { $$ = Msg::GetCommSize(); }
| tGMSH_MAJOR_VERSION { $$ = GetGmshMajorVersion(); }
| tGMSH_MINOR_VERSION { $$ = GetGmshMinorVersion(); }
| tGMSH_PATCH_VERSION { $$ = GetGmshPatchVersion(); }
| tCpu { $$ = Cpu(); }
| tMemory { $$ = GetMemoryUsage()/1024./1024.; }
| tTotalMemory { $$ = TotalRam(); }
// Variables
| tDefineNumber LP FExpr
{ init_options(); }
FloatParameterOptionsOrNone RP
{
std::vector<double> val(1, $3);
Msg::ExchangeOnelabParameter("", val, floatOptions, charOptions);
$$ = val[0];
}
| DefineStruct
{ $$ = $1; }
| tGetNumber LP StringExprVar RP
{
$$ = Msg::GetOnelabNumber($3);
Free($3);
}
| tGetNumber LP StringExprVar ',' FExpr RP
{
$$ = Msg::GetOnelabNumber($3, $5);
Free($3);
}
//+++
| Struct_FullName
{
if(gmsh_yysymbols.count($1.char2)){
gmsh_yysymbol &s(gmsh_yysymbols[$1.char2]);
if(s.value.empty()){
yymsg(0, "Uninitialized variable '%s'", $1.char2);
$$ = 0.;
}
else
$$ = s.value[0];
}
else{
std::string struct_namespace($1.char1? $1.char1 : std::string("")),
struct_name($1.char2);
if(nameSpaces.getTag(struct_namespace, struct_name, $$)) {
yymsg(0, "Unknown Constant: %s", struct_name.c_str());
}
}
Free($1.char1); Free($1.char2);
}
| String__Index '[' FExpr ']'
{
int index = (int)$3;
if(!gmsh_yysymbols.count($1)){
yymsg(0, "Unknown variable '%s'", $1);
$$ = 0.;
}
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
if((int)s.value.size() < index + 1){
yymsg(0, "Uninitialized variable '%s[%d]'", $1, index);
$$ = 0.;
}
else
$$ = s.value[index];
}
Free($1);
}
| String__Index '(' FExpr ')'
{
int index = (int)$3;
if(!gmsh_yysymbols.count($1)){
yymsg(0, "Unknown variable '%s'", $1);
$$ = 0.;
}
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
if((int)s.value.size() < index + 1){
yymsg(0, "Uninitialized variable '%s[%d]'", $1, index);
$$ = 0.;
}
else
$$ = s.value[index];
}
Free($1);
}
| tExists '(' Struct_FullName ')'
{
if(gmsh_yysymbols.count($3.char2)){
$$ = 1;
}
else{
std::string struct_namespace($3.char1? $3.char1 : std::string("")),
struct_name($3.char2);
$$ = (nameSpaces.getTag(struct_namespace, struct_name, $$))? 0 : 1;
}
Free($3.char1); Free($3.char2);
}
| tExists '(' Struct_FullName '.' tSTRING_Member_Float ')'
{
std::string struct_namespace($3.char1? $3.char1 : std::string("")),
struct_name($3.char2);
Free($3.char1); Free($3.char2);
std::string key_member($5);
$$ = (nameSpaces.getMember
(struct_namespace, struct_name, key_member, $$))? 0 : 1;
if (flag_tSTRING_alloc) Free($5);
}
| tFileExists '(' StringExpr ')'
{
std::string tmp = FixRelativePath(gmsh_yyname, $3);
$$ = !StatFile(tmp);
Free($3);
}
| '#' String__Index LP RP
{
if(gmsh_yysymbols.count($2)){
gmsh_yysymbol &s(gmsh_yysymbols[$2]);
$$ = s.value.size();
}
else if(gmsh_yystringsymbols.count($2)){
$$ = gmsh_yystringsymbols[$2].size();
}
else{
yymsg(0, "Unknown variable '%s'", $2);
$$ = 0.;
}
Free($2);
}
| '#' String__Index tSCOPE
{
std::string struct_namespace($2);
$$ = (double)nameSpaces[struct_namespace].size();
Free($2);
}
| '#' tSCOPE
{
std::string struct_namespace(std::string(""));
$$ = (double)nameSpaces[struct_namespace].size();
}
| String__Index NumericIncrement
{
if(!gmsh_yysymbols.count($1)){
yymsg(0, "Unknown variable '%s'", $1);
$$ = 0.;
}
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
if(s.value.empty()){
yymsg(0, "Uninitialized variable '%s'", $1);
$$ = 0.;
}
else{
$$ = s.value[0];
s.value[0] += $2;
}
}
Free($1);
}
| String__Index '[' FExpr ']' NumericIncrement
{
int index = (int)$3;
if(!gmsh_yysymbols.count($1)){
yymsg(0, "Unknown variable '%s'", $1);
$$ = 0.;
}
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
if((int)s.value.size() < index + 1){
yymsg(0, "Uninitialized variable '%s[%d]'", $1, index);
$$ = 0.;
}
else{
$$ = s.value[index];
s.value[index] += $5;
}
}
Free($1);
}
| String__Index '(' FExpr ')' NumericIncrement
{
int index = (int)$3;
if(!gmsh_yysymbols.count($1)){
yymsg(0, "Unknown variable '%s'", $1);
$$ = 0.;
}
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
if((int)s.value.size() < index + 1){
yymsg(0, "Uninitialized variable '%s[%d]'", $1, index);
$$ = 0.;
}
else{
$$ = s.value[index];
s.value[index] += $5;
}
}
Free($1);
}
// Option Strings
/* not any more ...
| tSTRING '.' tSTRING
{
NumberOption(GMSH_GET, $1, 0, $3, $$);
Free($1); Free($3);
}
*/
//+++ ... extention to structures
// PD: TO FIX (to avoid shift/reduce conflict)
// | Struct_FullName '.' tSTRING_Member_Float
| String__Index '.' tSTRING_Member_Float
{
$$ = treat_Struct_FullName_dot_tSTRING_Float(NULL, $1, $3);
/*
std::string struct_namespace($1.char1? $1.char1 : std::string("")),
struct_name($1.char2);
std::string key_member($3);
switch (nameSpaces.getMember
(struct_namespace, struct_name, key_member, $$)) {
case 0:
break;
case 1:
NumberOption(GMSH_GET, $1.char2, 0, $3, $$);
break;
case 2:
yymsg(0, "Unknown member '%s' of Struct %s", $3, struct_name.c_str());
break;
}
Free($1.char1); Free($1.char2);
if (flag_tSTRING_alloc) Free($3);
*/
}
| String__Index tSCOPE String__Index '.' tSTRING_Member_Float
{
$$ = treat_Struct_FullName_dot_tSTRING_Float($1, $3, $5);
}
| String__Index '[' FExpr ']' '.' tSTRING
{
NumberOption(GMSH_GET, $1, (int)$3, $6, $$);
Free($1); Free($6);
}
| String__Index '.' tSTRING NumericIncrement
{
double d = 0.;
if(NumberOption(GMSH_GET, $1, 0, $3, d)){
d += $4;
NumberOption(GMSH_SET|GMSH_GUI, $1, 0, $3, d);
$$ = d;
}
Free($1); Free($3);
}
| String__Index '[' FExpr ']' '.' tSTRING NumericIncrement
{
double d = 0.;
if(NumberOption(GMSH_GET, $1, (int)$3, $6, d)){
d += $7;
NumberOption(GMSH_SET|GMSH_GUI, $1, (int)$3, $6, d);
$$ = d;
}
Free($1); Free($6);
}
| tGetValue '(' StringExprVar ',' FExpr ')'
{
$$ = Msg::GetValue($3, $5);
Free($3);
}
| tFind '(' ListOfDouble ',' ListOfDouble ')'
{
int matches = 0;
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
matches += List_Search($5, &d, fcmp_double);
}
$$ = matches;
Free($3); Free($5);
}
| tStrFind LP StringExprVar ',' StringExprVar RP
{
std::string s($3), substr($5);
if(s.find(substr) != std::string::npos)
$$ = 1.;
else
$$ = 0.;
Free($3); Free($5);
}
| tStrLen LP StringExprVar RP
{
$$ = strlen($3);
Free($3);
}
| tStrCmp LP StringExprVar ',' StringExprVar RP
{
$$ = strcmp($3, $5);
Free($3); Free($5);
}
| tTextAttributes '(' RecursiveListOfStringExprVar ')'
{
int align = 0, font = 0, fontsize = CTX::instance()->glFontSize;
if(List_Nbr($3) % 2){
yyerror("Number of text attributes should be even");
}
else{
for(int i = 0 ; i < List_Nbr($3); i += 2){
char *s1, *s2; List_Read($3, i, &s1); List_Read($3, i + 1, &s2);
std::string key(s1), val(s2);
Free(s1); Free(s2);
#if defined(HAVE_OPENGL)
if(key == "Font")
font = drawContext::global()->getFontIndex(val.c_str());
else if(key == "FontSize")
fontsize = atoi(val.c_str());
else if(key == "Align")
align = drawContext::global()->getFontAlign(val.c_str());
#endif
}
}
List_Delete($3);
$$ = (double)((align<<16)|(font<<8)|(fontsize));
}
;
DefineStruct :
tDefineStruct Struct_FullName AppendOrNot
{
std::string struct_namespace($2.char1? $2.char1 : std::string("")),
struct_name($2.char2);
init_options
(nameSpaces.getMember_ValMax(struct_namespace, struct_name));
}
'[' FloatParameterOptionsOrNone_NoComma ']'
{
std::string struct_namespace($2.char1? $2.char1 : std::string("")),
struct_name($2.char2);
Free($2.char1); Free($2.char2);
int tag_out;
if (nameSpaces.defStruct(struct_namespace, struct_name,
floatOptions, charOptions,
tag_out, member_ValMax, $3))
yymsg(0, "Redefinition of Struct '%s::%s'",
struct_namespace.c_str(), struct_name.c_str());
$$ = (double)tag_out;
}
;
Struct_FullName :
String__Index
{ $$.char1 = NULL; $$.char2 = $1; }
| String__Index tSCOPE String__Index
{ $$.char1 = $1; $$.char2 = $3; }
;
tSTRING_Member_Float :
tSTRING
{ $$ = $1; flag_tSTRING_alloc = 1; }
/*
| tType
{ $$ = (char*)"Type"; flag_tSTRING_alloc = 0; }
*/
;
Append :
tAppend
{ $$ = 99; } // Default: max level
| tAppend FExpr
{ $$ = (int)$2; }
;
AppendOrNot :
/* none */
{ $$ = 0; }
| '(' Append ')'
{ $$ = $2; }
;
VExpr :
VExpr_Single
{
memcpy($$, $1, 5*sizeof(double));
}
| '-' VExpr %prec UNARYPREC
{
for(int i = 0; i < 5; i++) $$[i] = -$2[i];
}
| '+' VExpr %prec UNARYPREC
{
for(int i = 0; i < 5; i++) $$[i] = $2[i];
}
| VExpr '-' VExpr
{
for(int i = 0; i < 5; i++) $$[i] = $1[i] - $3[i];
}
| VExpr '+' VExpr
{
for(int i = 0; i < 5; i++) $$[i] = $1[i] + $3[i];
}
;
VExpr_Single :
'{' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr '}'
{
$$[0] = $2; $$[1] = $4; $$[2] = $6; $$[3] = $8; $$[4] = $10;
}
| '{' FExpr ',' FExpr ',' FExpr ',' FExpr '}'
{
$$[0] = $2; $$[1] = $4; $$[2] = $6; $$[3] = $8; $$[4] = 1.0;
}
| '{' FExpr ',' FExpr ',' FExpr '}'
{
$$[0] = $2; $$[1] = $4; $$[2] = $6; $$[3] = 0.0; $$[4] = 1.0;
}
| '(' FExpr ',' FExpr ',' FExpr ')'
{
$$[0] = $2; $$[1] = $4; $$[2] = $6; $$[3] = 0.0; $$[4] = 1.0;
}
;
RecursiveListOfListOfDouble :
ListOfDouble
{
$$ = List_Create(2, 1, sizeof(List_T*));
List_Add($$, &($1));
}
| RecursiveListOfListOfDouble ',' ListOfDouble
{
List_Add($$, &($3));
}
;
ListOfDouble :
FExpr
{
$$ = List_Create(2, 1, sizeof(double));
List_Add($$, &($1));
}
| FExpr_Multi
{
$$ = $1;
}
| '{' '}'
{
// creates an empty list
$$ = List_Create(2, 1, sizeof(double));
}
| '{' RecursiveListOfDouble '}'
{
$$ = $2;
}
| '-' '{' RecursiveListOfDouble '}'
{
$$ = $3;
for(int i = 0; i < List_Nbr($$); i++){
double *pd = (double*)List_Pointer($$, i);
(*pd) = - (*pd);
}
}
| FExpr '*' '{' RecursiveListOfDouble '}'
{
$$ = $4;
for(int i = 0; i < List_Nbr($$); i++){
double *pd = (double*)List_Pointer($$, i);
(*pd) *= $1;
}
}
;
ListOfDoubleOrAll :
ListOfDouble
{
$$ = $1;
}
| tBIGSTR
{
if(!strcmp($1, "*") || !strcmp($1, "all"))
$$ = 0;
else{
yyerror("Unknown special string for list replacement");
$$ = List_Create(2, 1, sizeof(double));
}
}
;
FExpr_Multi :
'-' FExpr_Multi %prec UNARYPREC
{
$$ = $2;
for(int i = 0; i < List_Nbr($$); i++){
double *pd = (double*)List_Pointer($$, i);
(*pd) = - (*pd);
}
}
| FExpr '*' FExpr_Multi
{
$$ = $3;
for(int i = 0; i < List_Nbr($$); i++){
double *pd = (double*)List_Pointer($$, i);
(*pd) *= $1;
}
}
| FExpr tDOTS FExpr
{
$$ = List_Create(2, 1, sizeof(double));
for(double d = $1; ($1 < $3) ? (d <= $3) : (d >= $3);
($1 < $3) ? (d += 1.) : (d -= 1.))
List_Add($$, &d);
}
| FExpr tDOTS FExpr tDOTS FExpr
{
$$ = List_Create(2, 1, sizeof(double));
if(!$5){ //|| ($1 < $3 && $5 < 0) || ($1 > $3 && $5 > 0)
yymsg(0, "Wrong increment in '%g:%g:%g'", $1, $3, $5);
}
else
for(double d = $1; ($5 > 0) ? (d <= $3) : (d >= $3); d += $5)
List_Add($$, &d);
}
| tPoint '{' FExpr '}'
{
$$ = List_Create(3, 1, sizeof(double));
int tag = (int)$3;
double x = 0., y = 0., z = 0.;
bool found = GModel::current()->getGEOInternals()->getVertex(tag, x, y, z);
if(!found && GModel::current()->getOCCInternals())
found = GModel::current()->getOCCInternals()->getVertex(tag, x, y, z);
if(!found){
GVertex *gv = GModel::current()->getVertexByTag(tag);
if(gv){
x = gv->x();
y = gv->y();
z = gv->z();
}
else{
yymsg(0, "Unknown model vertex with tag %d", tag);
}
}
List_Add($$, &x);
List_Add($$, &y);
List_Add($$, &z);
}
| tPoint tBIGSTR
{
$$ = List_Create(10, 10, sizeof(double));
getAllElementaryTags(0, $$);
Free($2);
}
| tLine tBIGSTR
{
$$ = List_Create(10, 10, sizeof(double));
getAllElementaryTags(1, $$);
Free($2);
}
| tSurface tBIGSTR
{
$$ = List_Create(10, 10, sizeof(double));
getAllElementaryTags(2, $$);
Free($2);
}
| tVolume tBIGSTR
{
$$ = List_Create(10, 10, sizeof(double));
getAllElementaryTags(3, $$);
Free($2);
}
| tPhysical tPoint ListOfDoubleOrAll
{
$$ = List_Create(10, 10, sizeof(double));
if(!$3){
getAllPhysicalTags(0, $$);
}
else{
getElementaryTagsForPhysicalGroups(0, $3, $$);
List_Delete($3);
}
}
| tPhysical tLine ListOfDoubleOrAll
{
$$ = List_Create(10, 10, sizeof(double));
if(!$3){
getAllPhysicalTags(1, $$);
}
else{
getElementaryTagsForPhysicalGroups(1, $3, $$);
List_Delete($3);
}
}
| tPhysical tSurface ListOfDoubleOrAll
{
$$ = List_Create(10, 10, sizeof(double));
if(!$3){
getAllPhysicalTags(2, $$);
}
else{
getElementaryTagsForPhysicalGroups(2, $3, $$);
List_Delete($3);
}
}
| tPhysical tVolume ListOfDoubleOrAll
{
$$ = List_Create(10, 10, sizeof(double));
if(!$3){
getAllPhysicalTags(3, $$);
}
else{
getElementaryTagsForPhysicalGroups(3, $3, $$);
List_Delete($3);
}
}
| tPoint tIn tBoundingBox
'{' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr '}'
{
$$ = List_Create(10, 10, sizeof(double));
getElementaryTagsInBoundingBox(0, $5, $7, $9, $11, $13, $15, $$);
}
| tLine tIn tBoundingBox
'{' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr '}'
{
$$ = List_Create(10, 10, sizeof(double));
getElementaryTagsInBoundingBox(1, $5, $7, $9, $11, $13, $15, $$);
}
| tSurface tIn tBoundingBox
'{' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr '}'
{
$$ = List_Create(10, 10, sizeof(double));
getElementaryTagsInBoundingBox(2, $5, $7, $9, $11, $13, $15, $$);
}
| tVolume tIn tBoundingBox
'{' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr '}'
{
$$ = List_Create(10, 10, sizeof(double));
getElementaryTagsInBoundingBox(3, $5, $7, $9, $11, $13, $15, $$);
}
| Transform
{
$$ = List_Create(List_Nbr($1), 1, sizeof(double));
for(int i = 0; i < List_Nbr($1); i++){
Shape *s = (Shape*) List_Pointer($1, i);
double d = s->Num;
List_Add($$, &d);
}
List_Delete($1);
}
| Extrude
{
$$ = List_Create(List_Nbr($1), 1, sizeof(double));
for(int i = 0; i < List_Nbr($1); i++){
Shape *s = (Shape*) List_Pointer($1, i);
double d = s->Num;
List_Add($$, &d);
}
List_Delete($1);
}
| Boolean
{
$$ = List_Create(List_Nbr($1), 1, sizeof(double));
for(int i = 0; i < List_Nbr($1); i++){
Shape *s = (Shape*) List_Pointer($1, i);
double d = s->Num;
List_Add($$, &d);
}
List_Delete($1);
}
| String__Index LP RP
{
$$ = List_Create(2, 1, sizeof(double));
if(!gmsh_yysymbols.count($1))
yymsg(0, "Unknown variable '%s'", $1);
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
for(unsigned int i = 0; i < s.value.size(); i++)
List_Add($$, &s.value[i]);
}
Free($1);
}
// for compatibility with GetDP
| tList '[' String__Index ']'
{
$$ = List_Create(2, 1, sizeof(double));
if(!gmsh_yysymbols.count($3))
yymsg(0, "Unknown variable '%s'", $3);
else{
gmsh_yysymbol &s(gmsh_yysymbols[$3]);
for(unsigned int i = 0; i < s.value.size(); i++)
List_Add($$, &s.value[i]);
}
Free($3);
}
| tList '[' FExpr_Multi ']'
{
$$ = $3;
}
| tList '(' FExpr_Multi ')'
{
$$ = $3;
}
| tList LP '{' RecursiveListOfDouble '}' RP
{
$$ = $4;
}
| String__Index LP '{' RecursiveListOfDouble '}' RP
{
$$ = List_Create(2, 1, sizeof(double));
if(!gmsh_yysymbols.count($1))
yymsg(0, "Unknown variable '%s'", $1);
else{
gmsh_yysymbol &s(gmsh_yysymbols[$1]);
for(int i = 0; i < List_Nbr($4); i++){
int index = (int)(*(double*)List_Pointer_Fast($4, i));
if((int)s.value.size() < index + 1)
yymsg(0, "Uninitialized variable '%s[%d]'", $1, index);
else
List_Add($$, &s.value[index]);
}
}
Free($1);
List_Delete($4);
}
| tLinSpace LP FExpr ',' FExpr ',' FExpr RP
{
$$ = List_Create(20,20,sizeof(double));
for(int i = 0; i < (int)$7; i++) {
double d = $3 + ($5-$3)*(double)i/($7-1);
List_Add($$, &d);
}
}
| tLogSpace LP FExpr ',' FExpr ',' FExpr RP
{
$$ = List_Create(20,20,sizeof(double));
for(int i = 0; i < (int)$7; i++) {
double d = pow(10,$3 + ($5-$3)*(double)i/($7-1));
List_Add($$, &d);
}
}
| tListFromFile LP StringExprVar RP
{
Msg::Barrier();
FILE *File;
$$ = List_Create(100, 100, sizeof(double));
std::string tmp = FixRelativePath(gmsh_yyname, $3);
if(!(File = Fopen(tmp.c_str(), "rb"))){
yymsg(0, "Could not open file '%s'", $3);
}
else{
double d;
while(!feof(File)){
int ret = fscanf(File, "%lf", &d);
if(ret == 1){
List_Add($$, &d);
}
else if(ret == EOF){
break;
}
else{
char dummy[1024];
fscanf(File, "%s", dummy);
yymsg(0, "Ignoring '%s' in file '%s'", dummy, $3);
}
}
fclose(File);
}
Free($3);
}
| tCatenary LP FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr ',' FExpr RP
{
double x0 = $3, x1 = $5, y0 = $7, y1 = $9, ys = $11;
int N = (int)$13;
std::vector<double> y(N);
if(!catenary(x0, x1, y0, y1, ys, N, &y[0]))
Msg::Warning("Catenary did not converge, using linear interpolation");
$$ = List_Create(N,10,sizeof(double));
for(int i = 0; i < N; i++) List_Add($$, &y[i]);
}
| tUnique LP FExpr_Multi RP
{
std::vector<double> tmp;
for(int i = 0; i < List_Nbr($3); i++){
double d; List_Read($3, i, &d);
tmp.push_back(d);
}
std::sort(tmp.begin(), tmp.end());
std::vector<double>::iterator last = std::unique(tmp.begin(), tmp.end());
tmp.erase(last, tmp.end());
$$ = $3;
List_Reset($$);
for(unsigned int i = 0; i < tmp.size(); i++){
List_Add($$, &tmp[i]);
}
}
| tAbs LP FExpr_Multi RP
{
for(int i = 0; i < List_Nbr($3); i++){
double *d = (double*)List_Pointer($3, i);
*d = std::abs(*d);
}
$$ = $3;
}
;
RecursiveListOfDouble :
FExpr
{
$$ = List_Create(2, 1, sizeof(double));
List_Add($$, &($1));
}
| FExpr_Multi
{
$$ = $1;
}
| RecursiveListOfDouble ',' FExpr
{
List_Add($$, &($3));
}
| RecursiveListOfDouble ',' FExpr_Multi
{
for(int i = 0; i < List_Nbr($3); i++){
double d;
List_Read($3, i, &d);
List_Add($$, &d);
}
List_Delete($3);
}
;
ColorExpr :
'{' FExpr ',' FExpr ',' FExpr ',' FExpr '}'
{
$$ = CTX::instance()->packColor((int)$2, (int)$4, (int)$6, (int)$8);
}
| '{' FExpr ',' FExpr ',' FExpr '}'
{
$$ = CTX::instance()->packColor((int)$2, (int)$4, (int)$6, 255);
}
/* shift/reduce conflict
| '{' tSTRING ',' FExpr '}'
{
int flag;
$$ = GetColorForString((int)$4, $2, &flag);
if(flag) yymsg(0, "Unknown color '%s'", $2);
}
*/
| String__Index
{
int flag = 0;
if(gmsh_yystringsymbols.count($1)){
if(gmsh_yystringsymbols[$1].size()){
$$ = GetColorForString(-1, gmsh_yystringsymbols[$1][0].c_str(), &flag);
}
else{
yymsg(0, "Unknown color '%s'", $1);
$$ = 0;
}
}
else
$$ = GetColorForString(-1, $1, &flag);
if(flag) yymsg(0, "Unknown color '%s'", $1);
Free($1);
}
| tSTRING '.' tColor '.' tSTRING
{
unsigned int val = 0;
ColorOption(GMSH_GET, $1, 0, $5, val);
$$ = val;
Free($1); Free($5);
}
;
ListOfColor :
'{' RecursiveListOfColor '}'
{
$$ = $2;
}
| String__Index '[' FExpr ']' '.' tColorTable
{
$$ = List_Create(256, 10, sizeof(unsigned int));
GmshColorTable *ct = GetColorTable((int)$3);
if(!ct)
yymsg(0, "View[%d] does not exist", (int)$3);
else{
for(int i = 0; i < ct->size; i++)
List_Add($$, &ct->table[i]);
}
Free($1);
}
;
RecursiveListOfColor :
ColorExpr
{
$$ = List_Create(256, 10, sizeof(unsigned int));
List_Add($$, &($1));
}
| RecursiveListOfColor ',' ColorExpr
{
List_Add($$, &($3));
}
;
StringExprVar :
StringExpr
{
$$ = $1;
}
| String__Index
{
std::string val;
if(!gmsh_yystringsymbols.count($1))
yymsg(0, "Unknown string variable '%s'", $1);
else if(gmsh_yystringsymbols[$1].size() == 1)
val = gmsh_yystringsymbols[$1][0];
else
yymsg(0, "Expected single valued string variable '%s'", $1);
$$ = (char *)Malloc((val.size() + 1) * sizeof(char));
strcpy($$, val.c_str());
Free($1);
}
| String__Index '[' FExpr ']'
{
std::string val;
int j = (int)$3;
if(!gmsh_yystringsymbols.count($1))
yymsg(0, "Unknown string variable '%s'", $1);
else if(j >= 0 && j < (int)gmsh_yystringsymbols[$1].size())
val = gmsh_yystringsymbols[$1][j];
else
yymsg(0, "Index %d out of range", j);
$$ = (char *)Malloc((val.size() + 1) * sizeof(char));
strcpy($$, val.c_str());
Free($1);
}
| String__Index '(' FExpr ')'
{
std::string val;
int j = (int)$3;
if(!gmsh_yystringsymbols.count($1))
yymsg(0, "Unknown string variable '%s'", $1);
else if(j >= 0 && j < (int)gmsh_yystringsymbols[$1].size())
val = gmsh_yystringsymbols[$1][j];
else
yymsg(0, "Index %d out of range", j);
$$ = (char *)Malloc((val.size() + 1) * sizeof(char));
strcpy($$, val.c_str());
Free($1);
}
// PD: TO FIX (to avoid shift/reduce conflict)
// | Struct_FullName '.' String__Index //tSTRING//_Member_Float
| String__Index '.' tSTRING_Member_Float
{
$$ = treat_Struct_FullName_dot_tSTRING_String(NULL, $1, $3);
/*
std::string out;
std::string struct_namespace($1.char1? $1.char1 : std::string("")),
struct_name($1.char2);
std::string key_member($3);
const std::string * out = NULL;
std::string out_tmp; // PD: we should avoid that -> StringOption() to be changed
switch (nameSpaces.getMember
(struct_namespace, struct_name, key_member, out)) {
case 0:
break;
case 1:
StringOption(GMSH_GET, $1, 0, $3, out_tmp);
out = &out_tmp;
break;
case 2:
yymsg(0, "Unknown member '%s' of Struct %s", $3, struct_name.c_str());
break;
}
char* out_c = (char*)Malloc((out->size() + 1) * sizeof(char));
strcpy(out_c, out->c_str());
Free($1.char1); Free($1.char2);
if (flag_tSTRING_alloc) Free(c3);
*/
}
| String__Index tSCOPE String__Index '.' tSTRING_Member_Float
{ $$ = treat_Struct_FullName_dot_tSTRING_String($1, $3, $5); }
| String__Index '[' FExpr ']' '.' tSTRING
{
std::string out;
StringOption(GMSH_GET, $1, (int)$3, $6, out);
$$ = (char*)Malloc((out.size() + 1) * sizeof(char));
strcpy($$, out.c_str());
Free($1); Free($6);
}
| tPhysical tPoint '{' FExpr '}'
{
std::string name = GModel::current()->getPhysicalName(0, (int)$4);
$$ = (char*)Malloc((name.size() + 1) * sizeof(char));
strcpy($$, name.c_str());
}
| tPhysical tLine '{' FExpr '}'
{
std::string name = GModel::current()->getPhysicalName(1, (int)$4);
$$ = (char*)Malloc((name.size() + 1) * sizeof(char));
strcpy($$, name.c_str());
}
| tPhysical tSurface '{' FExpr '}'
{
std::string name = GModel::current()->getPhysicalName(2, (int)$4);
$$ = (char*)Malloc((name.size() + 1) * sizeof(char));
strcpy($$, name.c_str());
}
| tPhysical tVolume '{' FExpr '}'
{
std::string name = GModel::current()->getPhysicalName(3, (int)$4);
$$ = (char*)Malloc((name.size() + 1) * sizeof(char));
strcpy($$, name.c_str());
}
;
StringExpr :
tBIGSTR
{
$$ = $1;
}
| tNameToString '[' String__Index ']'
{
$$ = $3;
}
| tToday
{
$$ = (char *)Malloc(32 * sizeof(char));
time_t now;
time(&now);
strcpy($$, ctime(&now));
$$[strlen($$) - 1] = '\0';
}
| tGmshExecutableName
{
std::string exe = Msg::GetExecutableName();
$$ = (char *)Malloc(exe.size() + 1);
strcpy($$, exe.c_str());
}
| tOnelabAction
{
std::string action = Msg::GetOnelabAction();
$$ = (char *)Malloc(action.size() + 1);
strcpy($$, action.c_str());
}
| tCodeName
{
$$ = strsave((char*)"Gmsh");
}
| tGetEnv '(' StringExprVar ')'
{
const char *env = GetEnvironmentVar($3);
if(!env) env = "";
$$ = (char *)Malloc((sizeof(env) + 1) * sizeof(char));
strcpy($$, env);
Free($3);
}
| tGetStringValue '(' StringExprVar ',' StringExprVar ')'
{
std::string s = Msg::GetString($3, $5);
$$ = (char *)Malloc((s.size() + 1) * sizeof(char));
strcpy($$, s.c_str());
Free($3);
Free($5);
}
| tGetString LP StringExprVar RP
{
std::string s = Msg::GetOnelabString($3);
$$ = (char *)Malloc((s.size() + 1) * sizeof(char));
strcpy($$, s.c_str());
Free($3);
}
| tGetString LP StringExprVar ',' StringExprVar RP
{
std::string s = Msg::GetOnelabString($3, $5);
$$ = (char *)Malloc((s.size() + 1) * sizeof(char));
strcpy($$, s.c_str());
Free($3);
Free($5);
}
| tStrCat LP RecursiveListOfStringExprVar RP
{
int size = 1;
for(int i = 0; i < List_Nbr($3); i++)
size += strlen(*(char**)List_Pointer($3, i)) + 1;
$$ = (char*)Malloc(size * sizeof(char));
$$[0] = '\0';
for(int i = 0; i < List_Nbr($3); i++){
char *s;
List_Read($3, i, &s);
strcat($$, s);
Free(s);
}
List_Delete($3);
}
| tStrPrefix '(' StringExprVar ')'
{
$$ = (char *)Malloc((strlen($3) + 1) * sizeof(char));
int i;
for(i = strlen($3) - 1; i >= 0; i--){
if($3[i] == '.'){
strncpy($$, $3, i);
$$[i]='\0';
break;
}
}
if(i <= 0) strcpy($$, $3);
Free($3);
}
| tStrRelative '(' StringExprVar ')'
{
$$ = (char *)Malloc((strlen($3) + 1) * sizeof(char));
int i;
for(i = strlen($3) - 1; i >= 0; i--){
if($3[i] == '/' || $3[i] == '\\')
break;
}
if(i <= 0)
strcpy($$, $3);
else
strcpy($$, &$3[i+1]);
Free($3);
}
| tStrReplace '(' StringExprVar ',' StringExprVar ',' StringExprVar ')'
{
std::string input = $3;
std::string substr_old = $5;
std::string substr_new = $7;
std::string ret = ReplaceSubString(substr_old, substr_new, input);
$$ = (char *)Malloc((ret.size() + 1) * sizeof(char));
strcpy($$, ret.c_str());
Free($3);
Free($5);
Free($7);
}
| tStr LP RecursiveListOfStringExprVar RP
{
int size = 1;
for(int i = 0; i < List_Nbr($3); i++)
size += strlen(*(char**)List_Pointer($3, i)) + 1;
$$ = (char*)Malloc(size * sizeof(char));
$$[0] = '\0';
for(int i = 0; i < List_Nbr($3); i++){
char *s;
List_Read($3, i, &s);
strcat($$, s);
Free(s);
if(i != List_Nbr($3) - 1) strcat($$, "\n");
}
List_Delete($3);
}
| tUpperCase LP StringExprVar RP
{
int i = 0;
while ($3[i]) {
$3[i] = toupper($3[i]);
i++;
}
$$ = $3;
}
| tLowerCase LP StringExprVar RP
{
int i = 0;
while ($3[i]) {
$3[i] = tolower($3[i]);
i++;
}
$$ = $3;
}
| tLowerCaseIn LP StringExprVar RP
{
int i = 0;
while ($3[i]) {
if (i > 0 && $3[i-1] != '_')
$3[i] = tolower($3[i]);
i++;
}
$$ = $3;
}
| tStrChoice LP FExpr ',' StringExprVar ',' StringExprVar RP
{
if($3){
$$ = $5;
Free($7);
}
else{
$$ = $7;
Free($5);
}
}
| tStrSub LP StringExprVar ',' FExpr ',' FExpr RP
{
std::string in = $3;
std::string out = in.substr((int)$5, (int)$7);
$$ = (char *)Malloc((out.size() + 1) * sizeof(char));
strcpy($$, out.c_str());
Free($3);
}
| tStrSub LP StringExprVar ',' FExpr RP
{
std::string in = $3;
std::string out = in.substr((int)$5, std::string::npos);
$$ = (char *)Malloc((out.size() + 1) * sizeof(char));
strcpy($$, out.c_str());
Free($3);
}
| tSprintf LP StringExprVar RP
{
$$ = $3;
}
| tSprintf LP StringExprVar ',' RecursiveListOfDouble RP
{
char tmpstring[5000];
int i = printListOfDouble($3, $5, tmpstring);
if(i < 0){
yymsg(0, "Too few arguments in Sprintf");
$$ = $3;
}
else if(i > 0){
yymsg(0, "%d extra argument%s in Sprintf", i, (i > 1) ? "s" : "");
$$ = $3;
}
else{
$$ = (char*)Malloc((strlen(tmpstring) + 1) * sizeof(char));
strcpy($$, tmpstring);
Free($3);
}
List_Delete($5);
}
| tFixRelativePath LP StringExprVar RP
{
std::string tmp = FixRelativePath(gmsh_yyname, $3);
$$ = (char*)Malloc((tmp.size() + 1) * sizeof(char));
strcpy($$, tmp.c_str());
Free($3);
}
| tCurrentDirectory
{
std::string tmp = SplitFileName(GetAbsolutePath(gmsh_yyname))[0];
$$ = (char*)Malloc((tmp.size() + 1) * sizeof(char));
strcpy($$, tmp.c_str());
}
| tDirName LP StringExprVar RP
{
std::string tmp = SplitFileName($3)[0];
$$ = (char*)Malloc((tmp.size() + 1) * sizeof(char));
strcpy($$, tmp.c_str());
Free($3);
}
| tAbsolutePath LP StringExprVar RP
{
std::string tmp = GetAbsolutePath($3);
$$ = (char*)Malloc((tmp.size() + 1) * sizeof(char));
strcpy($$, tmp.c_str());
Free($3);
}
| tDefineString LP StringExpr
{ init_options(); }
CharParameterOptionsOrNone RP
{
std::string val($3);
Msg::ExchangeOnelabParameter("", val, floatOptions, charOptions);
$$ = (char*)Malloc((val.size() + 1) * sizeof(char));
strcpy($$, val.c_str());
Free($3);
}
| tNameStruct LP NameStruct_Arg RP
{
std::string out;
const std::string * key_struct = NULL;
switch (nameSpaces.get_key_struct_from_tag(struct_namespace,
(int)$3, key_struct)) {
case 0:
out = *key_struct;
break;
case 1:
yymsg(1, "Unknown NameSpace '%s' of Struct", struct_namespace.c_str());
break;
case 2:
yymsg(1, "Unknown Struct of index %d", (int)$3);
break;
default:
break;
}
$$ = (char*)Malloc((out.size() + 1) * sizeof(char));
strcpy($$, out.c_str());
}
;
NameStruct_Arg :
'#' FExpr
{ struct_namespace = std::string(""); $$ = $2; }
| String__Index tSCOPE '#' FExpr
{ struct_namespace = $1; Free($1); $$ = $4; }
;
RecursiveListOfStringExprVar :
StringExprVar
{
$$ = List_Create(20,20,sizeof(char*));
List_Add($$, &($1));
}
| RecursiveListOfStringExprVar ',' StringExprVar
{
List_Add($$, &($3));
}
;
StringIndex :
tSTRING '~' '{' FExpr '}'
{
char tmpstr[256];
sprintf(tmpstr, "_%d", (int)$4);
$$ = (char *)Malloc((strlen($1)+strlen(tmpstr)+1)*sizeof(char));
strcpy($$, $1); strcat($$, tmpstr);
Free($1);
}
| StringIndex '~' '{' FExpr '}'
{
char tmpstr[256];
sprintf(tmpstr, "_%d", (int)$4);
$$ = (char *)Malloc((strlen($1)+strlen(tmpstr)+1)*sizeof(char)) ;
strcpy($$, $1) ; strcat($$, tmpstr) ;
Free($1);
}
;
String__Index :
tSTRING
{ $$ = $1; }
| StringIndex
{ $$ = $1; }
// Create a name from any string
| tStringToName '[' StringExprVar ']'
{ $$ = $3; }
;
%%
void assignVariable(const std::string &name, int index, int assignType,
double value)
{
if(!gmsh_yysymbols.count(name)){
if(!assignType){
gmsh_yysymbol &s(gmsh_yysymbols[name]);
s.list = true;
s.value.resize(index + 1, 0.);
s.value[index] = value;
}
else
yymsg(0, "Unknown variable '%s'", name.c_str());
}
else{
gmsh_yysymbol &s(gmsh_yysymbols[name]);
if(s.list){
if((int)s.value.size() < index + 1) s.value.resize(index + 1, 0.);
switch(assignType){
case 0 : s.value[index] = value; break;
case 1 : s.value[index] += value; break;
case 2 : s.value[index] -= value; break;
case 3 : s.value[index] *= value; break;
case 4 :
if(value) s.value[index] /= value;
else yymsg(0, "Division by zero in '%s[%d] /= %g'",
name.c_str(), index, value);
break;
}
}
else
yymsg(0, "Variable '%s' is not a list", name.c_str());
}
}
void assignVariables(const std::string &name, List_T *indices, int assignType,
List_T *values)
{
if(List_Nbr(indices) != List_Nbr(values)){
yymsg(0, "Incompatible array dimensions in affectation");
}
else{
if(!gmsh_yysymbols.count(name)){
if(!assignType){
gmsh_yysymbol &s(gmsh_yysymbols[name]);
s.list = true;
for(int i = 0; i < List_Nbr(indices); i++){
int index = (int)(*(double*)List_Pointer(indices, i));
s.value.resize(index + 1, 0.);
s.value[index] = *(double*)List_Pointer(values, i);
}
}
else
yymsg(0, "Unknown variable '%s'", name.c_str());
}
else{
gmsh_yysymbol &s(gmsh_yysymbols[name]);
if(s.list){
for(int i = 0; i < List_Nbr(indices); i++){
int index = (int)(*(double*)List_Pointer(indices, i));
double d = *(double*)List_Pointer(values, i);
if((int)s.value.size() < index + 1) s.value.resize(index + 1, 0.);
switch(assignType){
case 0 : s.value[index] = d; break;
case 1 : s.value[index] += d; break;
case 2 : s.value[index] -= d; break;
case 3 : s.value[index] *= d; break;
case 4 :
if(d) s.value[index] /= d;
else yymsg(0, "Division by zero in '%s[%d] /= %g'", name.c_str(), index, d);
break;
}
}
}
else
yymsg(0, "Variable '%s' is not a list", name.c_str());
}
}
}
void incrementVariable(const std::string &name, int index, double value)
{
if(!gmsh_yysymbols.count(name))
yymsg(0, "Unknown variable '%s'", name.c_str());
else{
gmsh_yysymbol &s(gmsh_yysymbols[name]);
if(s.list){
if((int)s.value.size() < index + 1) s.value.resize(index + 1, 0.);
s.value[index] += value;
}
else
yymsg(0, "Variable '%s' is not a list", name.c_str());
}
}
int printListOfDouble(char *format, List_T *list, char *buffer)
{
// if format does not contain formatting characters, dump the list (useful for
// quick debugging of lists)
int numFormats = 0;
for(unsigned int i = 0; i < strlen(format); i++)
if(format[i] == '%') numFormats++;
if(!numFormats){
strcpy(buffer, format);
for(int i = 0; i < List_Nbr(list); i++){
double d;
List_Read(list, i, &d);
char tmp[256];
sprintf(tmp, " [%d]%g", i, d);
strcat(buffer, tmp);
}
return 0;
}
char tmp1[256], tmp2[256];
int j = 0, k = 0;
buffer[j] = '\0';
while(j < (int)strlen(format) && format[j] != '%') j++;
strncpy(buffer, format, j);
buffer[j] = '\0';
for(int i = 0; i < List_Nbr(list); i++){
k = j;
j++;
if(j < (int)strlen(format)){
if(format[j] == '%'){
strcat(buffer, "%");
j++;
}
while(j < (int)strlen(format) && format[j] != '%') j++;
if(k != j){
strncpy(tmp1, &(format[k]), j-k);
tmp1[j-k] = '\0';
sprintf(tmp2, tmp1, *(double*)List_Pointer(list, i));
strcat(buffer, tmp2);
}
}
else
return List_Nbr(list) - i;
}
if(j != (int)strlen(format))
return -1;
return 0;
}
void PrintParserSymbols(bool help, std::vector<std::string> &vec)
{
if(help){
vec.push_back("//");
vec.push_back("// Numbers");
vec.push_back("//");
}
for(std::map<std::string, gmsh_yysymbol>::iterator it = gmsh_yysymbols.begin();
it != gmsh_yysymbols.end(); it++){
gmsh_yysymbol s(it->second);
std::ostringstream sstream;
sstream.precision(12);
sstream << it->first;
if(s.list){
sstream << "[] = {";
for(unsigned int i = 0; i < s.value.size(); i++){
if(i) sstream << ", ";
sstream << s.value[i];
}
sstream << "}";
}
else
sstream << " = " << s.value[0];
sstream << ";";
vec.push_back(sstream.str());
}
if(help){
vec.push_back("//");
vec.push_back("// Strings");
vec.push_back("//");
}
for(std::map<std::string, std::vector<std::string> >::iterator it =
gmsh_yystringsymbols.begin(); it != gmsh_yystringsymbols.end(); it++){
if(it->second.size() == 1)
vec.push_back(it->first + " = \"" + it->second[0] + "\";");
else{
std::string s = it->first + "[] = Str(";
for(unsigned int i = 0; i < it->second.size(); i++){
if(i) s += ", ";
s += std::string("\"") + it->second[i] + "\"";
}
s += ");";
vec.push_back(s);
}
}
if (nameSpaces.size()){
if(help){
vec.push_back("//");
vec.push_back("// Structures");
vec.push_back("//");
}
std::string s;
nameSpaces.sprint(s);
vec.push_back(s);
}
}
fullMatrix<double> ListOfListOfDouble2Matrix(List_T *list)
{
// Warning: this returns a fullMatrix copy, and deletes the input list
int M = List_Nbr(list);
int N = 0;
for(int i = 0; i < M; i++){
List_T *line = *(List_T**)List_Pointer_Fast(list, i);
N = std::max(N, List_Nbr(line));
}
fullMatrix<double> mat(M, N);
for(int i = 0; i < M; i++){
List_T *line = *(List_T**)List_Pointer_Fast(list, i);
for(int j = 0; j < List_Nbr(line); j++){
double val;
List_Read(line, j, &val);
mat(i, j) = val;
}
}
for(int i = 0; i < List_Nbr(list); i++)
List_Delete(*(List_T**)List_Pointer(list, i));
List_Delete(list);
return mat;
}
void ListOfDouble2Vector(List_T *list, std::vector<int> &v)
{
v.clear();
if(!list) return;
v.reserve(List_Nbr(list));
for(int i = 0; i < List_Nbr(list); i++){
double d;
List_Read(list, i, &d);
v.push_back((int)d);
}
}
void ListOfDouble2Vector(List_T *list, std::vector<double> &v)
{
v.clear();
if(!list) return;
v.reserve(List_Nbr(list));
for(int i = 0; i < List_Nbr(list); i++){
double d;
List_Read(list, i, &d);
v.push_back(d);
}
}
void ListOfShapes2VectorOfPairs(List_T *list, std::vector<std::pair<int, int> > &v)
{
for(int i = 0; i < List_Nbr(list); i++){
Shape s;
List_Read(list, i, &s);
int dim = s.Type / 100 - 1;
if(dim >= 0 && dim <= 3) v.push_back(std::pair<int, int>(dim, s.Num));
}
}
void VectorOfPairs2ListOfShapes(const std::vector<std::pair<int, int> > &v, List_T *list)
{
for(unsigned int i = 0; i < v.size(); i++){
int dim = v[i].first;
int tag = v[i].second;
Shape s;
s.Type = (dim == 3) ? MSH_VOLUME : (dim == 2) ? MSH_SURF_PLAN :
(dim == 1) ? MSH_SEGM_LINE : MSH_POINT;
s.Num = tag;
List_Add(list, &s);
}
}
void yyerror(const char *s)
{
Msg::Error("'%s', line %d : %s (%s)", gmsh_yyname.c_str(), gmsh_yylineno - 1,
s, gmsh_yytext);
gmsh_yyerrorstate++;
}
void yymsg(int level, const char *fmt, ...)
{
va_list args;
char tmp[1024];
va_start(args, fmt);
vsprintf(tmp, fmt, args);
va_end(args);
if(level == 0){
Msg::Error("'%s', line %d : %s", gmsh_yyname.c_str(), gmsh_yylineno - 1, tmp);
gmsh_yyerrorstate++;
}
else if(level == 1){
Msg::Warning("'%s', line %d : %s", gmsh_yyname.c_str(), gmsh_yylineno - 1, tmp);
}
else{
Msg::Info("'%s', line %d : %s", gmsh_yyname.c_str(), gmsh_yylineno - 1, tmp);
}
}
void addPeriodicFace(int iTarget, int iSource,
const std::vector<double>& affineTransform)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
GFace *target = GModel::current()->getFaceByTag(std::abs(iTarget));
GFace *source = GModel::current()->getFaceByTag(std::abs(iSource));
if (!target || !source) {
Msg::Error("Could not find edge slave %d or master %d for periodic copy",
iTarget, iSource);
}
else target->setMeshMaster(source, affineTransform);
}
void addPeriodicFace(int iTarget, int iSource,
const std::map<int,int>& edgeCounterparts)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
Msg::Info("Encoding periodic connection between %d and %d", iTarget, iSource);
std::map<int,int>::const_iterator sIter = edgeCounterparts.begin();
for (; sIter != edgeCounterparts.end(); ++sIter) {
Msg::Info("%d - %d", sIter->first, sIter->second);
}
GFace *target = GModel::current()->getFaceByTag(std::abs(iTarget));
GFace *source = GModel::current()->getFaceByTag(std::abs(iSource));
if (!target || !source) {
Msg::Error("Could not find surface slave %d or master %d for periodic copy",
iTarget,iSource);
}
else target->setMeshMaster(source, edgeCounterparts);
}
void addPeriodicEdge(int iTarget,int iSource,
const std::vector<double>& affineTransform)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
GEdge *target = GModel::current()->getEdgeByTag(std::abs(iTarget));
GEdge *source = GModel::current()->getEdgeByTag(std::abs(iSource));
if (!target || !source)
Msg::Error("Could not find surface %d or %d for periodic copy",
iTarget,iSource);
if (affineTransform.size() >= 12) {
target->setMeshMaster(source, affineTransform);
}
else {
target->setMeshMaster(source, iSource * iTarget < 0 ? -1 : 1);
}
}
void computeAffineTransformation(SPoint3& origin, SPoint3& axis,
double angle, SPoint3& translation,
std::vector<double>& tfo)
{
tfo.resize(16,0.0);
double ca = cos(angle);
double sa = sin(angle);
double ux = axis.x();
double uy = axis.y();
double uz = axis.z();
tfo.resize(16);
tfo[0*4+0] = ca + ux*ux*(1.-ca);
tfo[0*4+1] = ux*uy*(1.-ca) - uz * sa;
tfo[0*4+2] = ux*uz*(1.-ca) + uy * sa;
tfo[1*4+0] = ux*uy*(1.-ca) + uz * sa;
tfo[1*4+1] = ca + uy*uy*(1.-ca);
tfo[1*4+2] = uy*uz*(1.-ca) - ux * sa;
tfo[2*4+0] = ux*uz*(1.-ca) - uy * sa;
tfo[2*4+1] = uy*uz*(1.-ca) + ux * sa;
tfo[2*4+2] = ca + uz*uz*(1.-ca);
int idx = 0;
for (size_t i = 0; i < 3; i++,idx++) {
int tIdx = i*4+3;
tfo[tIdx] = origin[i] + translation[i];
for (int j = 0; j < 3; j++,idx++) tfo[tIdx] -= tfo[idx] * origin[j];
}
for (int i = 0; i < 4; i++) tfo[12+i] = 0;
tfo[15] = 1;
}
void addEmbedded(int dim, std::vector<int> tags, int dim2, int tag2)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
if(dim2 == 2){
GFace *gf = GModel::current()->getFaceByTag(tag2);
if(!gf){
yymsg(0, "Unknown model face with tag %d", tag2);
return;
}
for(unsigned int i = 0; i < tags.size(); i++){
if(dim == 0){
GVertex *gv = GModel::current()->getVertexByTag(tags[i]);
if(gv)
gf->addEmbeddedVertex(gv);
else
yymsg(0, "Unknown model vertex %d", tags[i]);
}
else if(dim == 1){
GEdge *ge = GModel::current()->getEdgeByTag(tags[i]);
if(ge)
gf->addEmbeddedEdge(ge);
else
yymsg(0, "Unknown model edge %d", tags[i]);
}
}
}
else if(dim2 == 3){
GRegion *gr = GModel::current()->getRegionByTag(tag2);
if(!gr){
yymsg(0, "Unknown model region with tag %d", tag2);
return;
}
for(unsigned int i = 0; i < tags.size(); i++){
if(dim == 0){
GVertex *gv = GModel::current()->getVertexByTag(tags[i]);
if(gv)
gr->addEmbeddedVertex(gv);
else
yymsg(0, "Unknown model vertex with tag %d", tags[i]);
}
else if(dim == 1){
GEdge *ge = GModel::current()->getEdgeByTag(tags[i]);
if(ge)
gr->addEmbeddedEdge(ge);
else
yymsg(0, "Unknown model edge with tag %d", tags[i]);
}
else if(dim == 2){
GFace *gf = GModel::current()->getFaceByTag(tags[i]);
if(gf)
gr->addEmbeddedFace(gf);
else
yymsg(0, "Unknown model face with tag %d", tags[i]);
}
}
}
}
void getAllElementaryTags(int dim, List_T *out)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
std::vector<GEntity*> entities;
GModel::current()->getEntities(entities, dim);
for(unsigned int i = 0; i < entities.size(); i++){
double tag = entities[i]->tag();
List_Add(out, &tag);
}
}
void getAllPhysicalTags(int dim, List_T *out)
{
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
std::map<int, std::vector<GEntity*> > groups;
GModel::current()->getPhysicalGroups(dim, groups);
for(std::map<int, std::vector<GEntity*> >::iterator it = groups.begin();
it != groups.end(); it++){
double d = it->first;
List_Add(out, &d);
}
}
void getElementaryTagsForPhysicalGroups(int dim, List_T *in, List_T *out)
{
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
std::map<int, std::vector<GEntity*> > groups;
GModel::current()->getPhysicalGroups(dim, groups);
for(int i = 0; i < List_Nbr(in); i++){
double num;
List_Read(in, i, &num);
std::map<int, std::vector<GEntity*> >::iterator it = groups.find(num);
if(it != groups.end()){
for(unsigned j = 0; j < it->second.size(); j++){
double d = it->second[j]->tag();
List_Add(out, &d);
}
}
}
}
void getElementaryTagsInBoundingBox(int dim, double x1, double y1, double z1,
double x2, double y2, double z2, List_T *out)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
SBoundingBox3d box(x1, y1, z1, x2, y2, z2);
std::vector<GEntity*> entities;
GModel::current()->getEntitiesInBox(entities, box, dim);
for(unsigned int i = 0; i < entities.size(); i++){
double d = entities[i]->tag();
List_Add(out, &d);
}
}
void setVisibility(int dim, int visible, bool recursive)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
std::vector<GEntity*> entities;
GModel::current()->getEntities(entities, dim);
for(unsigned int i = 0; i < entities.size(); i++){
entities[i]->setVisibility(visible);
}
}
void setVisibility(const std::vector<std::pair<int, int> > &dimTags,
int visible, bool recursive)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
for(unsigned int i = 0; i < dimTags.size(); i++){
GEntity *ge = GModel::current()->getEntityByTag
(dimTags[i].first, std::abs(dimTags[i].second));
if(ge) ge->setVisibility(visible, recursive);
}
}
void setColor(const std::vector<std::pair<int, int> > &dimTags,
unsigned int val, bool recursive)
{
if(GModel::current()->getOCCInternals() &&
GModel::current()->getOCCInternals()->getChanged())
GModel::current()->getOCCInternals()->synchronize(GModel::current());
if(GModel::current()->getGEOInternals()->getChanged())
GModel::current()->getGEOInternals()->synchronize(GModel::current());
for(unsigned int i = 0; i < dimTags.size(); i++){
GEntity *ge = GModel::current()->getEntityByTag
(dimTags[i].first, std::abs(dimTags[i].second));
if(ge) ge->setColor(val, recursive);
}
}
int NEWPOINT()
{
int tag = GModel::current()->getGEOInternals()->getMaxTag(0) + 1;
if(GModel::current()->getOCCInternals())
tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(0) + 1);
return tag;
}
int NEWLINE()
{
int tag = 0;
if(CTX::instance()->geom.oldNewreg)
tag = NEWREG();
else
tag = GModel::current()->getGEOInternals()->getMaxTag(1) + 1;
if(GModel::current()->getOCCInternals())
tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(1) + 1);
return tag;
}
int NEWLINELOOP()
{
int tag = 0;
if(CTX::instance()->geom.oldNewreg)
tag = NEWREG();
else
tag = GModel::current()->getGEOInternals()->getMaxTag(-1) + 1;
if(GModel::current()->getOCCInternals())
tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(-1) + 1);
return tag;
}
int NEWSURFACE()
{
int tag = 0;
if(CTX::instance()->geom.oldNewreg)
tag = NEWREG();
else
tag = GModel::current()->getGEOInternals()->getMaxTag(2) + 1;
if(GModel::current()->getOCCInternals())
tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(2) + 1);
return tag;
}
int NEWSURFACELOOP()
{
int tag = 0;
if(CTX::instance()->geom.oldNewreg)
tag = NEWREG();
else
tag = GModel::current()->getGEOInternals()->getMaxTag(-2) + 1;
if(GModel::current()->getOCCInternals())
tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(-2) + 1);
return tag;
}
int NEWVOLUME()
{
int tag = 0;
if(CTX::instance()->geom.oldNewreg)
tag = NEWREG();
else
tag = GModel::current()->getGEOInternals()->getMaxTag(3) + 1;
if(GModel::current()->getOCCInternals())
tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(3) + 1);
return tag;
}
int NEWREG()
{
int tag = 0;
for(int dim = -2; dim <= 3; dim++){
if(dim)
tag = std::max(tag, GModel::current()->getGEOInternals()->getMaxTag(dim) + 1);
}
tag = std::max(tag, GModel::current()->getGEOInternals()->getMaxPhysicalTag() + 1);
if(GModel::current()->getOCCInternals()){
for(int dim = -2; dim <= 3; dim++){
if(dim)
tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(dim) + 1);
}
}
return tag;
}
int NEWFIELD()
{
#if defined(HAVE_MESH)
return (GModel::current()->getFields()->maxId() + 1);
#else
return 0;
#endif
}
int NEWPHYSICAL()
{
if(CTX::instance()->geom.oldNewreg)
return NEWREG();
else
return (GModel::current()->getGEOInternals()->getMaxPhysicalTag() + 1);
}
double treat_Struct_FullName_dot_tSTRING_Float(char* c1, char* c2, char* c3)
{
double out;
std::string struct_namespace(c1? c1 : std::string("")),
struct_name(c2);
/*
std::string struct_namespace($1.char1? $1.char1 : std::string("")),
struct_name($1.char2);
*/
std::string key_member(c3);
switch (nameSpaces.getMember
(struct_namespace, struct_name, key_member, out)) {
case 0:
break;
case 1:
NumberOption(GMSH_GET, c2, 0, c3, out);
break;
case 2:
yymsg(0, "Unknown member '%s' of Struct %s", c3, struct_name.c_str());
break;
}
Free(c1); Free(c2);
if (flag_tSTRING_alloc) Free(c3);
return out;
}
char* treat_Struct_FullName_dot_tSTRING_String(char* c1, char* c2, char* c3)
{
std::string struct_namespace(c1? c1 : std::string("")),
struct_name(c2);
/*
std::string struct_namespace($1.char1? $1.char1 : std::string("")),
struct_name($1.char2);
*/
std::string key_member(c3);
const std::string * out = NULL;
std::string out_tmp; // PD: we should avoid that -> StringOption() to be changed
switch (nameSpaces.getMember
(struct_namespace, struct_name, key_member, out)) {
case 0:
break;
case 1:
StringOption(GMSH_GET, c2, 0, c3, out_tmp);
out = &out_tmp;
break;
case 2:
yymsg(0, "Unknown member '%s' of Struct %s", c3, struct_name.c_str());
break;
}
char* out_c = (char*)Malloc((out->size() + 1) * sizeof(char));
strcpy(out_c, out->c_str());
Free(c1); Free(c2);
if (flag_tSTRING_alloc) Free(c3);
return out_c;
}