Welcome to mirror list, hosted at ThFree Co, Russian Federation.

plugins.cpp « src « libsass « src « node-sass « node_modules - github.com/austingebauer/devise.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: eecba7880423495960baf6f10457d4fd99642a5d (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
#include "sass.hpp"
#include <iostream>
#include "output.hpp"
#include "plugins.hpp"

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <dlfcn.h>
#endif

namespace Sass {

  Plugins::Plugins(void) { }
  Plugins::~Plugins(void)
  {
    for (auto function : functions) {
      sass_delete_function(function);
    }
    for (auto importer : importers) {
      sass_delete_importer(importer);
    }
    for (auto header : headers) {
      sass_delete_importer(header);
    }
  }

  // check if plugin is compatible with this version
  // plugins may be linked static against libsass
  // we try to be compatible between major versions
  inline bool compatibility(const char* their_version)
  {
// const char* their_version = "3.1.2";
    // first check if anyone has an unknown version
    const char* our_version = libsass_version();
    if (!strcmp(their_version, "[na]")) return false;
    if (!strcmp(our_version, "[na]")) return false;

    // find the position of the second dot
    size_t pos = std::string(our_version).find('.', 0);
    if (pos != std::string::npos) pos = std::string(our_version).find('.', pos + 1);

    // if we do not have two dots we fallback to compare complete string
    if (pos == std::string::npos) { return strcmp(their_version, our_version) ? 0 : 1; }
    // otherwise only compare up to the second dot (major versions)
    else { return strncmp(their_version, our_version, pos) ? 0 : 1; }

  }

  // load one specific plugin
  bool Plugins::load_plugin (const std::string& path)
  {

    typedef const char* (*__plugin_version__)(void);
    typedef Sass_Function_List (*__plugin_load_fns__)(void);
    typedef Sass_Importer_List (*__plugin_load_imps__)(void);

    if (LOAD_LIB(plugin, path))
    {
      // try to load initial function to query libsass version suppor
      if (LOAD_LIB_FN(__plugin_version__, plugin_version, "libsass_get_version"))
      {
        // get the libsass version of the plugin
        if (!compatibility(plugin_version())) return false;
        // try to get import address for "libsass_load_functions"
        if (LOAD_LIB_FN(__plugin_load_fns__, plugin_load_functions, "libsass_load_functions"))
        {
          Sass_Function_List fns = plugin_load_functions(), _p = fns;
          while (fns && *fns) { functions.push_back(*fns); ++ fns; }
          sass_free_memory(_p); // only delete the container, items not yet
        }
        // try to get import address for "libsass_load_importers"
        if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_importers, "libsass_load_importers"))
        {
          Sass_Importer_List imps = plugin_load_importers(), _p = imps;
          while (imps && *imps) { importers.push_back(*imps); ++ imps; }
          sass_free_memory(_p); // only delete the container, items not yet
        }
        // try to get import address for "libsass_load_headers"
        if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_headers, "libsass_load_headers"))
        {
          Sass_Importer_List imps = plugin_load_headers(), _p = imps;
          while (imps && *imps) { headers.push_back(*imps); ++ imps; }
          sass_free_memory(_p); // only delete the container, items not yet
        }
        // success
        return true;
      }
      else
      {
        // print debug message to stderr (should not happen)
        std::cerr << "failed loading 'libsass_support' in <" << path << ">" << std::endl;
        if (const char* dlsym_error = dlerror()) std::cerr << dlsym_error << std::endl;
        CLOSE_LIB(plugin);
      }
    }
    else
    {
      // print debug message to stderr (should not happen)
      std::cerr << "failed loading plugin <" << path << ">" << std::endl;
      if (const char* dlopen_error = dlerror()) std::cerr << dlopen_error << std::endl;
    }

    return false;

  }

  size_t Plugins::load_plugins(const std::string& path)
  {

    // count plugins
    size_t loaded = 0;

    #ifdef _WIN32

      try
      {

        // use wchar (utf16)
        WIN32_FIND_DATAW data;
        // trailing slash is guaranteed
        std::string globsrch(path + "*.dll");
        // convert to wide chars (utf16) for system call
        std::wstring wglobsrch(UTF_8::convert_to_utf16(globsrch));
        HANDLE hFile = FindFirstFileW(wglobsrch.c_str(), &data);
        // check if system called returned a result
        // ToDo: maybe we should print a debug message
        if (hFile == INVALID_HANDLE_VALUE) return -1;

        // read directory
        while (true)
        {
          try
          {
            // the system will report the filenames with wide chars (utf16)
            std::string entry = UTF_8::convert_from_utf16(data.cFileName);
            // check if file ending matches exactly
            if (!ends_with(entry, ".dll")) continue;
            // load the plugin and increase counter
            if (load_plugin(path + entry)) ++ loaded;
            // check if there should be more entries
            if (GetLastError() == ERROR_NO_MORE_FILES) break;
            // load next entry (check for return type)
            if (!FindNextFileW(hFile, &data)) break;
          }
          catch (...)
          {
            // report the error to the console (should not happen)
            // seems like we got strange data from the system call?
            std::cerr << "filename in plugin path has invalid utf8?" << std::endl;
          }
        }
      }
      catch (utf8::invalid_utf8)
      {
        // report the error to the console (should not happen)
        // implementors should make sure to provide valid utf8
        std::cerr << "plugin path contains invalid utf8" << std::endl;
      }

    #else

      DIR *dp;
      struct dirent *dirp;
      if((dp  = opendir(path.c_str())) == NULL) return -1;
      while ((dirp = readdir(dp)) != NULL) {
        #if __APPLE__
          if (!ends_with(dirp->d_name, ".dylib")) continue;
        #else
          if (!ends_with(dirp->d_name, ".so")) continue;
        #endif
        if (load_plugin(path + dirp->d_name)) ++ loaded;
      }
      closedir(dp);

    #endif
    return loaded;

  }

}