1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: ParseOGLExt.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 /* A program that will read in OpenGL extension header files and output VTK
16 * code that handles extensions in a more platform-independent manner.
17 */
18
19
20 /*
21 * Copyright 2003 Sandia Corporation.
22 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
23 * license for use of this work by or on behalf of the
24 * U.S. Government. Redistribution and use in source and binary forms, with
25 * or without modification, are permitted provided that this Notice and any
26 * statement of authorship are reproduced on all copies.
27 */
28
29 #include "vtkSystemIncludes.h"
30
31 #include "Tokenizer.h"
32
33 #include <list>
34 #include <set>
35 #include <map>
36
37 #include <string.h>
38 #include <ctype.h>
39
40 // #define this if you want debug output as the parser does its work
41
42 // #define DEBUG_PARSE
43
44 static std::set< std::pair< std::string, std::string > > ConstantsAlreadyWritten;
45
ToUpper(std::string s)46 static std::string ToUpper(std::string s)
47 {
48 std::string u;
49
50 for (std::string::size_type i = 0; i < s.length(); i++)
51 {
52 u.append(1, static_cast<char>(toupper(s[i])));
53 }
54
55 return u;
56 }
57
58 class Extension {
59 public:
GetName() const60 std::string GetName() const { return this->name; }
61 enum {GL, WGL, GLX} type;
62
Extension()63 Extension() {}
64 Extension(char *line);
65 static bool isExtension(char *line);
66
WriteSupportWrapperBegin(ostream & out,int itype)67 static inline void WriteSupportWrapperBegin(ostream &out, int itype) {
68 switch (itype)
69 {
70 case WGL:
71 out << "#ifdef WIN32" << endl;
72 break;
73 case GLX:
74 out << "#ifdef VTK_USE_X" << endl;
75 break;
76 case GL:
77 break;
78 }
79 }
WriteSupportWrapperBegin(ostream & out) const80 inline void WriteSupportWrapperBegin(ostream &out) const {
81 WriteSupportWrapperBegin(out, this->type);
82 }
WriteSupportWrapperEnd(ostream & out,int itype)83 static inline void WriteSupportWrapperEnd(ostream &out, int itype) {
84 if ((itype == WGL) || (itype == GLX))
85 {
86 out << "#endif" << endl;
87 }
88 }
WriteSupportWrapperEnd(ostream & out) const89 inline void WriteSupportWrapperEnd(ostream &out) const {
90 WriteSupportWrapperEnd(out, this->type);
91 }
92
TypeToCapString(int t)93 static inline const char *TypeToCapString(int t) {
94 switch (t)
95 {
96 case GL: return "GL";
97 case GLX: return "GLX";
98 case WGL: return "WGL";
99 }
100 return NULL;
101 }
TypeToString(int t)102 static inline const char *TypeToString(int t) {
103 switch (t)
104 {
105 case GL: return "gl";
106 case GLX: return "glX";
107 case WGL: return "wgl";
108 }
109 return NULL;
110 }
111
operator <(const Extension & obj) const112 bool operator<(const Extension &obj) const { return this->name < obj.name; }
113
114 protected:
115 std::string name;
116 };
117
Extension(char * line)118 Extension::Extension(char *line)
119 {
120 Tokenizer t(line);
121
122 t.GetNextToken();
123
124 this->name = t.GetNextToken();
125
126 Tokenizer nameTokens(this->name, "_");
127 std::string header = nameTokens.GetNextToken();
128 if (header == "WGL")
129 {
130 this->type = WGL;
131 }
132 else if (header == "GLX")
133 {
134 this->type = GLX;
135 }
136 else
137 {
138 this->type = GL;
139 }
140 }
141
isExtension(char * line)142 bool Extension::isExtension(char *line)
143 {
144 Tokenizer t(line);
145
146 if (t.GetNextToken() != "#ifndef") return false;
147
148 Tokenizer nameTokens(t.GetNextToken(), "_");
149 std::string header = nameTokens.GetNextToken();
150 if ((header == "GL") || (header == "WGL") || (header == "GLX"))
151 {
152 return true;
153 }
154
155 return false;
156 }
157
158 static Extension currentExtension;
159
160 class Constant {
161 public:
GetName() const162 std::string GetName() const { return this->name; }
163 std::string GetValue() const;
164
165 Constant(char *line);
166 static bool isConstant(char *line);
167
operator <(const Constant & obj) const168 bool operator<(const Constant &obj) const { return this->name < obj.name; }
169
170 protected:
171 std::string name;
172 std::string value;
173 };
174
175 static std::map<std::string, std::string> EncounteredConstants;
176
Constant(char * line)177 Constant::Constant(char *line)
178 {
179 // Assumes isConstant is true.
180 Tokenizer t(line);
181
182 t.GetNextToken();
183
184 this->name = t.GetNextToken();
185 std::string fullname = this->name;
186 if (currentExtension.type == Extension::GL)
187 {
188 // Skip the "GL_"
189 this->name = this->name.substr(3);
190 }
191 else
192 {
193 // Skip the "GLX_" or "WGL_"
194 this->name = this->name.substr(4);
195 }
196 // Make sure name does not start with a numeric.
197 if ((this->name[0] >= '0') && (this->name[0] <= '9'))
198 {
199 this->name = '_' + this->name;
200 }
201
202 this->value = t.GetNextToken();
203
204 // Now record this as found.
205 EncounteredConstants[fullname] = this->value;
206 }
207
GetValue() const208 std::string Constant::GetValue() const
209 {
210 // Sometimes, one constant points to another. Handle this properly.
211 std::map<std::string, std::string>::iterator found
212 = EncounteredConstants.find(this->value);
213 if (found != EncounteredConstants.end())
214 {
215 return found->second;
216 }
217 return this->value;
218 }
219
isConstant(char * line)220 bool Constant::isConstant(char *line)
221 {
222 Tokenizer t(line);
223
224 if (t.GetNextToken() != "#define")
225 {
226 return false;
227 }
228
229 std::string n = t.GetNextToken();
230 if ( ( (currentExtension.type == Extension::GL)
231 && (strncmp(n.c_str(), "GL_", 3) == 0) )
232 || ( (currentExtension.type == Extension::WGL)
233 && (strncmp(n.c_str(), "WGL_", 4) == 0) )
234 || ( (currentExtension.type == Extension::GLX)
235 && (strncmp(n.c_str(), "GLX_", 4) == 0) ) )
236 {
237 return true;
238 }
239 return false;
240 }
241
242 class Typedef {
243 public:
244 std::string definition;
245
246 Typedef(char *line);
247 static bool isTypedef(char *line);
248
operator <(const Typedef & obj) const249 bool operator<(const Typedef &obj) const { return this->definition < obj.definition; }
250 };
251
Typedef(char * line)252 Typedef::Typedef(char *line)
253 {
254 // Assumes isTypedef is true.
255 this->definition = line;
256 }
257
isTypedef(char * line)258 bool Typedef::isTypedef(char *line)
259 {
260 Tokenizer t(line);
261
262 // Hack for some SGI stuff that declares a multiline struct.
263 if ( (t.GetNextToken() == "typedef")
264 && ((t.GetNextToken() != "struct") || (t.GetNextToken() != "{")) )
265 {
266 return true;
267 }
268
269 // Hack for how some WIN32 things are declared.
270 if (strncmp(line, "DECLARE_HANDLE(", 15) == 0)
271 {
272 return true;
273 }
274
275 return false;
276 }
277
278 class Function {
279 public:
GetReturnType() const280 std::string GetReturnType() const { return this->returnType; }
GetEntry() const281 std::string GetEntry() const { return this->entry; }
GetName() const282 std::string GetName() const { return this->name; }
GetArguments() const283 std::string GetArguments() const { return this->arguments; }
GetExtensionType() const284 int GetExtensionType() const { return this->extensionType; }
285
286 Function(char *line);
287 static bool isFunction(char *line);
288 const char *GetProcType();
289
operator <(const Function & obj) const290 bool operator<(const Function &obj) const { return this->name < obj.name; }
291
292 protected:
293 std::string returnType;
294 std::string entry;
295 std::string name;
296 std::string arguments;
297 int extensionType;
298 };
299
Function(char * line)300 Function::Function(char *line) : extensionType(currentExtension.type)
301 {
302 // Assumes isFunction returns true.
303
304 Tokenizer t(line, " \n\t(");
305
306 t.GetNextToken();
307 std::string token = t.GetNextToken();
308 this->returnType = "";
309 while ((token == "const") || (token == "unsigned"))
310 {
311 this->returnType += token + " ";
312 token = t.GetNextToken();
313 }
314 this->returnType += token;
315
316 token = t.GetNextToken();
317 if (token == "*")
318 {
319 this->returnType += " *";
320 token = t.GetNextToken();
321 }
322 else if (token[0] == '*')
323 {
324 this->returnType += " *";
325 token = token.substr(1);
326 }
327
328 #ifdef DEBUG_PARSE
329 cerr << "Function return type: " << this->returnType << endl;
330 #endif
331
332 if (currentExtension.type == Extension::GL)
333 {
334 this->entry = "APIENTRY";
335 token = t.GetNextToken();
336 }
337 else if (currentExtension.type == Extension::WGL)
338 {
339 this->entry = "WINAPI";
340 token = t.GetNextToken();
341 }
342 else
343 {
344 this->entry = "";
345 }
346
347 #ifdef DEBUG_PARSE
348 cerr << "Function entry: " << this->entry << endl;
349 #endif
350
351 if (currentExtension.type == Extension::GL)
352 {
353 // Strip off "gl"
354 this->name = token.substr(2);
355 }
356 else
357 {
358 // Strip off "glX" or "wgl"
359 this->name = token.substr(3);
360 }
361
362 #ifdef DEBUG_PARSE
363 cerr << "Function name: " << this->name << endl;
364 #endif
365
366 this->arguments = t.GetRemainingString();
367
368 #ifdef DEBUG_PARSE
369 cerr << "Function arguments: " << this->arguments << endl;
370 #endif
371 }
372
isFunction(char * line)373 bool Function::isFunction(char *line)
374 {
375 Tokenizer t(line);
376
377 std::string modifier = t.GetNextToken();
378 std::string sreturnType = t.GetNextToken();
379 if (sreturnType == "const")
380 {
381 // We don't really need the return type, just to skip over const.
382 sreturnType += " ";
383 sreturnType += t.GetNextToken();
384 }
385
386 std::string sentry = t.GetNextToken();
387 if (sentry == "*")
388 {
389 sreturnType += " *";
390 sentry = t.GetNextToken();
391 }
392 else if (sentry.size() && sentry[0] == '*')
393 {
394 sreturnType += " *";
395 sentry = sentry.substr(1);
396 }
397
398 return ( ( (currentExtension.type == Extension::GL)
399 && (modifier == "GLAPI") && (sentry == "APIENTRY") )
400 || ( (currentExtension.type == Extension::GL)
401 && (modifier == "extern") && (sentry == "APIENTRY") )
402 || ( (currentExtension.type == Extension::WGL)
403 && (modifier == "extern") && (sentry == "WINAPI") )
404 || ( (currentExtension.type == Extension::GLX)
405 && (modifier == "extern") ) );
406 }
407
GetProcType()408 const char *Function::GetProcType()
409 {
410 static std::string proctype;
411
412 proctype = "PFN";
413 proctype += Extension::TypeToCapString(this->extensionType);
414 proctype += ToUpper(this->name);
415 proctype += "PROC";
416
417 return proctype.c_str();
418 }
419
420 static std::list<Extension> extensions;
421 static std::set<Extension> extensionset;
422 static std::map<Extension, std::list<Constant> > consts;
423 static std::map<Extension, std::list<Typedef> > types;
424 static std::map<Extension, std::list<Function> > functs;
425
ParseLine(char * line)426 static void ParseLine(char *line)
427 {
428 static bool inExtension = false;
429 static int ifLevel = 0;
430
431 Tokenizer tokens(line);
432 std::string firstToken = tokens.GetNextToken();
433
434 if (Extension::isExtension(line))
435 {
436 currentExtension = Extension(line);
437 #ifdef DEBUG_PARSE
438 cerr << "Recognized extension: " << line << endl;
439 #endif
440
441 // There are some exceptions to the extensions we support. This is
442 // because someone has placed some funky nonstandard stuff in the
443 // header files.
444 if ( (currentExtension.GetName() == "GLX_SGIX_video_source")
445 || (currentExtension.GetName() == "GLX_SGIX_dmbuffer")
446 || (currentExtension.GetName() == "GLX_SGIX_hyperpipe") )
447 {
448 inExtension = false;
449 return;
450 }
451
452 // Only add extension to list if it is not already in it.
453 if (extensionset.find(currentExtension) == extensionset.end())
454 {
455 if (currentExtension.GetName() == "GLX_ARB_get_proc_address")
456 {
457 // Special case where GLX_VERSION_1_4 depends on a typedef in
458 // GLX_ARB_get_proc_address, so we have to move the latter up.
459 extensions.push_front(currentExtension);
460 }
461 else
462 {
463 extensions.push_back(currentExtension);
464 }
465 extensionset.insert(currentExtension);
466 }
467 inExtension = true;
468 ifLevel = 0;
469 }
470 else if (inExtension)
471 {
472 if (strncmp(firstToken.c_str(), "#if", 3) == 0)
473 {
474 ifLevel++;
475 }
476 else if (firstToken == "#endif")
477 {
478 if (ifLevel == 0)
479 {
480 inExtension = false;
481 }
482 else
483 {
484 ifLevel--;
485 }
486 }
487 else if ( Constant::isConstant(line)
488 && (strncmp(currentExtension.GetName().c_str(), (line+8),
489 currentExtension.GetName().length()) != 0) )
490 {
491 #ifdef DEBUG_PARSE
492 cerr << "Recognized constant: " << line << endl;
493 #endif
494 consts[currentExtension].push_back(line);
495 }
496 else if (Function::isFunction(line))
497 {
498 #ifdef DEBUG_PARSE
499 cerr << "Recognized function: " << line << endl;
500 #endif
501 functs[currentExtension].push_back(line);
502 }
503 else if (Typedef::isTypedef(line))
504 {
505 #ifdef DEBUG_PARSE
506 cerr << "Recognized typedef: " << line << endl;
507 #endif
508 types[currentExtension].push_back(line);
509 }
510 }
511 else
512 {
513 #ifdef DEBUG_PARSE
514 cerr << "Unrecognized line: " << line << endl;
515 #endif
516 }
517 }
518
WriteHeader(ostream & file,const char * generator,char ** srcs,int num_srcs)519 static void WriteHeader(ostream &file, const char *generator,
520 char **srcs, int num_srcs)
521 {
522 file << "// -*- c++ -*-" << endl << endl;
523 file << "//DO NOT EDIT!" << endl;
524 file << "//This file was created with " << generator << endl
525 << "//from";
526 for (int i = 0; i < num_srcs; i++)
527 {
528 file << " " << srcs[i];
529 }
530 file << endl << endl;
531 file << "/*" << endl
532 << " * Copyright 2003 Sandia Corporation." << endl
533 << " * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive" << endl
534 << " * license for use of this work by or on behalf of the" << endl
535 << " * U.S. Government. Redistribution and use in source and binary forms, with" << endl
536 << " * or without modification, are permitted provided that this Notice and any" << endl
537 << " * statement of authorship are reproduced on all copies." << endl
538 << " */" << endl << endl;
539 }
540
WriteClassDeclarationGuts(ostream & hfile,int type)541 static void WriteClassDeclarationGuts(ostream &hfile, int type)
542 {
543 for (std::list<Extension>::iterator iextension = extensions.begin();
544 iextension != extensions.end(); iextension++)
545 {
546 if (iextension->type != type) continue;
547 hfile << endl << " //Definitions for " << iextension->GetName().c_str() << endl;
548 std::map<Extension, std::list<Constant> >::iterator cExts
549 = consts.find(*iextension);
550 if (cExts != consts.end())
551 {
552 for (std::list<Constant>::iterator iconst = cExts->second.begin();
553 iconst != cExts->second.end(); iconst++)
554 {
555 // New versions of the NVIDIA OpenGL headers for Linux can
556 // #define the same constant with the same value in multiple
557 // sections. This utility will happily parse those and write
558 // out duplicate enums in different enum classes, which
559 // confuses the C++ preprocessor terribly. Don't write out a
560 // definition for an enum with a name/value pair that's
561 // already been used.
562 if (ConstantsAlreadyWritten.find(std::make_pair(iconst->GetName(),
563 iconst->GetValue()))
564 == ConstantsAlreadyWritten.end())
565 {
566 if(strcmp(iconst->GetName().c_str(),"TIMEOUT_IGNORED")==0)
567 {
568 // BCC/VS6/VS70 cannot digest this C99 macro
569 hfile << "#if !defined(__BORLANDC__) && (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER>=1310))" << endl;
570 }
571
572
573 hfile << " const GLenum " << iconst->GetName().c_str()
574 << " = static_cast<GLenum>(" << iconst->GetValue().c_str() << ");" << endl;
575
576 ConstantsAlreadyWritten.insert(std::make_pair(iconst->GetName(),
577 iconst->GetValue()));
578 if(strcmp(iconst->GetName().c_str(),"TIMEOUT_IGNORED")==0)
579 {
580 // really special case for non C99 compilers like BCC
581 hfile << "#endif /* only for C99 compilers */" << endl;
582 }
583 }
584 else
585 {
586 hfile << " /* skipping duplicate " << iconst->GetName().c_str()
587 << " = " << iconst->GetValue().c_str() << " */" << endl;
588 }
589 }
590 }
591 std::map<Extension, std::list<Typedef> >::iterator tExts
592 = types.find(*iextension);
593 if (tExts != types.end())
594 {
595 for (std::list<Typedef>::iterator itype = tExts->second.begin();
596 itype != tExts->second.end(); itype++)
597 {
598 hfile << " " << itype->definition.c_str() << endl;
599 }
600 }
601 std::map<Extension, std::list<Function> >::iterator fExts
602 = functs.find(*iextension);
603 if (fExts != functs.end())
604 {
605 for (std::list<Function>::iterator ifunc = fExts->second.begin();
606 ifunc != fExts->second.end(); ifunc++)
607 {
608 hfile << " extern VTKRENDERINGOPENGL_EXPORT " << ifunc->GetProcType()
609 << " " << ifunc->GetName().c_str() << ";" << endl;
610 }
611 }
612 }
613 }
614
WriteFunctionPointerDeclarations(ostream & cxxfile,int type)615 static void WriteFunctionPointerDeclarations(ostream &cxxfile, int type)
616 {
617 Extension::WriteSupportWrapperBegin(cxxfile, type);
618 for (std::map<Extension, std::list<Function> >::iterator fExts
619 = functs.begin();
620 fExts != functs.end(); fExts++)
621 {
622 if (fExts->first.type != type) continue;
623 cxxfile << "//Functions for " << fExts->first.GetName().c_str() << endl;
624 for (std::list<Function>::iterator ifunc = fExts->second.begin();
625 ifunc != fExts->second.end(); ifunc++)
626 {
627 cxxfile << "vtk" << Extension::TypeToString(type) << "::"
628 << ifunc->GetProcType()
629 << " vtk" << Extension::TypeToString(type) << "::"
630 << ifunc->GetName().c_str() << " = NULL;" << endl;
631 }
632 }
633 Extension::WriteSupportWrapperEnd(cxxfile, type);
634 cxxfile << endl;
635 }
636
WriteCode(ostream & hfile,ostream & cxxfile)637 static void WriteCode(ostream &hfile, ostream &cxxfile)
638 {
639 // Write data for header file ---------------------------------
640 hfile << "#ifndef vtkgl_h" << endl
641 << "#define vtkgl_h" << endl << endl;
642 hfile << "#include \"vtkRenderingOpenGLConfigure.h\"" << endl;
643 hfile << "#include \"vtkSystemIncludes.h\"" << endl;
644 hfile << "#include \"vtkWindows.h\"" << endl;
645 hfile << "#include \"vtkOpenGL.h\"" << endl;
646 hfile << "#include <stddef.h>" << endl << endl;
647 hfile << "#ifdef VTK_USE_X" << endl
648 << "/* To prevent glx.h to include glxext.h from the OS */" << endl
649 << "#define GLX_GLXEXT_LEGACY" << endl
650 << "#include <GL/glx.h>" << endl
651 << "#endif" << endl << endl;
652 hfile << "class vtkOpenGLExtensionManager;" << endl << endl;
653 hfile << "#ifndef APIENTRY" << endl
654 << "#define APIENTRY" << endl
655 << "#define VTKGL_APIENTRY_DEFINED" << endl
656 << "#endif" << endl << endl;
657 hfile << "#ifndef APIENTRYP" << endl
658 << "#define APIENTRYP APIENTRY *" << endl
659 << "#define VTKGL_APIENTRYP_DEFINED" << endl
660 << "#endif" << endl << endl;
661
662 hfile << "/* Undefine all constants to avoid name conflicts. They should be defined */" << endl
663 << "/* with GL_, GLX_, or WGL_ preprended to them anyway, but sometimes you run */" << endl
664 << "/* into a header file that gets it wrong. */" << endl;
665 for (std::map<Extension, std::list<Constant> >::iterator constlist
666 = consts.begin();
667 constlist != consts.end(); constlist++)
668 {
669 for (std::list<Constant>::iterator c = (*constlist).second.begin();
670 c != (*constlist).second.end(); c++)
671 {
672 hfile << "#ifdef " << (*c).GetName().c_str() << endl;
673 hfile << "#undef " << (*c).GetName().c_str() << endl;
674 hfile << "#endif" << endl;
675 }
676 }
677
678 Extension::WriteSupportWrapperBegin(hfile, Extension::GL);
679 hfile << endl << "namespace vtkgl {" << endl;
680 // Add necessary type declarations.
681 hfile << " //Define int32_t, int64_t, and uint64_t." << endl;
682 hfile << " typedef vtkTypeInt32 int32_t;" << endl;
683 hfile << " typedef vtkTypeInt64 int64_t;" << endl;
684 hfile << " typedef vtkTypeUInt64 uint64_t;" << endl;
685 // OpenGL 3.2 typedefs
686 hfile << " typedef int64_t GLint64;" << endl;
687 hfile << " typedef uint64_t GLuint64;" << endl;
688 hfile << " typedef struct __GLsync *GLsync;" << endl;
689
690 ConstantsAlreadyWritten.clear();
691 WriteClassDeclarationGuts(hfile, Extension::GL);
692 hfile << endl << " // Method to load functions for a particular extension.";
693 hfile << endl << " extern int VTKRENDERINGOPENGL_EXPORT LoadExtension(const char *name, "
694 << "vtkOpenGLExtensionManager *manager);" << endl;
695 hfile << endl << " // Strings containing special version extensions.";
696 hfile << endl << " extern VTKRENDERINGOPENGL_EXPORT const char *GLVersionExtensionsString();" << endl;
697 hfile << endl << " const char *GLXVersionExtensionsString();" << endl;
698 hfile << "}" << endl;
699 Extension::WriteSupportWrapperEnd(hfile, Extension::GL);
700
701 Extension::WriteSupportWrapperBegin(hfile, Extension::GLX);
702 hfile << "namespace vtkglX {" << endl;
703 // glxext.h is not written very well. Add some typedefs that may not
704 // be defined.
705 hfile << " //Miscellaneous definitions." << endl;
706 hfile << " typedef XID GLXContextID;" << endl;
707 hfile << " typedef XID GLXPbuffer;" << endl;
708 hfile << " typedef XID GLXWindow;" << endl;
709 hfile << " typedef XID GLXFBConfigID;" << endl;
710 hfile << " typedef struct __GLXFBConfigRec *GLXFBConfig;" << endl;
711 hfile << " typedef vtkTypeInt32 int32_t;" << endl;
712 hfile << " typedef vtkTypeInt64 int64_t;" << endl;
713 ConstantsAlreadyWritten.clear();
714 WriteClassDeclarationGuts(hfile, Extension::GLX);
715 hfile << "}" << endl;
716 Extension::WriteSupportWrapperEnd(hfile, Extension::GLX);
717
718 Extension::WriteSupportWrapperBegin(hfile, Extension::WGL);
719 hfile << "namespace vtkwgl {" << endl;
720 ConstantsAlreadyWritten.clear();
721 WriteClassDeclarationGuts(hfile, Extension::WGL);
722 hfile << "}" << endl;
723 Extension::WriteSupportWrapperEnd(hfile, Extension::WGL);
724
725 hfile << endl
726 << "#ifdef VTKGL_APIENTRY_DEFINED" << endl
727 << "#undef APIENTRY" << endl
728 << "#endif" << endl << endl;
729 hfile << "#ifdef VTKGL_APIENTRYP_DEFINED" << endl
730 << "#undef APIENTRYP" << endl
731 << "#endif" << endl << endl;
732 hfile << "#endif //_vtkgl_h" << endl;
733
734 // Write data for C++ file --------------------------------------------
735 cxxfile << "#include \"vtkgl.h\"" << endl;
736 cxxfile << "#include \"vtkOpenGLExtensionManager.h\"" << endl << endl;
737
738 // Write function pointer declarations.
739 WriteFunctionPointerDeclarations(cxxfile, Extension::GL);
740 WriteFunctionPointerDeclarations(cxxfile, Extension::GLX);
741 WriteFunctionPointerDeclarations(cxxfile, Extension::WGL);
742
743 std::list<Extension>::iterator iextension;
744
745 // Write function to load function pointers.
746 cxxfile << "int vtkgl::LoadExtension(const char *name, vtkOpenGLExtensionManager *manager)" << endl
747 << "{" << endl;
748 for (iextension = extensions.begin();
749 iextension != extensions.end(); iextension++)
750 {
751 iextension->WriteSupportWrapperBegin(cxxfile);
752 cxxfile << " if (strcmp(name, \"" << iextension->GetName().c_str()
753 << "\") == 0)" << endl
754 << " {" << endl;
755 std::string vtkglclass = "vtk";
756 vtkglclass += Extension::TypeToString(iextension->type);
757 std::list<Function>::iterator ifunct;
758 for (ifunct = functs[*iextension].begin();
759 ifunct != functs[*iextension].end(); ifunct++)
760 {
761 cxxfile << " " << vtkglclass.c_str() << "::"
762 << ifunct->GetName().c_str() << " = reinterpret_cast<" << vtkglclass.c_str() << "::"
763 << ifunct->GetProcType()
764 << ">(manager->GetProcAddress(\""
765 << Extension::TypeToString(iextension->type)
766 << ifunct->GetName().c_str() << "\"));" << endl;
767 }
768 cxxfile << " return 1";
769 for (ifunct = functs[*iextension].begin();
770 ifunct != functs[*iextension].end(); ifunct++)
771 {
772 cxxfile << " && (" << vtkglclass.c_str() << "::" << ifunct->GetName().c_str()
773 << " != NULL)";
774 }
775 cxxfile << ";" << endl;
776 cxxfile << " }" << endl;
777 iextension->WriteSupportWrapperEnd(cxxfile);
778 }
779 cxxfile << " vtkGenericWarningMacro(<< \"Nothing known about extension \" << name" << endl
780 << " << \". vtkgl may need to be updated.\");" << endl;
781 cxxfile << " return 0;" << endl
782 << "}" << endl;
783
784 // Write functions to report special version extension strings.
785 cxxfile << endl << "const char *vtkgl::GLVersionExtensionsString()" << endl
786 << "{" << endl
787 << " return \"";
788 for (iextension = extensions.begin();
789 iextension != extensions.end(); iextension++)
790 {
791 if (strncmp("GL_VERSION_", iextension->GetName().c_str(), 11) == 0)
792 {
793 cxxfile << iextension->GetName().c_str() << " ";
794 }
795 }
796 cxxfile << "\";" << endl
797 << "}" << endl;
798
799 cxxfile << endl << "const char *vtkgl::GLXVersionExtensionsString()" << endl
800 << "{" << endl
801 << " return \"";
802 for (iextension = extensions.begin();
803 iextension != extensions.end(); iextension++)
804 {
805 if (strncmp("GLX_VERSION_", iextension->GetName().c_str(), 12) == 0)
806 {
807 cxxfile << iextension->GetName().c_str() << " ";
808 }
809 }
810 cxxfile << "\";" << endl
811 << "}" << endl;
812 }
813
main(int argc,char ** argv)814 int main(int argc, char **argv)
815 {
816 if (argc < 3)
817 {
818 cerr << "USAGE: " << argv[0] << "<output dir> <header files>" << endl;
819 return 1;
820 }
821
822 std::string outputDir = argv[1];
823
824 for (int i = 2; i < argc; i++)
825 {
826 #ifdef DEBUG_PARSE
827 cerr << "*** Parsing declarations from file " << argv[i] << endl;
828 #endif
829 ifstream file(argv[i]);
830 if (!file)
831 {
832 cerr << "Could not open " << argv[i] << endl;
833 return 2;
834 }
835
836 while (!file.eof())
837 {
838 static char buf[4096]; // What are the odds of needing more?
839 file.getline(buf, 4096);
840 ParseLine(buf);
841 }
842 file.close();
843 }
844
845 ofstream hfile((outputDir + "/vtkgl.h").c_str());
846 WriteHeader(hfile, argv[0], argv+1, argc-1);
847 ofstream cxxfile((outputDir + "/vtkgl.cxx").c_str());
848 WriteHeader(cxxfile, argv[0], argv+1, argc-1);
849
850 WriteCode(hfile, cxxfile);
851
852 hfile.close();
853 cxxfile.close();
854
855 return 0;
856 }
857