1 /* -*-c++-*- Producer - Copyright (C) 2001-2004  Don Burns
2  *
3  * This library is open source and may be redistributed and/or modified under
4  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5  * (at your option) any later version.  The full license is in LICENSE file
6  * included with this distribution, and on the openscenegraph.org website.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * OpenSceneGraph Public License for more details.
12  */
13 
14 
15 %{
16 
17 #ifndef WIN32
18 #include <unistd.h>
19 #include <sys/wait.h>
20 #include <stdlib.h>
21 #include <fcntl.h>
22 #endif
23 
24 #ifndef WIN32
25 #define SUPPORT_CPP 1
26 #endif
27 
28 #include <stdio.h>
29 #include <fstream>
30 #include <string>
31 
32 #include "FlexLexer.h"
33 
34 #include <Producer/CameraConfig>
35 
36 
37 using namespace std;
38 using namespace Producer;
39 
40 static void ConfigParser_error( const char * );
41 static CameraConfig *cfg = 0L;
42 static std::string fileName = "(stdin)";
43 
44 static yyFlexLexer *flexer = 0L;
45 
yylex()46 static int yylex()
47 {
48     if( flexer == 0L )
49         fprintf( stderr, "Internal error!\n" );
50     return flexer->yylex();
51 }
52 
53 %}
54 
55 %token PRTOKEN_VISUAL
56 %token PRTOKEN_SET_SIMPLE
57 %token PRTOKEN_VISUAL_ID
58 %token PRTOKEN_BUFFER_SIZE
59 %token PRTOKEN_LEVEL
60 %token PRTOKEN_RGBA
61 %token PRTOKEN_DOUBLEBUFFER
62 %token PRTOKEN_STEREO
63 %token PRTOKEN_AUX_BUFFERS
64 %token PRTOKEN_RED_SIZE
65 %token PRTOKEN_GREEN_SIZE
66 %token PRTOKEN_BLUE_SIZE
67 %token PRTOKEN_ALPHA_SIZE
68 %token PRTOKEN_DEPTH_SIZE
69 %token PRTOKEN_STENCIL_SIZE
70 %token PRTOKEN_ACCUM_RED_SIZE
71 %token PRTOKEN_ACCUM_GREEN_SIZE
72 %token PRTOKEN_ACCUM_BLUE_SIZE
73 %token PRTOKEN_ACCUM_ALPHA_SIZE
74 %token PRTOKEN_ACCUM_ALPHA_SIZE
75 %token PRTOKEN_SAMPLES
76 %token PRTOKEN_SAMPLE_BUFFERS
77 %token PRTOKEN_RENDER_SURFACE
78 %token PRTOKEN_WINDOW_RECT
79 %token PRTOKEN_INPUT_RECT
80 %token PRTOKEN_HOSTNAME
81 %token PRTOKEN_DISPLAY
82 %token PRTOKEN_SCREEN
83 %token PRTOKEN_BORDER
84 %token PRTOKEN_DRAWABLE_TYPE
85 %token PRTOKEN_WINDOW_TYPE
86 %token PRTOKEN_PBUFFER_TYPE
87 %token PRTOKEN_CAMERA_GROUP
88 %token PRTOKEN_CAMERA
89 %token PRTOKEN_PROJECTION_RECT
90 %token PRTOKEN_LENS
91 %token PRTOKEN_FRUSTUM
92 %token PRTOKEN_PERSPECTIVE
93 %token PRTOKEN_ORTHO
94 %token PRTOKEN_OFFSET
95 %token PRTOKEN_ROTATE
96 %token PRTOKEN_TRANSLATE
97 %token PRTOKEN_SCALE
98 %token PRTOKEN_SHEAR
99 %token PRTOKEN_CLEAR_COLOR
100 %token PRTOKEN_INPUT_AREA
101 %token PRTOKEN_ERROR
102 %token PRTOKEN_INTEGER
103 %token PRTOKEN_HEX_INTEGER
104 %token PRTOKEN_FLOAT
105 %token PRTOKEN_TRUE
106 %token PRTOKEN_FALSE
107 %token PRTOKEN_QUOTED_STRING
108 %token PRTOKEN_STEREO_SYSTEM_COMMANDS
109 %token PRTOKEN_CUSTOM_FULL_SCREEN_RECTANGLE
110 %token PRTOKEN_METHOD
111 %token PRTOKEN_PREMULTIPLY
112 %token PRTOKEN_POSTMULTIPLY
113 %token PRTOKEN_OVERRIDE_REDIRECT
114 %token PRTOKEN_SHARELENS
115 %token PRTOKEN_SHAREVIEW
116 %token PRTOKEN_READ_DRAWABLE
117 %token PRTOKEN_SET_RTT_MODE
118 %token PRTOKEN_RTT_MODE_NONE
119 %token PRTOKEN_RTT_MODE_RGB
120 %token PRTOKEN_RTT_MODE_RGBA
121 %token PRTOKEN_THREAD_MODEL
122 %token PRTOKEN_SINGLE_THREADED
123 %token PRTOKEN_THREAD_PER_CAMERA
124 %token PRTOKEN_THREAD_PER_RENDER_SURFACE
125 
126 %union {
127     char * string;
128     int    integer;
129     float  real;
130     bool boolean;
131 };
132 
133 %type <string> name string;
134 %type <integer> intparam offset_multiply_method;
135 %type <integer> hex_integer;
136 %type <integer> drawableType rtt_mode;
137 %type <integer> threadModelDirective;
138 %type <real>    floatparam;
139 %type <real>    real;
140 %type <boolean> bool;
141 
142 %%
143 
144 config  : entries
145     ;
146 
147 entries : entry | entries entry
148     ;
149 
150 entry : visual | render_surface | camera | input_area | camera_group | stereo_param | system_params
151     ;
152 
153 system_params : system_param | system_params system_param
154     ;
155 
156 system_param :
157         PRTOKEN_THREAD_MODEL threadModelDirective ';'
158         {
159             Producer::CameraGroup::ThreadModel tm = (Producer::CameraGroup::ThreadModel)$2;
160             cfg->setThreadModelDirective( tm );
161         }
162         ;
163 
164 threadModelDirective:
165           PRTOKEN_SINGLE_THREADED               { $$ = CameraGroup::SingleThreaded; }
166         | PRTOKEN_THREAD_PER_CAMERA             { $$ = CameraGroup::ThreadPerCamera; }
167         | PRTOKEN_THREAD_PER_RENDER_SURFACE     { $$ = CameraGroup::ThreadPerRenderSurface; }
168         ;
169 
170 stereo_param : PRTOKEN_STEREO_SYSTEM_COMMANDS intparam string string ';'
171         {
172            cfg->addStereoSystemCommand( $2, $3, $4 );
173         };
174 
175 
176 camera_group: PRTOKEN_CAMERA_GROUP '{' camera_group_attributes '}'
177     ;
178 
179 camera_group_attributes: cameras
180     ;
181 
182 cameras :  /* null */ | camera | cameras camera
183     ;
184 
185 camera : PRTOKEN_CAMERA name
186      {
187         cfg->beginCamera( $2 );
188      }
189     '{' camera_attributes '}'
190      {
191         cfg->endCamera();
192      };
193 
194 camera_attributes : camera_attribute | camera_attributes camera_attribute
195      ;
196 
197 camera_attribute :
198     /* EMPTY */
199     | PRTOKEN_RENDER_SURFACE name ';'
200     {
201         cfg->setCameraRenderSurface( $2 );
202     }
203     | render_surface
204     {
205         cfg->setCameraRenderSurface();
206     }
207     | PRTOKEN_PROJECTION_RECT real real real real ';'
208     {
209         cfg->setCameraProjectionRectangle( $2, $3, $4, $5 );
210     }
211     | PRTOKEN_SHARELENS bool ';'
212     {
213         cfg->setCameraShareLens( $2 );
214     }
215     | PRTOKEN_SHAREVIEW bool ';'
216     {
217         cfg->setCameraShareView( $2 );
218     }
219     | PRTOKEN_CLEAR_COLOR real real real real ';'
220     {
221         cfg->setCameraClearColor( $2, $3, $4, $5 );
222     }
223     | lens
224     | camera_offset
225     ;
226 
227 camera_offset : PRTOKEN_OFFSET '{'
228     {
229         cfg->beginCameraOffset();
230     }
231         camera_offset_attributes '}'
232     {
233         cfg->endCameraOffset();
234     }
235     ;
236 
237 camera_offset_attributes : camera_offset_attribute | camera_offset_attributes camera_offset_attribute
238     ;
239 
240 camera_offset_attribute  :
241       PRTOKEN_SHEAR real real ';'
242       {
243         cfg->shearCameraOffset( $2, $3 );
244       }
245     | PRTOKEN_ROTATE real real real real ';'
246       {
247         cfg->rotateCameraOffset( $2, $3, $4, $5 );
248       }
249     | PRTOKEN_TRANSLATE real real real ';'
250       {
251         cfg->translateCameraOffset( $2, $3, $4 );
252       }
253     | PRTOKEN_SCALE real real real ';'
254       {
255         cfg->scaleCameraOffset( $2, $3, $4 );
256       }
257     | PRTOKEN_METHOD offset_multiply_method ';'
258       {
259         cfg->setCameraOffsetMultiplyMethod( (Producer::Camera::Offset::MultiplyMethod)$2 );
260       }
261     ;
262 
263 offset_multiply_method:
264       PRTOKEN_PREMULTIPLY  { $$ = Producer::Camera::Offset::PreMultiply; }
265     | PRTOKEN_POSTMULTIPLY { $$ = Producer::Camera::Offset::PostMultiply; }
266     ;
267 
268 lens : PRTOKEN_LENS '{' lens_attributes '}'
269     ;
270 
271 lens_attributes : lens_attribute | lens_attributes lens_attribute
272     ;
273 
274 lens_attribute :
275     /* Empty */
276     | PRTOKEN_ORTHO real real real real real real ';'
277       {
278           cfg->setCameraOrtho( $2, $3, $4, $5, $6, $7 );
279       }
280     | PRTOKEN_ORTHO real real real real real real real real ';'
281       {
282           cfg->setCameraOrtho( $2, $3, $4, $5, $6, $7, $8, $9 );
283       }
284     | PRTOKEN_PERSPECTIVE real real real real ';'
285       {
286           cfg->setCameraPerspective( $2, $3, $4, $5 );
287       }
288     | PRTOKEN_PERSPECTIVE real real real real real real ';'
289       {
290           cfg->setCameraPerspective( $2, $3, $4, $5, $6, $7 );
291       }
292     | PRTOKEN_FRUSTUM real real real real real real ';'
293       {
294           cfg->setCameraFrustum( $2, $3, $4, $5, $6, $7 );
295       }
296     | PRTOKEN_FRUSTUM real real real real real real real real ';'
297       {
298           cfg->setCameraFrustum( $2, $3, $4, $5, $6, $7, $8, $9 );
299       }
300     | PRTOKEN_SHEAR real real ';'
301       {
302           cfg->setCameraLensShear( $2, $3 );
303       }
304     ;
305 
306 render_surface : PRTOKEN_RENDER_SURFACE name
307      {
308          cfg->beginRenderSurface( $2 );
309      }
310      '{' render_surface_attributes '}'
311      {
312          cfg->endRenderSurface();
313      }
314     ;
315 
316 render_surface_attributes :
317           render_surface_attribute
318         | render_surface_attributes render_surface_attribute
319     ;
320 
321 render_surface_attribute :
322     /* Empty */
323     | PRTOKEN_VISUAL name ';'
324     {
325         cfg->setRenderSurfaceVisualChooser( $2 );
326     }
327     | visual
328     {
329         cfg->setRenderSurfaceVisualChooser();
330     }
331     | PRTOKEN_WINDOW_RECT intparam  intparam  intparam  intparam ';'
332     {
333         cfg->setRenderSurfaceWindowRectangle( $2, $3, $4, $5 );
334     }
335     | PRTOKEN_INPUT_RECT floatparam floatparam floatparam floatparam ';'
336     {
337         cfg->setRenderSurfaceInputRectangle( $2, $3, $4, $5 );
338     }
339     | PRTOKEN_HOSTNAME name ';'
340     {
341         cfg->setRenderSurfaceHostName( std::string($2) );
342     }
343     | PRTOKEN_DISPLAY intparam ';'
344     {
345         cfg->setRenderSurfaceDisplayNum( $2 );
346     }
347     | PRTOKEN_SCREEN intparam ';'
348     {
349         cfg->setRenderSurfaceScreen( $2 );
350     }
351     | PRTOKEN_BORDER bool ';'
352     {
353         cfg->setRenderSurfaceBorder( $2 );
354     }
355     | PRTOKEN_CUSTOM_FULL_SCREEN_RECTANGLE intparam  intparam  intparam  intparam ';'
356     {
357         cfg->setRenderSurfaceCustomFullScreenRectangle( $2, $3, $4, $5 );
358     }
359     | PRTOKEN_OVERRIDE_REDIRECT bool ';'
360     {
361         cfg->setRenderSurfaceOverrideRedirect( $2 );
362     }
363     | PRTOKEN_DRAWABLE_TYPE drawableType ';'
364     {
365         Producer::RenderSurface::DrawableType drawableType = (RenderSurface::DrawableType)$2;
366         cfg->setRenderSurfaceDrawableType( drawableType );
367     }
368     | PRTOKEN_READ_DRAWABLE name ';'
369     {
370         cfg->setRenderSurfaceReadDrawable( $2 );
371     }
372     | PRTOKEN_SET_RTT_MODE rtt_mode ';'
373     {
374         cfg->setRenderSurfaceRenderToTextureMode( (Producer::RenderSurface::RenderToTextureMode)$2 );
375     }
376     ;
377 
378 drawableType:
379       PRTOKEN_WINDOW_TYPE   { $$ =  RenderSurface::DrawableType_Window; }
380     | PRTOKEN_PBUFFER_TYPE  { $$ =  RenderSurface::DrawableType_PBuffer; }
381     ;
382 
383 rtt_mode :
384           PRTOKEN_RTT_MODE_NONE  { $$ = RenderSurface::RenderToTextureMode_None; }
385         | PRTOKEN_RTT_MODE_RGB   { $$ = RenderSurface::RenderToRGBTexture; }
386         | PRTOKEN_RTT_MODE_RGBA  { $$ = RenderSurface::RenderToRGBATexture; }
387         ;
388 
389 
390 visual : PRTOKEN_VISUAL name
391      {
392          cfg->beginVisual( $2 );
393      }
394     '{' visual_attributes '}'
395      {
396          cfg->endVisual();
397      }
398 
399      | PRTOKEN_VISUAL
400      {
401          cfg->beginVisual();
402      }
403     '{' visual_attributes '}'
404      {
405          cfg->endVisual();
406      }
407      ;
408 
409 
410 visual_attributes : visual_attribute | visual_attributes ',' visual_attribute
411     ;
412 visual_attribute :
413       PRTOKEN_SET_SIMPLE
414       {
415           cfg->setVisualSimpleConfiguration();
416       }
417     | PRTOKEN_VISUAL_ID hex_integer
418       {
419           cfg->setVisualByID( $2 );
420       }
421 
422     | PRTOKEN_BUFFER_SIZE intparam
423       {
424           cfg->addVisualAttribute( VisualChooser::BufferSize, $2 );
425       }
426     | PRTOKEN_LEVEL intparam
427       {
428           cfg->addVisualAttribute( VisualChooser::Level, $2 );
429       }
430 
431     | PRTOKEN_RGBA
432       {
433           cfg->addVisualAttribute( VisualChooser::RGBA );
434       }
435     | PRTOKEN_DOUBLEBUFFER
436       {
437           cfg->addVisualAttribute( VisualChooser::DoubleBuffer );
438       }
439     | PRTOKEN_STEREO
440       {
441           cfg->addVisualAttribute( VisualChooser::Stereo );
442       }
443     | PRTOKEN_AUX_BUFFERS intparam
444       {
445           cfg->addVisualAttribute( VisualChooser::AuxBuffers, $2 );
446       }
447     | PRTOKEN_RED_SIZE intparam
448       {
449           cfg->addVisualAttribute( VisualChooser::RedSize, $2 );
450       }
451 
452     | PRTOKEN_GREEN_SIZE   intparam
453       {
454           cfg->addVisualAttribute( VisualChooser::GreenSize, $2 );
455       }
456 
457     | PRTOKEN_BLUE_SIZE intparam
458       {
459           cfg->addVisualAttribute( VisualChooser::BlueSize, $2 );
460       }
461     | PRTOKEN_ALPHA_SIZE  intparam
462       {
463           cfg->addVisualAttribute( VisualChooser::AlphaSize, $2 );
464       }
465     | PRTOKEN_DEPTH_SIZE  intparam
466       {
467           cfg->addVisualAttribute( VisualChooser::DepthSize, $2 );
468       }
469     | PRTOKEN_STENCIL_SIZE  intparam
470       {
471           cfg->addVisualAttribute( VisualChooser::StencilSize, $2 );
472       }
473     | PRTOKEN_ACCUM_RED_SIZE  intparam
474       {
475           cfg->addVisualAttribute( VisualChooser::AccumRedSize, $2 );
476       }
477     | PRTOKEN_ACCUM_GREEN_SIZE  intparam
478       {
479           cfg->addVisualAttribute( VisualChooser::AccumGreenSize, $2 );
480       }
481     | PRTOKEN_ACCUM_BLUE_SIZE  intparam
482       {
483           cfg->addVisualAttribute( VisualChooser::AccumBlueSize, $2 );
484       }
485     | PRTOKEN_ACCUM_ALPHA_SIZE  intparam
486       {
487           cfg->addVisualAttribute( VisualChooser::AccumAlphaSize, $2 );
488       }
489     | PRTOKEN_SAMPLES  intparam
490       {
491           cfg->addVisualAttribute( VisualChooser::Samples, $2 );
492       }
493     | PRTOKEN_SAMPLE_BUFFERS
494       {
495           cfg->addVisualAttribute( VisualChooser::SampleBuffers );
496       }
497     | intparam intparam
498       {
499           cfg->addVisualExtendedAttribute( $1, $2 );
500       }
501       ;
502 
503 input_area : PRTOKEN_INPUT_AREA
504             { cfg->beginInputArea(); }
505             '{' input_area_entries '}'
506             { cfg->endInputArea(); }
507     ;
508 
509 input_area_entries : input_area_entry | input_area_entries input_area_entry
510     ;
511 
512 input_area_entry :
513         PRTOKEN_RENDER_SURFACE name ';'
514         {
515             cfg->addInputAreaEntry( $2 );
516         }
517         ;
518 
519 real   : PRTOKEN_FLOAT
520     {
521         $$ = osg::asciiToFloat(flexer->YYText());
522     }
523     | PRTOKEN_INTEGER
524     {
525         $$ = osg::asciiToFloat(flexer->YYText());
526     }
527     ;
528 
529 
530 floatparam : PRTOKEN_FLOAT
531     {
532         $$ = osg::asciiToFloat(flexer->YYText());
533     }
534     ;
535 
536 intparam : PRTOKEN_INTEGER
537     {
538         $$ = atoi( flexer->YYText() );
539     }
540     ;
541 
542 name : PRTOKEN_QUOTED_STRING
543     {
544         $$ = strdup( flexer->YYText() );
545     }
546     ;
547 
548 string : PRTOKEN_QUOTED_STRING
549     {
550         $$ = strdup( flexer->YYText() );
551     }
552     ;
553 
554 
555 hex_integer : PRTOKEN_HEX_INTEGER
556     {
557         int n;
558         sscanf( flexer->YYText(), "0x%x", &n );
559         $$ = n;
560     }
561     ;
562 
563 bool : PRTOKEN_TRUE { $$ = true;} | PRTOKEN_FALSE { $$ = false; }
564     ;
565 
566 %%
567 
568 static void yyerror( const char *errmsg )
569 {
570     fprintf( stderr,
571         "CameraConfig::parseFile(\"%s\") : %s - Line %d at or before \"%s\"\n",
572         fileName.c_str(),
573         errmsg,
574         flexer->lineno(),
575         flexer->YYText() );
576 }
577 
parseFile(const std::string & file)578 bool CameraConfig::parseFile( const std::string &file )
579 {
580     fileName.clear();
581 
582     fileName = findFile(file);
583 
584     if( fileName.empty() )
585     {
586         fprintf( stderr, "CameraConfig::parseFile() - Can't find file \"%s\".\n", file.c_str() );
587         return false;
588     }
589 
590     bool retval = true;
591 
592 #if defined (SUPPORT_CPP)
593 
594     char *cpp_path =
595   #if defined(__APPLE__)
596                 "/usr/bin/cpp";
597   #else
598                 "/lib/cpp";
599   #endif
600 
601     if( access( cpp_path, X_OK ) == 0 )
602     {
603 
604         int pd[2];
605         pipe( pd );
606 
607         flexer = new yyFlexLexer;
608         if( fork() == 0 )
609         {
610             // we don't want to read from the pipe in the child, so close it.
611             close( pd[0] );
612             close( 1 );
613             dup( pd[1] );
614 
615 
616             /* This was here to allow reading a config file from stdin.
617              * This has never been directly supported, so commenting out.
618             if( fileName.empty() )
619                 execlp( cpp_path, "cpp",  "-P", 0L );
620             else
621             */
622             execlp( cpp_path, "cpp",  "-P", fileName.c_str(), 0L );
623 
624             // This should not execute unless an error happens
625             perror( "execlp" );
626         }
627         else
628         {
629             close( pd[1]);
630             close( 0 );
631             dup( pd[0] );
632 
633             cfg = this;
634 
635             retval = ConfigParser_parse() == 0 ? true : false;
636 
637             // Wait on child process to finish
638             int stat;
639             wait( &stat );
640         }
641     }
642     else
643 #endif
644     {
645         std::ifstream ifs(fileName.c_str());
646         flexer = new yyFlexLexer(&ifs);
647         cfg = this;
648         retval = ConfigParser_parse() == 0 ? true : false;
649         ifs.close();
650         delete flexer;
651     }
652     return retval;
653 }
654 
655