1 /* 2 * Copyright 2012 Aleksas Pantechovskis, <alexp.frl@gmail.com> 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 #include <exception> 7 #include <fstream> 8 #include <iostream> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string> 12 #include <string.h> 13 14 #include <ByteOrder.h> 15 #include <FindDirectory.h> 16 #include <Path.h> 17 #include <String.h> 18 #include <TypeConstants.h> 19 20 21 using namespace std; 22 23 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"; 30 31 fstream gProjFile; 32 uint32 gProjLength; 33 uint8* gProjData; 34 35 fstream gMakeFile; 36 37 fstream gTemplateFile; 38 39 string gSPthString; 40 string gPPthString; 41 string gFil1String; 42 string gLinkString; 43 string gPLnkString; 44 45 const char* gAppTypes[] = { 46 "APP", 47 "SHARED", 48 "STAITC", 49 "DRIVER" 50 }; 51 52 uint8 gAppType; 53 string gAppName; 54 55 struct hdr 56 { 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; 65 }; 66 67 68 class Error : public std::exception 69 { 70 BString fWhat; 71 public: 72 Error(const char* what, ...); 73 virtual ~Error() throw() {} 74 virtual const char* what() const throw() { return fWhat.String(); } 75 }; 76 77 78 Error::Error(const char* what, ...) 79 { 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); 86 } 87 88 89 void 90 CheckFiles(const char* projPath, const char* makePath) 91 { 92 gProjFile.open(projPath, fstream::in | fstream::binary); 93 if (!gProjFile.is_open()) 94 throw Error("%s not found", projPath); 95 96 gProjFile.seekg(0, ios::end); 97 uint32 projFileLength = gProjFile.tellg(); 98 gProjFile.seekg(0, ios::beg); 99 100 char* name = new char[5]; 101 gProjFile.read(name, 4); 102 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; 108 109 if (strcmp(name, "MIDE") != 0 || gProjLength > projFileLength) 110 throw Error("File corrupted or it is not BeIDE *.proj file"); 111 112 gMakeFile.open(makePath, fstream::in); 113 if (gMakeFile.is_open()) 114 throw Error("%s already exists", makePath); 115 116 gMakeFile.open(makePath, fstream::out); 117 if (!gMakeFile.is_open()) 118 throw Error("Can not create makefile"); 119 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"); 125 126 gTemplateFile.open(templateFileName.Path(), fstream::in); 127 if (!gTemplateFile.is_open()) 128 throw Error("Can not open template %s", templateFileName.Path()); 129 } 130 131 132 void 133 ParseGenB(hdr* data) 134 { 135 hdr* child = (hdr*)data->Data(); 136 char* name = (char*)(child + 1); 137 int len = strlen(name) + 1; 138 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); 142 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; 150 } 151 } 152 153 154 class _l { 155 static string _s; 156 public: 157 _l() { _s += " " ; } 158 ~_l() { _s.resize(_s.size() - 1); } 159 160 char* str() { _s.c_str(); } 161 }; 162 163 string _l::_s; 164 165 void 166 Parse(hdr* current, hdr* parent) 167 { 168 _l l; 169 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()); 175 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 += ¤t->Data()[5]; 195 return; 196 case 'PPth': 197 gPPthString += " \\\n\t"; 198 gPPthString += ¤t->Data()[5]; 199 return; 200 case 'Name': 201 if (parent->Id() == 'Fil1') { 202 gFil1String += " \\\n\t"; 203 gFil1String += ¤t->Data()[4]; 204 } else if (parent->Id() == 'Link') { 205 gLinkString += " \\\n\t"; 206 gLinkString += ¤t->Data()[4]; 207 } else if (parent->Id() == 'PLnk') { 208 gPLnkString += " \\\n\t"; 209 gPLnkString += ¤t->Data()[4]; 210 } 211 return; 212 case 'GenB': 213 ParseGenB(current); 214 return; 215 default: 216 return; 217 } 218 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()); 224 } 225 } 226 227 228 void 229 ReadProj() 230 { 231 gProjFile.seekg(0, ios::beg); 232 gProjData = new uint8[gProjLength]; 233 gProjFile.read((char*)gProjData, gProjLength); 234 gProjFile.close(); 235 236 Parse((hdr*)gProjData, NULL); 237 } 238 239 240 void 241 Proj2Make() 242 { 243 gFil1String = " "; 244 gLinkString = " "; 245 gPLnkString = " "; 246 gSPthString = " "; 247 gPPthString = " "; 248 249 ReadProj(); 250 string str; 251 while (gTemplateFile.good()) { 252 getline(gTemplateFile, str); 253 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; 268 269 gMakeFile << str << endl; 270 } 271 272 gMakeFile.close(); 273 gTemplateFile.close(); 274 } 275 276 277 int 278 main(int argc, char** argv) 279 { 280 try { 281 if (argc <= 1 || (argc > 1 && strcmp(argv[1], "--help") == 0)) 282 throw Error(""); 283 284 BString projPath = argv[1]; 285 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(); 296 } 297 298 CheckFiles(projPath.String(), makePath.String()); 299 300 Proj2Make(); 301 302 } catch(exception& exc) { 303 cerr << argv[0] << " : " << exc.what() << endl; 304 cerr << kUsageMessage; 305 return B_ERROR; 306 } 307 308 return B_OK; 309 } 310 311