Fix for UBSan build
[platform/upstream/doxygen.git] / src / config.h
1 /******************************************************************************
2  *
3  * $Id: config.h,v 1.39 2001/03/19 19:27:40 root Exp $
4  *
5  *
6  * Copyright (C) 1997-2012 by Dimitri van Heesch.
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation under the terms of the GNU General Public License is hereby 
10  * granted. No representations are made about the suitability of this software 
11  * for any purpose. It is provided "as is" without express or implied warranty.
12  * See the GNU General Public License for more details.
13  *
14  * Documents produced by Doxygen are derivative works derived from the
15  * input used in their production; they are not affected by this license.
16  *
17  */
18
19 #ifndef CONFIG_H
20 #define CONFIG_H
21
22 #include "qtbc.h"
23 #include <qstrlist.h>
24 #include <qfile.h>
25 #include <qdict.h>
26 #include <qlist.h>
27 #include "ftextstream.h"
28
29
30 /** Abstract base class for any configuration option.
31  */
32 class ConfigOption
33 {
34     friend class Config;
35
36   public:
37
38     /*! The type of option */
39     enum OptionType 
40     { 
41       O_Info,      //<! A section header
42       O_List,      //<! A list of items
43       O_Enum,      //<! A fixed set of items
44       O_String,    //<! A single item
45       O_Int,       //<! An integer value
46       O_Bool,      //<! A boolean value
47       O_Obsolete   //<! An obsolete option
48     };
49     enum 
50     { 
51      /*! Maximum length of an option in the config file. Used for 
52       *  alignment purposes.
53       */
54       MAX_OPTION_LENGTH = 23  
55     };
56     ConfigOption(OptionType t) : m_kind(t) 
57     {
58       m_spaces.fill(' ',40);
59     }
60     virtual ~ConfigOption()
61     {
62     }
63
64     /*! returns the kind of option this is. */
65     OptionType kind() const { return m_kind; }
66     QCString name() const { return m_name; }
67     QCString docs() const { return m_doc; }
68
69     QCString dependsOn() const { return m_dependency; }
70     void addDependency(const char *dep) { m_dependency = dep; }
71     void setEncoding(const QCString &e) { m_encoding = e; }
72
73   protected:
74     virtual void writeTemplate(FTextStream &t,bool sl,bool upd) = 0;
75     virtual void convertStrToVal() {}
76     virtual void substEnvVars() = 0;
77     virtual void writeXML(FTextStream&) {}
78     virtual void init() {}
79
80     QCString convertToComment(const QCString &s);
81     void writeBoolValue(FTextStream &t,bool v);
82     void writeIntValue(FTextStream &t,int i);
83     void writeStringValue(FTextStream &t,QCString &s);
84     void writeStringList(FTextStream &t,QStrList &l);
85
86     QCString m_spaces;
87     QCString m_name;
88     QCString m_doc;
89     QCString m_dependency;
90     QCString m_encoding;
91     OptionType m_kind;
92 };
93
94 /** Section marker for grouping the configuration options.
95  */
96 class ConfigInfo : public ConfigOption
97 {
98   public:
99     ConfigInfo(const char *name,const char *doc) 
100       : ConfigOption(O_Info)
101     {
102       m_name = name;
103       m_doc = doc;
104     }
105     void writeTemplate(FTextStream &t, bool sl,bool)
106     {
107       if (!sl)
108       {
109         t << "\n";
110       }
111       t << "#---------------------------------------------------------------------------\n";
112       t << "# " << m_doc << endl;
113       t << "#---------------------------------------------------------------------------\n";
114     }
115     void substEnvVars() {}
116 };
117
118 /** Class respresenting a list type option.
119  */
120 class ConfigList : public ConfigOption
121 {
122   public:
123     enum WidgetType { String, File, Dir, FileAndDir };
124     ConfigList(const char *name,const char *doc) 
125       : ConfigOption(O_List)
126     {
127       m_name = name;
128       m_doc = doc;
129       m_widgetType = String;
130     }
131     void addValue(const char *v) { m_value.append(v); }
132     void setWidgetType(WidgetType w) { m_widgetType = w; }
133     WidgetType widgetType() const { return m_widgetType; }
134     QStrList *valueRef() { return &m_value; }
135     void writeTemplate(FTextStream &t,bool sl,bool)
136     {
137       if (!sl)
138       {
139         t << endl;
140         t << convertToComment(m_doc);
141         t << endl;
142       }
143       t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "=";
144       writeStringList(t,m_value);
145       t << "\n";
146     }
147     void substEnvVars();
148     void writeXML(FTextStream&);
149     void init() { m_value.clear(); }
150   private:
151     QStrList m_value;
152     WidgetType m_widgetType;
153 };
154
155 /** Class representing an enum type option.
156  */
157 class ConfigEnum : public ConfigOption
158 {
159   public:
160     ConfigEnum(const char *name,const char *doc,const char *defVal) 
161       : ConfigOption(O_Enum)
162     {
163       m_name = name;
164       m_doc = doc;
165       m_value = defVal;
166       m_defValue = defVal;
167     }
168     void addValue(const char *v) { m_valueRange.append(v); }
169     QStrListIterator iterator() 
170     {
171       return QStrListIterator(m_valueRange);
172     }
173     QCString *valueRef() { return &m_value; }
174     void substEnvVars();
175     void writeTemplate(FTextStream &t,bool sl,bool)
176     {
177       if (!sl)
178       {
179         t << endl;
180         t << convertToComment(m_doc);
181         t << endl;
182       }
183       t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "=";
184       writeStringValue(t,m_value);
185       t << "\n";
186     }
187     void writeXML(FTextStream&);
188     void init() { m_value = m_defValue.copy(); }
189
190   private:
191     QStrList m_valueRange;
192     QCString m_value;
193     QCString m_defValue;
194 };
195
196 /** Class representing a string type option.
197  */
198 class ConfigString : public ConfigOption
199 {
200   public:
201     enum WidgetType { String, File, Dir };
202     ConfigString(const char *name,const char *doc) 
203       : ConfigOption(O_String)
204     {
205       m_name = name;
206       m_doc = doc;
207       m_widgetType = String;
208     }
209    ~ConfigString()
210     {
211     }
212     void setWidgetType(WidgetType w) { m_widgetType = w; }
213     WidgetType widgetType() const { return m_widgetType; }
214     void setDefaultValue(const char *v) { m_defValue = v; }
215     QCString *valueRef() { return &m_value; }
216     void writeTemplate(FTextStream &t,bool sl,bool)
217     {
218       if (!sl)
219       {
220         t << endl;
221         t << convertToComment(m_doc);
222         t << endl;
223       }
224       t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "=";
225       writeStringValue(t,m_value);
226       t << "\n";
227     }
228     void substEnvVars();
229     void writeXML(FTextStream&);
230     void init() { m_value = m_defValue.copy(); }
231   
232   private:
233     QCString m_value;
234     QCString m_defValue;
235     WidgetType m_widgetType;
236 };
237
238 /** Class representing an integer type option.
239  */
240 class ConfigInt : public ConfigOption
241 {
242   public:
243     ConfigInt(const char *name,const char *doc,int minVal,int maxVal,int defVal) 
244       : ConfigOption(O_Int)
245     {
246       m_name = name;
247       m_doc = doc;
248       m_value = defVal;
249       m_defValue = defVal;
250       m_minVal = minVal;
251       m_maxVal = maxVal;
252     }
253     QCString *valueStringRef() { return &m_valueString; }
254     int *valueRef() { return &m_value; }
255     int minVal() const { return m_minVal; }
256     int maxVal() const { return m_maxVal; }
257     void convertStrToVal();
258     void substEnvVars();
259     void writeTemplate(FTextStream &t,bool sl,bool upd)
260     {
261       if (!sl)
262       {
263         t << endl;
264         t << convertToComment(m_doc);
265         t << endl;
266       }
267       t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "=";
268       if (upd && !m_valueString.isEmpty())
269       {
270         writeStringValue(t,m_valueString);
271       }
272       else
273       {
274         writeIntValue(t,m_value);
275       }
276       t << "\n";
277     }
278     void writeXML(FTextStream&);
279     void init() { m_value = m_defValue; }
280   private:
281     int m_value;
282     int m_defValue;
283     int m_minVal;
284     int m_maxVal;
285     QCString m_valueString;
286 };
287
288 /** Class representing a Boolean type option.
289  */
290 class ConfigBool : public ConfigOption
291 {
292   public:
293     ConfigBool(const char *name,const char *doc,bool defVal) 
294       : ConfigOption(O_Bool)
295     {
296       m_name = name;
297       m_doc = doc;
298       m_value = defVal;
299       m_defValue = defVal;
300     }
301     QCString *valueStringRef() { return &m_valueString; }
302     bool *valueRef() { return &m_value; }
303     void convertStrToVal();
304     void substEnvVars();
305     void setValueString(const QCString &v) { m_valueString = v; }
306     void writeTemplate(FTextStream &t,bool sl,bool upd)
307     {
308       if (!sl)
309       {
310         t << endl;
311         t << convertToComment(m_doc);
312         t << endl;
313       }
314       t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "=";
315       if (upd && !m_valueString.isEmpty())
316       {
317         writeStringValue(t,m_valueString);
318       }
319       else
320       {
321         writeBoolValue(t,m_value);
322       }
323       t << "\n";
324     }
325     void writeXML(FTextStream&);
326     void init() { m_value = m_defValue; }
327   private:
328     bool m_value;
329     bool m_defValue;
330     QCString m_valueString;
331 };
332
333 /** Section marker for obsolete options
334  */
335 class ConfigObsolete : public ConfigOption
336 {
337   public:
338     ConfigObsolete(const char *name,OptionType t) : ConfigOption(t)  
339     { m_name = name; }
340     void writeTemplate(FTextStream &,bool,bool) {}
341     void substEnvVars() {}
342     void writeXML(FTextStream&);
343 };
344
345
346 // some convenience macros
347 #define Config_getString(val)  Config::instance()->getString(__FILE__,__LINE__,val)
348 #define Config_getInt(val)     Config::instance()->getInt(__FILE__,__LINE__,val)
349 #define Config_getList(val)    Config::instance()->getList(__FILE__,__LINE__,val)
350 #define Config_getEnum(val)    Config::instance()->getEnum(__FILE__,__LINE__,val)
351 #define Config_getBool(val)    Config::instance()->getBool(__FILE__,__LINE__,val)
352
353 /** Singleton for configuration variables.
354  *
355  *  This object holds the global static variables
356  *  read from a user-supplied configuration file.
357  *  The static member instance() can be used to get
358  *  a pointer to the one and only instance.
359  *  
360  *  Set all variables to their default values by
361  *  calling Config::instance()->init()
362  *
363  */
364 class Config
365 {
366   public:
367     /////////////////////////////
368     // public API
369     /////////////////////////////
370
371     /*! Returns the one and only instance of this class */
372     static Config *instance()
373     {
374       if (m_instance==0) m_instance = new Config;
375       return m_instance;
376     }
377     /*! Delete the instance */
378     static void deleteInstance()
379     {
380       delete m_instance;
381       m_instance=0;
382     }
383     
384     /*! Returns an iterator that can by used to iterate over the 
385      *  configuration options.
386      */
387     QListIterator<ConfigOption> iterator()
388     {
389       return QListIterator<ConfigOption>(*m_options);
390     }
391
392     /*! 
393      *  @name Getting configuration values.
394      *  @{
395      */
396
397     /*! Returns the value of the string option with name \a fileName. 
398      *  The arguments \a num and \a name are for debugging purposes only.
399      *  There is a convenience function Config_getString() for this.
400      */
401     QCString &getString(const char *fileName,int num,const char *name) const;
402
403     /*! Returns the value of the list option with name \a fileName. 
404      *  The arguments \a num and \a name are for debugging purposes only.
405      *  There is a convenience function Config_getList() for this.
406      */
407     QStrList &getList(const char *fileName,int num,const char *name) const;
408
409     /*! Returns the value of the enum option with name \a fileName. 
410      *  The arguments \a num and \a name are for debugging purposes only.
411      *  There is a convenience function Config_getEnum() for this.
412      */
413     QCString &getEnum(const char *fileName,int num,const char *name) const;
414
415     /*! Returns the value of the integer option with name \a fileName. 
416      *  The arguments \a num and \a name are for debugging purposes only.
417      *  There is a convenience function Config_getInt() for this.
418      */
419     int      &getInt(const char *fileName,int num,const char *name) const;
420
421     /*! Returns the value of the boolean option with name \a fileName. 
422      *  The arguments \a num and \a name are for debugging purposes only.
423      *  There is a convenience function Config_getBool() for this.
424      */
425     bool     &getBool(const char *fileName,int num,const char *name) const;
426
427     /*! Returns the ConfigOption corresponding with \a name or 0 if
428      *  the option is not supported.
429      */
430     ConfigOption *get(const char *name) const
431     {
432       return m_dict->find(name); 
433     }
434     /* @} */
435
436     /*! 
437      *  @name Adding configuration options. 
438      *  @{
439      */
440
441     /*! Starts a new configuration section with \a name and description \a doc.
442      *  \returns An object representing the option.
443      */
444     ConfigInfo   *addInfo(const char *name,const char *doc)
445     {
446       ConfigInfo *result = new ConfigInfo(name,doc);
447       m_options->append(result);
448       return result;
449     }
450
451     /*! Adds a new string option with \a name and documentation \a doc.
452      *  \returns An object representing the option.
453      */
454     ConfigString *addString(const char *name,
455                             const char *doc)
456     {
457       ConfigString *result = new ConfigString(name,doc);
458       m_options->append(result);
459       m_dict->insert(name,result);
460       return result;
461     }
462
463     /*! Adds a new enumeration option with \a name and documentation \a doc
464      *  and initial value \a defVal. 
465      *  \returns An object representing the option.
466      */
467     ConfigEnum   *addEnum(const char *name,
468                           const char *doc,
469                           const char *defVal)
470     {
471       ConfigEnum *result = new ConfigEnum(name,doc,defVal);
472       m_options->append(result);
473       m_dict->insert(name,result);
474       return result;
475     }
476
477     /*! Adds a new string option with \a name and documentation \a doc.
478      *  \returns An object representing the option.
479      */
480     ConfigList   *addList(const char *name,
481                           const char *doc)
482     {
483       ConfigList *result = new ConfigList(name,doc);
484       m_options->append(result);
485       m_dict->insert(name,result);
486       return result;
487     }
488
489     /*! Adds a new integer option with \a name and documentation \a doc.
490      *  The integer has a range between \a minVal and \a maxVal and a
491      *  default value of \a defVal.
492      *  \returns An object representing the option.
493      */
494     ConfigInt    *addInt(const char *name,
495                          const char *doc,
496                          int minVal,int maxVal,int defVal)
497     {
498       ConfigInt *result = new ConfigInt(name,doc,minVal,maxVal,defVal);
499       m_options->append(result);
500       m_dict->insert(name,result);
501       return result;
502     }
503
504     /*! Adds a new boolean option with \a name and documentation \a doc.
505      *  The boolean has a default value of \a defVal.
506      *  \returns An object representing the option.
507      */
508     ConfigBool   *addBool(const char *name,
509                           const char *doc,
510                           bool defVal)
511     {
512       ConfigBool *result = new ConfigBool(name,doc,defVal);
513       m_options->append(result);
514       m_dict->insert(name,result);
515       return result;
516     }
517     /*! Adds an option that has become obsolete. */
518     ConfigOption *addObsolete(const char *name)
519     {
520       ConfigObsolete *option = new ConfigObsolete(name,ConfigOption::O_Obsolete);
521       m_dict->insert(name,option);
522       m_obsolete->append(option);
523       return option;
524     }
525     /*! @} */
526
527     /*! Writes a template configuration to stream \a t. If \a shortIndex
528      *  is \c TRUE the description of each configuration option will
529      *  be omitted.
530      */
531     void writeTemplate(FTextStream &t,bool shortIndex,bool updateOnly);
532
533     /** Write XML representation of the config file */
534     void writeXML(FTextStream &t);
535
536     /////////////////////////////
537     // internal API
538     /////////////////////////////
539
540     /*! Converts the string values read from the configuration file
541      *  to real values for non-string type options (like int, and bools)
542      */
543     void convertStrToVal();
544
545     /*! Replaces references to environment variable by the actual value
546      *  of the environment variable.
547      */
548     void substituteEnvironmentVars();
549
550     /*! Checks if the values of the variable are correct, adjusts them
551      *  if needed, and report any errors.
552      */
553     void check();
554
555     /*! Initialize config variables to their default value */
556     void init();
557
558     /*! Parse a configuration data in string \a str.
559      *  \returns TRUE if successful, or FALSE if the string could not be
560      *  parsed.
561      */ 
562     bool parseString(const char *fn,const char *str);
563
564     /*! Parse a configuration file with name \a fn.
565      *  \returns TRUE if successful, FALSE if the file could not be 
566      *  opened or read.
567      */ 
568     bool parse(const char *fn);
569
570     /*! Called from the constructor, will add doxygen's default options
571      *  to the configuration object 
572      */
573     void create();
574
575   protected:
576
577     Config()
578     { 
579       m_options  = new QList<ConfigOption>;
580       m_obsolete = new QList<ConfigOption>;
581       m_dict     = new QDict<ConfigOption>(257);
582       m_options->setAutoDelete(TRUE);
583       m_obsolete->setAutoDelete(TRUE);
584       m_initialized = FALSE;
585       create();
586     }
587    ~Config()
588     {
589       delete m_options;
590       delete m_obsolete;
591       delete m_dict;
592     }
593
594   private:
595     QList<ConfigOption> *m_options;
596     QList<ConfigOption> *m_obsolete;
597     QDict<ConfigOption> *m_dict;
598     static Config *m_instance;
599     bool m_initialized;
600 };
601
602 #endif