Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include "sal/config.h"
11 :
12 : #include <map>
13 : #include <vector>
14 :
15 : #include "osl/file.h"
16 : #include "osl/file.hxx"
17 : #include "rtl/character.hxx"
18 : #include "rtl/ref.hxx"
19 : #include "rtl/ustrbuf.hxx"
20 : #include "rtl/ustring.hxx"
21 : #include "unoidl/unoidl.hxx"
22 :
23 : #include "sourceprovider-parser-requires.hxx"
24 : #include "sourceprovider-parser.hxx"
25 : #include "sourceprovider-scanner.hxx"
26 : #include "sourcetreeprovider.hxx"
27 :
28 : #if defined MACOSX
29 : #include <dirent.h>
30 : #include "osl/thread.h"
31 : #endif
32 :
33 : namespace unoidl { namespace detail {
34 :
35 : namespace {
36 :
37 : //TODO: Bad hack to work around osl::FileStatus::getFileName not determining the
38 : // original spelling of a file name (not even with
39 : // osl_FileStatus_Mask_Validate):
40 0 : OUString getFileName(OUString const & uri, osl::FileStatus & status) {
41 : #if defined MACOSX
42 : sal_Int32 i = uri.lastIndexOf('/') + 1;
43 : OUString path;
44 : if (osl::FileBase::getSystemPathFromFileURL(uri.copy(0, i), path)
45 : != osl::FileBase::E_None)
46 : {
47 : SAL_WARN(
48 : "unoidl",
49 : "cannot getSystemPathFromFileURL(" << uri.copy(0, i) << ")");
50 : return status.getFileName();
51 : }
52 : OString dir(OUStringToOString(path, osl_getThreadTextEncoding()));
53 : OString name(OUStringToOString(uri.copy(i), osl_getThreadTextEncoding()));
54 : DIR * d = opendir(dir.getStr());
55 : if (d == 0) {
56 : SAL_WARN("unoidl", "cannot opendir(" << dir << ")");
57 : return status.getFileName();
58 : }
59 : for (;;) {
60 : dirent ent;
61 : dirent * p;
62 : int e = readdir_r(d, &ent, &p);
63 : if (e != 0) {
64 : SAL_WARN("unoidl", "cannot readdir_r");
65 : closedir(d);
66 : return status.getFileName();
67 : }
68 : if (p == 0) {
69 : SAL_WARN(
70 : "unoidl", "cannot find " << name << " via readdir of " << dir);
71 : closedir(d);
72 : return status.getFileName();
73 : }
74 : if (name.equalsIgnoreAsciiCase(p->d_name)) {
75 : closedir(d);
76 : return OUString(
77 : p->d_name, std::strlen(p->d_name), osl_getThreadTextEncoding());
78 : }
79 : }
80 : #else
81 : (void) uri;
82 0 : return status.getFileName();
83 : #endif
84 : }
85 :
86 0 : bool exists(OUString const & uri, bool directory) {
87 0 : osl::DirectoryItem item;
88 : osl::FileStatus status(
89 0 : osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName);
90 0 : return osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None
91 0 : && item.getFileStatus(status) == osl::FileBase::E_None
92 0 : && (status.getFileType() == osl::FileStatus::Directory) == directory
93 0 : && getFileName(uri, status) == uri.copy(uri.lastIndexOf('/') + 1);
94 : }
95 :
96 : class Cursor: public MapCursor {
97 : public:
98 0 : Cursor() {}
99 :
100 : private:
101 0 : virtual ~Cursor() throw () {}
102 :
103 0 : virtual rtl::Reference<Entity> getNext(OUString *) SAL_OVERRIDE
104 0 : { return rtl::Reference<Entity>(); } //TODO
105 : };
106 :
107 : class SourceModuleEntity: public ModuleEntity {
108 : public:
109 0 : SourceModuleEntity() {}
110 :
111 : private:
112 0 : virtual ~SourceModuleEntity() throw () {}
113 :
114 0 : virtual std::vector<OUString> getMemberNames() const SAL_OVERRIDE
115 0 : { return std::vector<OUString>(); } //TODO
116 :
117 0 : virtual rtl::Reference< MapCursor > createCursor() const SAL_OVERRIDE
118 0 : { return new Cursor; }
119 : };
120 :
121 : }
122 :
123 0 : SourceTreeProvider::SourceTreeProvider(
124 : rtl::Reference<Manager> const & manager, OUString const & uri):
125 0 : manager_(manager), uri_(uri.endsWith("/") ? uri : uri + "/")
126 0 : {}
127 :
128 0 : rtl::Reference<MapCursor> SourceTreeProvider::createRootCursor() const {
129 0 : return new Cursor;
130 : }
131 :
132 0 : rtl::Reference<Entity> SourceTreeProvider::findEntity(OUString const & name)
133 : const
134 : {
135 : std::map< OUString, rtl::Reference<Entity> >::iterator ci(
136 0 : cache_.find(name));
137 0 : if (ci != cache_.end()) {
138 0 : return ci->second;
139 : }
140 : // Match name against
141 : // name ::= identifier ("." identifier)*
142 : // identifier ::= upper-blocks | lower-block
143 : // upper-blocks ::= upper ("_"? alnum)*
144 : // lower-block :== lower alnum*
145 : // alnum ::= digit | upper | lower
146 : // digit ::= "0"--"9"
147 : // upper ::= "A"--"Z"
148 : // lower ::= "a"--"z"
149 0 : OUStringBuffer buf(name);
150 0 : sal_Int32 start = 0;
151 0 : sal_Int32 i = 0;
152 0 : for (; i != name.getLength(); ++i) {
153 0 : sal_Unicode c = name[i];
154 0 : if (c == '.') {
155 : assert(i == start || i != 0);
156 0 : if (i == start || name[i - 1] == '_') {
157 : throw FileFormatException( //TODO
158 0 : "", "Illegal UNOIDL identifier \"" + name + "\"");
159 : }
160 0 : buf[i] = '/';
161 0 : start = i + 1;
162 0 : } else if (c == '_') {
163 : assert(i == start || i != 0);
164 0 : if (i == start || name[i - 1] == '_'
165 0 : || !rtl::isAsciiUpperCase(name[start]))
166 : {
167 : throw FileFormatException( //TODO
168 0 : "", "Illegal UNOIDL identifier \"" + name + "\"");
169 : }
170 0 : } else if (rtl::isAsciiDigit(c)) {
171 0 : if (i == start) {
172 : throw FileFormatException( //TODO
173 0 : "", "Illegal UNOIDL identifier \"" + name + "\"");
174 : }
175 0 : } else if (!rtl::isAsciiAlpha(c)) {
176 : throw FileFormatException( //TODO
177 0 : "", "Illegal UNOIDL identifier \"" + name + "\"");
178 : }
179 : }
180 0 : if (i == start) {
181 : throw FileFormatException( //TODO
182 0 : "", "Illegal UNOIDL identifier \"" + name + "\"");
183 : }
184 0 : OUString uri(uri_ + buf.makeStringAndClear());
185 0 : rtl::Reference<Entity> ent;
186 : // Prevent conflicts between foo/ and Foo.idl on case-preserving file
187 : // systems:
188 0 : if (exists(uri, true) && !exists(uri + ".idl", false)) {
189 0 : ent = new SourceModuleEntity;
190 : } else {
191 0 : uri += ".idl";
192 0 : SourceProviderScannerData data(manager_);
193 0 : if (parse(uri, &data)) {
194 : std::map<OUString, SourceProviderEntity>::const_iterator j(
195 0 : data.entities.find(name));
196 0 : if (j != data.entities.end()) {
197 0 : ent = j->second.entity;
198 : }
199 : SAL_WARN_IF(
200 : !ent.is(), "unoidl",
201 : "<" << uri << "> does not define entity " << name);
202 0 : }
203 : }
204 : cache_.insert(
205 0 : std::map< OUString, rtl::Reference<Entity> >::value_type(name, ent));
206 0 : return ent;
207 : }
208 :
209 0 : SourceTreeProvider::~SourceTreeProvider() throw () {}
210 :
211 : } }
212 :
213 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|