1 /**
2  * @file uncrustify_types.h
3  *
4  * Defines some types for the uncrustify program
5  *
6  * @author  Ben Gardner
7  * @license GPL v2+
8  */
9 
10 #ifndef UNCRUSTIFY_TYPES_H_INCLUDED
11 #define UNCRUSTIFY_TYPES_H_INCLUDED
12 
13 #include "options.h"
14 #include "pcf_flags.h"
15 #include "token_enum.h"    // c_token_t
16 #include "unc_text.h"
17 #include "uncrustify_limits.h"
18 
19 #include <assert.h>
20 
21 #ifdef HAVE_UTIME_H
22 #include <utime.h>
23 #endif
24 
25 
26 class ParseFrame;
27 
28 
29 /**
30  * abbreviations used:
31  *   SS = star style
32  */
33 
34 /**
35  * special strings to mark a part of the input file where
36  * uncrustify shall not change anything
37  */
38 #define UNCRUSTIFY_OFF_TEXT    " *INDENT-OFF*"
39 #define UNCRUSTIFY_ON_TEXT     " *INDENT-ON*"
40 
41 //! returns type (with removed reference) of a variable
42 #define noref_decl_t(X)              std::remove_reference<decltype((X))>::type
43 
44 //! returns type (with removed const and reference) of a variable
45 #define nocref_decl_t(X)             std::remove_const<noref_decl_t((X))>::type
46 
47 //! static casts Y to the type (with removed reference) of X
48 #define s_cast_noref_decl_t(X, Y)    static_cast<nocref_decl_t(X)>(Y)
49 
50 //! performs abs on Y after static casting it to the type (with removed reference) of X
51 #define cast_abs(X, Y)               s_cast_noref_decl_t(X, abs(Y))
52 
53 /**
54  * @brief Macro to inform the compiler that a variable is intentionally
55  * not in use.
56  *
57  * @param [in] variableName: The unused variable.
58  */
59 #define UNUSED(variableName)         ((void)variableName)
60 
61 
62 //! Brace stage enum used in brace_cleanup
63 enum class brace_stage_e : unsigned int
64 {
65    NONE,
66    PAREN1,      //! expected paren after if/catch (C++)/for/switch/synchronized/while
67    OP_PAREN1,   //! optional paren after catch (C#)
68    WOD_PAREN,   //! while of do parens
69    WOD_SEMI,    //! semicolon after while of do
70    BRACE_DO,    //! do
71    BRACE2,      //! if/catch/else/finally/for/switch/synchronized/while
72    ELSE,        //! expecting 'else' after 'if'
73    ELSEIF,      //! expecting 'if' after 'else'
74    WHILE,       //! expecting 'while' after 'do'
75    CATCH,       //! expecting 'catch' or 'finally' after 'try'
76    CATCH_WHEN,  //! optional 'when' after 'catch'
77 };
78 
79 
80 enum class char_encoding_e : unsigned int
81 {
82    e_ASCII,     //! 0-127
83    e_BYTE,      //! 0-255, not UTF-8
84    e_UTF8,      //! utf 8 bit wide
85    e_UTF16_LE,  //! utf 16 bit wide, little endian
86    e_UTF16_BE   //! utf 16 bit wide, big endian
87 };
88 
89 
90 struct chunk_t; //forward declaration
91 
92 
93 /**
94  * Sort of like the aligning stuff, but the token indent is relative to the
95  * indent of another chunk. This is needed, as that chunk may be aligned and
96  * so the indent cannot be determined in the indent code.
97  */
98 struct indent_ptr_t
99 {
100    chunk_t *ref;
101    int     delta;
102 };
103 
104 
105 struct align_ptr_t
106 {
107    chunk_t *next;       //! nullptr or the chunk that should be under this one
108    bool    right_align; //! AlignStack.m_right_align
109    size_t  star_style;  //! AlignStack.m_star_style
110    size_t  amp_style;   //! AlignStack.m_amp_style
111    int     gap;         //! AlignStack.m_gap
112 
113    /*
114     * col_adj is the amount to alter the column for the token.
115     * For example, a dangling '*' would be set to -1.
116     * A right-aligned word would be a positive value.
117     */
118    int     col_adj;
119    chunk_t *ref;
120    chunk_t *start;
121 };
122 
123 
124 // for debugging purpose only
125 typedef std::pair<size_t, char *>   Track_nr;         // track for "trackNumber" and "rule"
126 typedef std::vector<Track_nr>       track_list;       // liste for many tracks
127 
128 // This is the main type of this program
129 struct chunk_t
130 {
chunk_tchunk_t131    chunk_t()
132    {
133       reset();
134    }
135 
136 
137    //! sets all elements of the struct to their default value
resetchunk_t138    void reset()
139    {
140       memset(&align, 0, sizeof(align));
141       memset(&indent, 0, sizeof(indent));
142       next          = nullptr;
143       prev          = nullptr;
144       parent        = nullptr;
145       type          = CT_NONE;
146       parent_type   = CT_NONE;
147       orig_line     = 0;
148       orig_col      = 0;
149       orig_col_end  = 0;
150       orig_prev_sp  = 0;
151       flags         = PCF_NONE;
152       column        = 0;
153       column_indent = 0;
154       nl_count      = 0;
155       nl_column     = 0;
156       level         = 0;
157       brace_level   = 0;
158       pp_level      = 999;                           // use a big value to find some errors
159       after_tab     = false;
160       // for debugging purpose only
161       tracking = nullptr;
162       str.clear();
163    }
164 
165 
166    //! provides the number of characters of string
lenchunk_t167    size_t len() const
168    {
169       return(str.size());
170    }
171 
172 
173    //! provides the content of a string a zero terminated character pointer
textchunk_t174    const char *text() const
175    {
176       return(str.c_str());
177    }
178 
179 
180    // Issue #2984, fill up, if necessary, a copie of the first chars of the text() string
elided_textchunk_t181    const char *elided_text(char *for_the_copy)
182    {
183       const char *test_it       = text();
184       size_t     test_it_length = strlen(test_it);
185 
186       size_t     truncate_value = uncrustify::options::debug_truncate();
187 
188       if (truncate_value != 0)
189       {
190          if (test_it_length > truncate_value)
191          {
192             memset(for_the_copy, 0, 1000);
193 
194             if (test_it_length < truncate_value + 30)
195             {
196                strncpy(for_the_copy, test_it, truncate_value - 30);
197                for_the_copy[truncate_value - 30] = 0;
198             }
199             else
200             {
201                strncpy(for_the_copy, test_it, truncate_value);
202                for_the_copy[truncate_value] = 0;
203             }
204             char *message = strcat(for_the_copy, " ... <The string is truncated>");
205 
206             return(message);
207          }
208          else
209          {
210             return(test_it);
211          }
212       }
213       return(test_it);
214    }
215 
216    chunk_t      *next;            //! pointer to next chunk in list
217    chunk_t      *prev;            //! pointer to previous chunk in list
218    chunk_t      *parent;          //! pointer to parent chunk(not always set)
219    align_ptr_t  align;
220    indent_ptr_t indent;
221    c_token_t    type;             //! type of the chunk itself
222    c_token_t    parent_type;      //! type of the parent chunk usually CT_NONE
223                                   //! might be different from parent->parent_type (above)
224    size_t       orig_line;        //! line number of chunk in input file
225    size_t       orig_col;         //! column where chunk started in the input file, is always > 0
226    size_t       orig_col_end;     //! column where chunk ended in the input file, is always > 1
227    UINT32       orig_prev_sp;     //! whitespace before this token
228    pcf_flags_t  flags;            //! see PCF_xxx
229    size_t       column;           //! column of chunk
230    size_t       column_indent;    /** if 1st on a line, set to the 'indent'
231                                    * column, which may be less than the real
232                                    * column used to indent with tabs          */
233    size_t       nl_count;         //! number of newlines in CT_NEWLINE
234    size_t       nl_column;        //! column of the subsequent newline entries(all of them should have the same column)
235    size_t       level;            /** nest level in {, (, or [
236                                    * only to help vim command } */
237    size_t       brace_level;      //! nest level in braces only
238    size_t       pp_level;         //! nest level in preprocessor
239    bool         after_tab;        //! whether this token was after a tab
240    unc_text     str;              //! the token text
241 
242    // for debugging purpose only
243    track_list   *tracking;
244 };
245 
246 
247 //! list of all programming languages Uncrustify supports
248 enum lang_flag_e
249 {
250    LANG_C    = 0x0001,
251    LANG_CPP  = 0x0002,
252    LANG_D    = 0x0004,
253    LANG_CS   = 0x0008,     //! C# (C-Sharp)
254    LANG_JAVA = 0x0010,
255    LANG_OC   = 0x0020,     //! Objective-C
256    LANG_VALA = 0x0040,
257    LANG_PAWN = 0x0080,
258    LANG_ECMA = 0x0100,     //! ECMA Script (JavaScript)
259 
260    LANG_ALLC = 0x017f,     /** LANG_C    | LANG_CPP | LANG_D    | LANG_CS   |
261                             *  LANG_JAVA | LANG_OC  | LANG_VALA | LANG_ECMA   */
262    LANG_ALL  = 0x0fff,     //! applies to all languages
263 
264    FLAG_HDR  = 0x2000,     /*<< Header file for C family languages */
265    FLAG_DIG  = 0x4000,     //! digraph/trigraph
266    FLAG_PP   = 0x8000,     //! only appears in a preprocessor
267 };
268 
269 //! Pattern classes for special keywords
270 enum class pattern_class_e : unsigned int
271 {
272    NONE,
273    BRACED,   /** keyword + braced statement:
274               *    do, try, finally, body, unittest, unsafe, volatile
275               *    add, get, remove, set                                      */
276    PBRACED,  /** keyword + parens + braced statement:
277               *    if, elseif, switch, for, while, synchronized,
278               *    using, lock, with, version, CT_D_SCOPE_IF                  */
279    OPBRACED, /** keyword + optional parens + braced statement:
280               *    catch, version, debug                                      */
281    VBRACED,  /** keyword + value + braced statement:
282               *    namespace                                                  */
283    PAREN,    /** keyword + parens:
284               *    while-of-do                                                */
285    OPPAREN,  /** keyword + optional parens:
286               *    invariant (D lang)                                         */
287    ELSE,     /** Special case of pattern_class_e::BRACED for handling CT_IF
288               *    else                                                       */
289 };
290 
291 //! used to link language keywords with some addition information
292 struct chunk_tag_t
293 {
294    const char *tag;        //! name of the keyword e.g. "bool"
295    c_token_t  type;        //! uncrustify type assigned to that keyword
296    size_t     lang_flags;  //! programming language that uses this keyword
297 };
298 
299 
300 struct align_t
301 {
302    size_t    col;
303    c_token_t type;
304    size_t    len;    //! length of the token + space
305 };
306 
307 //! holds information and data of a file
308 struct file_mem
309 {
310    std::vector<UINT8> raw;  //! raw content of file
311    std::deque<int>    data; //! processed content of file
312    bool               bom;
313    char_encoding_e    enc;  //! character encoding of file ASCII, utf, etc.
314 #ifdef HAVE_UTIME_H
315    struct utimbuf     utb;
316 #endif
317 };
318 
319 enum class unc_stage_e : unsigned int
320 {
321    TOKENIZE,
322    HEADER,
323    TOKENIZE_CLEANUP,
324    BRACE_CLEANUP,
325    FIX_SYMBOLS,
326    MARK_COMMENTS,
327    COMBINE_LABELS,
328    OTHER,
329    CLEANUP
330 };
331 
332 struct cp_data_t
333 {
334    std::deque<UINT8> *bout;
335    FILE              *fout;
336    int               last_char;
337    bool              do_check;
338    unc_stage_e       unc_stage;
339    int               check_fail_cnt;       //! total failure count
340    bool              if_changed;
341 
342    UINT32            error_count;       //! counts how many errors occurred so far
343    std::string       filename;
344 
345    file_mem          file_hdr;          // for cmt_insert_file_header
346    file_mem          file_ftr;          // for cmt_insert_file_footer
347    file_mem          func_hdr;          // for cmt_insert_func_header
348    file_mem          oc_msg_hdr;        // for cmt_insert_oc_msg_header
349    file_mem          class_hdr;         // for cmt_insert_class_header
350    file_mem          reflow_fold_regex; // for cmt_reflow_fold_regex_file
351 
352    size_t            lang_flags;        //! defines the language of the source input
353    bool              lang_forced;       //! overwrites automatic language detection
354 
355    bool              unc_off;
356    bool              unc_off_used;       //! true if the `disable_processing_cmt` option was actively used in the processed file
357    UINT32            line_number;
358    size_t            column;             //! column for parsing
359    UINT16            spaces;             //! space count on output
360 
361    int               ifdef_over_whole_file;
362 
363    bool              frag;          //! activates code fragment option
364    UINT32            frag_cols;
365 
366    // stuff to auto-detect line endings
367    UINT32            le_counts[uncrustify::line_end_styles];
368    unc_text          newline;
369 
370    int               did_newline;       //! flag indicates if a newline was added or converted
371    c_token_t         in_preproc;
372    int               preproc_ncnl_count;
373    bool              output_trailspace;
374    bool              output_tab_as_space;
375 
376    bool              bom;
377    char_encoding_e   enc;
378 
379    // bumped up when a line is split or indented
380    int               changes;
381    int               pass_count;       //! indicates how often the chunk list shall be processed
382 
383    align_t           al[uncrustify::limits::AL_SIZE];
384    size_t            al_cnt;
385    bool              al_c99_array;
386 
387    bool              warned_unable_string_replace_tab_chars;
388 
389    int               pp_level;       // TODO: can this ever be -1?
390 
391    const char        *phase_name;
392    const char        *dumped_file;
393    const char        *html_file = nullptr; // for debugging purpose only
394 };
395 
396 extern cp_data_t cpd;  // TODO: can we avoid this external variable?
397 
398 const char *get_brace_stage_name(brace_stage_e brace_stage);
399 
400 const char *get_unc_stage_name(unc_stage_e unc_stage);
401 
402 #endif /* UNCRUSTIFY_TYPES_H_INCLUDED */
403