summaryrefslogtreecommitdiffstats
path: root/buildtools/qmake/scope.h
blob: f50d4d998c3856d606fc318f503516ad4c517f46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/***************************************************************************
*   Copyright (C) 2006 by Andreas Pakulat                                 *
*   apaku@gmx.de                                                          *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/

#ifndef _SCOPE_H_
#define _SCOPE_H_

#include <tqstring.h>
#include <tqstringlist.h>
#include <tqmap.h>
#include <set>

#include "qmakeast.h"
#include "qmakedefaultopts.h"

#ifdef DEBUG
#include "qmakeastvisitor.h"
#endif

class Scope;
class TrollProjectPart;

class Scope
{
public:

    enum ScopeType {
        ProjectScope,
        FunctionScope,
        SimpleScope,
        IncludeScope,
        InvalidScope
    };
    static const TQStringList KnownVariables;
    static const TQStringList KnownConfigValues;

    Scope( const TQMap<TQString, TQString>& env, const TQString &filename, TrollProjectPart* part );
    ~Scope();

    void saveToFile() const;

    // Changing variable values
    void addToPlusOp( const TQString& variable, const TQStringList& values );
    void removeFromPlusOp( const TQString& variable, const TQStringList& values );
    void addToMinusOp( const TQString& variable, const TQStringList& values );
    void removeFromMinusOp( const TQString& variable, const TQStringList& values );
    void addToEqualOp( const TQString& variable, const TQStringList& values );
    void removeFromEqualOp( const TQString& variable, const TQStringList& values );
    void setPlusOp( const TQString& variable, const TQStringList& values );
    void setEqualOp( const TQString& variable, const TQStringList& values );
    void setMinusOp( const TQString& variable, const TQStringList& values );

    // Checks wether a line like VAR = exists in this subscope
    bool isVariableReset( const TQString& var );

    // Fetch the valuelist for the variable op combination inside this scope
    TQStringList variableValuesForOp( const TQString& variable, const TQString& op ) const;

    // Fetch the variable values by running over the statements and adding/removing/setting
    // as the encountered op's say, begin with the parent projects variableValues list
    TQStringList variableValues( const TQString& variable, bool checkIncParent = true, bool fetchFromParent = true, bool evaluateSubScopes = false );

    // Remove a variable+Op combination from the scope, if existant
    void removeVariable( const TQString& var, const TQString& op );

    // Getting to know what type of scope this is
    ScopeType scopeType() const;

    // This returns the function+args, the scopename or the pro/pri file
    // depending on the type of scope
    TQString scopeName() const;

    // Returns the projectName for this scope, this is equal to the last part of the projectDir()
    TQString projectName() const;

    // Returns just the filename of this project's .pro file
    TQString fileName() const;

    // Returns the absolute path of the dir containing the .pro file
    TQString projectDir() const;

    // get the parent Scope
    Scope* parent() const { return m_parent; }

    // Fetching sub-scopes
    const TQValueList<Scope*> scopesInOrder() const { return m_scopes.values(); }
    // Working on SubScopes
    /*
     * creates a new function scope at the end of this (Sub-)AST and returns the Scope wrapping it
     */
    Scope* createFunctionScope( const TQString& funcName, const TQString& args );
    /*
     * creates a new simple scope at the end of this (Sub-)AST and returns the Scope wrapping it
     */
    Scope* createSimpleScope( const TQString& scopename );

    /*
     * creates a new function scope at the end of this (Sub-)AST
     * and a new include scope inside the new function scope.
     * It returns the Scope wrapping the include-AST, the function scope AST
     * can be accessed easily using the parent() method.
     */
    Scope* createIncludeScope( const TQString& includeFile, bool negate = false );

    /*
     * creates a new subproject in dir (create's dir if necessary)
     * If this scope is not a project scope the subproject will be added to this
     * Scope only, i.e. it is not seen in the project-files list of subdirs
     */
    Scope* createSubProject( const TQString& dir );

    /* delete the given function scope */
    bool deleteFunctionScope( unsigned int );
    /* delete the given simple scope */
    bool deleteSimpleScope( unsigned int );
    /* delete the given include scope */
    bool deleteIncludeScope( unsigned int );
    /* deletes the subproject (including the subdir if deleteSubdir is true) */
    bool deleteSubProject( unsigned int, bool deleteSubdir );

    /* Provide a Map of Custom variables */
    const TQMap<unsigned int, TQMap<TQString, TQString> > customVariables() const;

    unsigned int addCustomVariable( const TQString& var, const TQString& op, const TQString& values );

    /* Removes the variable with the given id if it exists */
    void removeCustomVariable( unsigned int );

    /* Update the values of the variable/operation combo var+op to values */
    void updateCustomVariable( unsigned int, const TQString&, const TQString& , const TQString& );

    // Checks wether a TQStringList contains any values that are not whitespace or \\n
    static bool listIsEmpty( const TQStringList& values );

    /* returns wether this is an enabled subproject or a disabled one */
    bool isEnabled() { return m_isEnabled; }

    TQStringList cleanStringList(const TQStringList& list) const;

    /* Reload a project scope */
    void reloadProject();

    /* creates a new disabled Scope child and add SUBDIRS -= dir to this scope */
    Scope* disableSubproject( const TQString& );

    /* return the "position" of this scope in the list of scopes */
    unsigned int getNum() { return m_num; }

    TQStringList allFiles( const TQString& );

    TQString resolveVariables( const TQString& ) const;

    TQString findCustomVarForPath( const TQString& );

