vfs: check userland buffers before reading them.
[haiku.git] / 3rdparty / proj2make / proj2make.cpp
blobb35a57a89eb9be17256eedb22c8d03dc6fef5201
1 /*
2 * Copyright 2012 Aleksas Pantechovskis, <alexp.frl@gmail.com>
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
6 #include <exception>
7 #include <fstream>
8 #include <iostream>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string>
12 #include <string.h>
14 #include <ByteOrder.h>
15 #include <FindDirectory.h>
16 #include <Path.h>
17 #include <String.h>
18 #include <TypeConstants.h>
21 using namespace std;
24 const char* kUsageMessage = \
25 "proj2make usage:\n"
26 "# proj2make <projPath> [makePath]\n"
27 "# if makePath parameter doesn't specified makefile will be created in\n"
28 "# the same directory as .proj file\n"
29 "# example: proj2make /boot/home/myprog/myprog.proj\n";
31 fstream gProjFile;
32 uint32 gProjLength;
33 uint8* gProjData;
35 fstream gMakeFile;
37 fstream gTemplateFile;
39 string gSPthString;
40 string gPPthString;
41 string gFil1String;
42 string gLinkString;
43 string gPLnkString;
45 const char* gAppTypes[] = {
46 "APP",
47 "SHARED",
48 "STAITC",
49 "DRIVER"
52 uint8 gAppType;
53 string gAppName;
55 struct hdr
57 uint32 Id() { return
58 static_cast<uint32>(B_BENDIAN_TO_HOST_INT32(fId)); }
59 uint32 Size() { return
60 static_cast<uint32>(B_BENDIAN_TO_HOST_INT32(fSize)); }
61 const char* Data() { return (char*)(this + 1); }
62 private:
63 uint32 fId;
64 uint32 fSize;
68 class Error : public std::exception
70 BString fWhat;
71 public:
72 Error(const char* what, ...);
73 virtual ~Error() throw() {}
74 virtual const char* what() const throw() { return fWhat.String(); }
78 Error::Error(const char* what, ...)
80 const int size = 1024;
81 va_list args;
82 va_start(args, what);
83 vsnprintf(fWhat.LockBuffer(size), size, what, args);
84 fWhat.UnlockBuffer();
85 va_end(args);
89 void
90 CheckFiles(const char* projPath, const char* makePath)
92 gProjFile.open(projPath, fstream::in | fstream::binary);
93 if (!gProjFile.is_open())
94 throw Error("%s not found", projPath);
96 gProjFile.seekg(0, ios::end);
97 uint32 projFileLength = gProjFile.tellg();
98 gProjFile.seekg(0, ios::beg);
100 char* name = new char[5];
101 gProjFile.read(name, 4);
103 uint32 length;
104 gProjFile.read((char*)&length, 4);
105 name[4] = '\0';
106 length = static_cast<uint32>(B_BENDIAN_TO_HOST_INT32(length));
107 gProjLength = length + 8;
109 if (strcmp(name, "MIDE") != 0 || gProjLength > projFileLength)
110 throw Error("File corrupted or it is not BeIDE *.proj file");
112 gMakeFile.open(makePath, fstream::in);
113 if (gMakeFile.is_open())
114 throw Error("%s already exists", makePath);
116 gMakeFile.open(makePath, fstream::out);
117 if (!gMakeFile.is_open())
118 throw Error("Can not create makefile");
120 BPath templateFileName;
121 // not supporter yet in my haiku rev
122 // find_directory(B_SYSTEM_DEVELOP_DIR, &templateFileName);
123 // templateFileName.Append("etc/makefile");
124 templateFileName.SetTo("/boot/develop/etc/makefile");
126 gTemplateFile.open(templateFileName.Path(), fstream::in);
127 if (!gTemplateFile.is_open())
128 throw Error("Can not open template %s", templateFileName.Path());
132 void
133 ParseGenB(hdr* data)
135 hdr* child = (hdr*)data->Data();
136 char* name = (char*)(child + 1);
137 int len = strlen(name) + 1;
139 uint32 u = child->Id();
140 char* c = (char*)&u;
141 printf("\t%c%c%c%c:%d:%s\n", c[3], c[2], c[1], c[0], child->Size(), name);
143 if (strncmp(name, "ProjectPrefsx86", len - 1) == 0) {
144 const char* type = child->Data() + len + 8;
145 if (*type <= 3)
146 gAppType = *type;
147 type++;
148 type += 64; // skip the mime type name
149 gAppName = type;
154 class _l {
155 static string _s;
156 public:
157 _l() { _s += " " ; }
158 ~_l() { _s.resize(_s.size() - 1); }
160 char* str() { _s.c_str(); }
163 string _l::_s;
165 void
166 Parse(hdr* current, hdr* parent)
168 _l l;
170 uint32 u = current->Id();
171 char* c = (char*)&u;
172 printf("%#06x:%s%c%c%c%c:%d\n",
173 (uint8*)current - gProjData, l.str(),
174 c[3], c[2], c[1], c[0], current->Size());
176 bool useGrandParent = false;
177 size_t off = 0;
178 switch(current->Id()) {
179 case 'Fil1':
180 case 'Link':
181 case 'PLnk':
182 off = 24;
183 break;
184 case 'MIDE':
185 case 'DPrf':
186 case 'GPrf':
187 break;
188 case 'MSFl':
189 off = 8;
190 useGrandParent = true;
191 break;
192 case 'SPth':
193 gSPthString += " \\\n\t";
194 gSPthString += &current->Data()[5];
195 return;
196 case 'PPth':
197 gPPthString += " \\\n\t";
198 gPPthString += &current->Data()[5];
199 return;
200 case 'Name':
201 if (parent->Id() == 'Fil1') {
202 gFil1String += " \\\n\t";
203 gFil1String += &current->Data()[4];
204 } else if (parent->Id() == 'Link') {
205 gLinkString += " \\\n\t";
206 gLinkString += &current->Data()[4];
207 } else if (parent->Id() == 'PLnk') {
208 gPLnkString += " \\\n\t";
209 gPLnkString += &current->Data()[4];
211 return;
212 case 'GenB':
213 ParseGenB(current);
214 return;
215 default:
216 return;
219 hdr* child = (hdr*)(current->Data() + off);
220 while (off < current->Size()) {
221 Parse(child, useGrandParent ? parent : current);
222 off += child->Size() + sizeof(hdr);
223 child = (hdr*)(child->Data() + child->Size());
228 void
229 ReadProj()
231 gProjFile.seekg(0, ios::beg);
232 gProjData = new uint8[gProjLength];
233 gProjFile.read((char*)gProjData, gProjLength);
234 gProjFile.close();
236 Parse((hdr*)gProjData, NULL);
240 void
241 Proj2Make()
243 gFil1String = " ";
244 gLinkString = " ";
245 gPLnkString = " ";
246 gSPthString = " ";
247 gPPthString = " ";
249 ReadProj();
250 string str;
251 while (gTemplateFile.good()) {
252 getline(gTemplateFile, str);
254 if (str.find("SRCS") == 0)
255 str = str + gFil1String;
256 else if (str.find("LIBS") == 0)
257 str = str + gLinkString;
258 else if (str.find("SYSTEM_INCLUDE_PATHS") == 0)
259 str = str + gSPthString;
260 else if (str.find("LOCAL_INCLUDE_PATHS") == 0)
261 str = str + gPPthString;
262 else if (str.find("TYPE") == 0)
263 str = str + gAppTypes[gAppType];
264 else if (str.find("NAME") == 0)
265 str = str + gAppName;
266 else if (str.find("RSRCS") == 0)
267 str = str + gPLnkString;
269 gMakeFile << str << endl;
272 gMakeFile.close();
273 gTemplateFile.close();
278 main(int argc, char** argv)
280 try {
281 if (argc <= 1 || (argc > 1 && strcmp(argv[1], "--help") == 0))
282 throw Error("");
284 BString projPath = argv[1];
286 BString makePath;
287 // if makefile path specified
288 if (argc > 2)
289 makePath = argv[2];
290 // default makefile path
291 else {
292 BPath path(argv[1]);
293 path.GetParent(&path);
294 path.Append("makefile");
295 makePath = path.Path();
298 CheckFiles(projPath.String(), makePath.String());
300 Proj2Make();
302 } catch(exception& exc) {
303 cerr << argv[0] << " : " << exc.what() << endl;
304 cerr << kUsageMessage;
305 return B_ERROR;
308 return B_OK;