summaryrefslogtreecommitdiff
path: root/dwarflint/dwarflint.hh
blob: 6b82883489f6ae7eb60270e94259743cc6460667 (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
/* Pedantic checking of DWARF files
   Copyright (C) 2009,2010,2011 Red Hat, Inc.
   This file is part of elfutils.

   This file 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 3 of the License, or
   (at your option) any later version.

   elfutils is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef DWARFLINT_HH
#define DWARFLINT_HH

#include <map>
#include <vector>
#include <stdexcept>
#include <iosfwd>

#include "../libelf/libelf.h"
#include "checks_i.hh"
#include "checkdescriptor_i.hh"
#include "checkrule.hh"
#include "check_registrar.hh"
#include "dwarflint_i.hh"
#include "highlevel_check_i.hh"

// Classes for full-blown check passes.
struct main_check_item
{
  virtual checkdescriptor const *descriptor () const = 0;
  virtual ~main_check_item () {}
  virtual void run (checkstack &stack, dwarflint &lint) = 0;
};

class main_check_registrar
  : public check_registrar_T<main_check_item>
{
public:
  friend class dwarflint;
  void run (dwarflint &lint);
};

class checkstack
  : public std::vector <checkdescriptor const *>
{};
std::ostream &operator << (std::ostream &o, checkstack const &stack);


class dwarflint
{
  typedef std::map <void const *, class check_base *> check_map;
  check_map _m_checks;
  char const *_m_fname;
  int _m_fd;
  checkrules const &_m_rules;

  static void *const marker;

  // Return a pointer to check, or NULL if the check hasn't been done
  // yet.  Throws check_base::failed if the check was requested
  // earlier but failed, or aborts program via assertion if recursion
  // was detected.
  void *find_check (void const *key);

  template <class T>
  static check_base *
  create_check_object (checkstack &stack, dwarflint &lint)
  {
    return new T (stack, lint);
  }

  void *dispatch_check (checkstack &stack,
			checkdescriptor const &cd,
			void const *key,
			check_base *(* create) (checkstack &, dwarflint &));

public:
  dwarflint (char const *fname, checkrules const &rules);
  ~dwarflint ();
  int fd () { return _m_fd; }
  char const *fname () { return _m_fname; }

  template <class T>
  T *
  check (checkstack &stack)
  {
    void const *key = T::key ();
    T *c = static_cast <T *> (find_check (key));
    checkdescriptor const &cd = *T::descriptor ();

    if (c == NULL)
      c = (T *)dispatch_check (stack, cd, key, &create_check_object<T>);

    return c;
  }

  template <class T>
  T *
  check (checkstack &stack, T *)
  {
    return check<T> (stack);
  }

  template <class T>
  T *toplev_check (checkstack &stack, T *fake = NULL);

  template <class T>
  T *
  check_if (bool whether, checkstack &stack,
	    __attribute__ ((unused)) T *fake = NULL)
  {
    if (whether)
      return check<T> (stack);
    else
      return NULL;
  }

  checkrules const &
  rules () const
  {
    return _m_rules;
  }

  static main_check_registrar *main_registrar ();

  static void list_checks ();
};

#endif//DWARFLINT_HH