#ifdef DEBUG
    void printTree();
#endif

private:

    // Builds the scope-lists and the customVariables list
    void init();

    /*
     * Updates the given Variable+op with the values, if removeFromOp is true it removes the values, else it adds them
     * this works it's way back through the current scope and changes the last occurence of op to
     * include all new values.
     *
     * Depending on "op" it might end the search earlier (if op is += it also stops at =)
     *
     * This also removes the values from other assignments if the operation is not op, i.e.
     * if op is += removes values from any occurence of -=
     * if op is -= removes values from any occurence of = and +=
     * if op is = removes values frmo any occurence of -=
     */
    void updateVariable( const TQString& variable, const TQString& op, const TQStringList& values, bool removeFromOp );

    /*
     * Helper Function to change the origValues list with the values from newValues
     * depending on the state of "remove" either adds or removes all entries from newValues
     * to origValues if they didn't exist there yet
     */
    void updateValues( TQStringList& origValues, const TQStringList& newValues, bool remove = false, TQString indent = "  " );

    /*
     * Finds an existing variable, returns the end() of the statemenst if it is not found
     */
    TQValueList<TQMake::AST*>::iterator findExistingVariable( const TQString& variable );

    // Private constructors for easier subscope creation
    /*
     * just initializes the lists from the scope
     */
    Scope( const TQMap<TQString, TQString>& env, unsigned int num, Scope* parent, TQMake::ProjectAST* root, TQMakeDefaultOpts*, TrollProjectPart* part );
    /*
     * reads the given filename and parses it. If it doesn't exist creates an empty
     * ProjectAST with the given filename
     */
    Scope( const TQMap<TQString, TQString>& env, unsigned int num, Scope* parent, const TQString& filename, TrollProjectPart* part, bool isEnabled = true );
    /*
     * Creates a scope for an include statement, parses the file and initializes the Scope
     * Create an empty ProjectAST if the file cannot be found or parsed.
     */
    Scope( const TQMap<TQString, TQString>& env, unsigned int num, Scope* parent, TQMake::IncludeAST* incast, const TQString& path, const TQString& incfile, TQMakeDefaultOpts*, TrollProjectPart* part );


    // runs through the statements until stopHere is found (or the end is reached, if stopHere is 0),
    // using the given list as startvalue
    // Changes the list using the +=, -=, = operations accordingly
    void calcValuesFromStatements( const TQString& variable, TQStringList& result, bool, TQMake::AST* stopHere = 0, bool fetchFromParent = true, bool setDefault = true, bool evaluateSubScopes = false ) const;

    // Check wether the two operators are compatible
    static bool isCompatible( const TQString& op1, const TQString& op2);

    // Check wether the 2 lists are equal, regardless of element order.
    static bool listsEqual(const TQStringList& , const TQStringList& );

    // Load and Save project files, these only work on ProjectScope's
    bool loadFromFile( const TQString& filename );

    TQString funcScopeKey( TQMake::ProjectAST* funcast ) const { return funcast->scopedID + "(" + funcast->args + ")"; }

    unsigned int getNextScopeNum() { if( m_scopes.isEmpty() ) return 0; else return (m_scopes.keys().last()+1); }

    TQStringList lookupVariable( const TQString& var );

    TQStringList resolveVariables( const TQStringList&, TQMake::AST* = 0 ) const;
    TQStringList variableValues( const TQString& variable, TQMake::AST*, bool fetchFromParent = true ) const;
    TQString resolveVariables( const TQString& , TQMake::AST* ) const;

    // This function determines the currently used String for fileending, it can be \n, \r or \r\n
    TQString getLineEndingString() const;
    bool isComment( const TQString& ) const;
    bool containsContinue( const TQString& ) const;
    void allFiles( const TQString&, std::set<TQString>& );

    void loadDefaultOpts();

    TQMake::ProjectAST* m_root;
    TQMake::IncludeAST* m_incast;
    TQMap<unsigned int, TQMake::AssignmentAST*> m_customVariables;
    TQMap<unsigned int, Scope*> m_scopes;
    Scope* m_parent;
    unsigned int m_maxCustomVarNum;

    TQString replaceWs(TQString);


    // The "position" inside the parent scope that this scope starts at
    unsigned int m_num;
    bool m_isEnabled;
    TrollProjectPart* m_part;
    TQMakeDefaultOpts* m_defaultopts;
    TQMap<TQString, TQStringList> m_varCache;
    TQMap<TQString,TQString> m_environment;

#ifdef DEBUG
    class PrintAST : TQMake::ASTVisitor
    {

    public:
        PrintAST();
        virtual void processProject( TQMake::ProjectAST* p );
        virtual void enterRealProject( TQMake::ProjectAST* p );

        virtual void leaveRealProject( TQMake::ProjectAST* p );

        virtual void enterScope( TQMake::ProjectAST* p );

        virtual void leaveScope( TQMake::ProjectAST* p );

        virtual void enterFunctionScope( TQMake::ProjectAST* p );

        virtual void leaveFunctionScope( TQMake::ProjectAST* p );

        virtual void processAssignment( TQMake::AssignmentAST* a);

        virtual void processNewLine( TQMake::NewLineAST* n);

        virtual void processComment( TQMake::CommentAST* a);

        virtual void processInclude( TQMake::IncludeAST* a);

        TQString replaceWs(TQString);

    private:
        TQString getIndent();
        int indent;

    };
#endif

};

#endif