stdutil.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. #include "stdutil.h"
  2. #include <errno.h>
  3. #include <sys/types.h>
  4. bool opt_trace; //-z BMK0: trace dependancies
  5. string opt_outfile; //-o BMK0: output exe
  6. bool opt_quiet; //-q
  7. bool opt_verbose; //-v
  8. bool opt_makeall; //-a
  9. bool opt_debug; //-d
  10. bool opt_release; //-r
  11. bool opt_threaded;
  12. string opt_arch; //-g x86/ppc
  13. string opt_apptype; //-t apptype
  14. string opt_module; //-m 'modname'
  15. string opt_framework; //-f 'modname' or "*"
  16. string opt_infile;
  17. set<string> env_config;
  18. string env_blitzpath,env_platform,env_binpath,env_libpath,config_mung,global_mung;
  19. #if _WIN32
  20. static void init_env(){
  21. char path[1024]={0};
  22. GetModuleFileName( GetModuleHandle(0),path,1024 );
  23. string t=path;
  24. int n=t.rfind( "\\bin\\" );
  25. if( n==string::npos ) n=t.rfind( "\\BIN\\" );
  26. if( n==string::npos ) abort();
  27. env_blitzpath=t.substr(0,n);
  28. env_platform="win32";
  29. }
  30. #elif __APPLE__
  31. static void init_env(){
  32. CFURLRef url;
  33. char path[1024],*p;
  34. url=CFBundleCopyExecutableURL( CFBundleGetMainBundle() );
  35. CFURLGetFileSystemRepresentation( url,true,(UInt8*)path,1024 );
  36. string t=path;
  37. int n=t.rfind( "/bin/" );
  38. if( n==string::npos ) abort();
  39. env_blitzpath=t.substr(0,n);
  40. env_platform="macos";
  41. }
  42. #elif __linux
  43. static void init_env(){
  44. char linkname[256]; // /proc/<pid>/exe
  45. char path[1024]={0};
  46. pid_t pid;
  47. int ret;
  48. pid=getpid();
  49. sprintf(linkname, "/proc/%i/exe", pid);
  50. ret=readlink(linkname, path,1024);
  51. if (ret<1 || ret>1022) abort();
  52. path[ret]=0;
  53. string t=path;
  54. int n=t.rfind( "/bin/" );
  55. if( n==string::npos ) abort();
  56. env_blitzpath=t.substr(0,n);
  57. env_platform="linux";
  58. }
  59. #else
  60. #error "Unsuppported build platform"
  61. #endif
  62. void stdutil_init( int argc,char *argv[] ){
  63. init_env();
  64. fixpath( env_blitzpath );
  65. env_binpath=env_blitzpath+"/bin";
  66. env_libpath=env_blitzpath+"/lib";
  67. #if __APPLE__
  68. #if __ppc__
  69. if( is_pid_native(0) ) opt_arch="ppc"; else opt_arch="x86";
  70. #elif __i386__
  71. if( is_pid_native(0) ) opt_arch="x86"; else opt_arch="ppc";
  72. #endif
  73. #else
  74. opt_arch="x86";
  75. #endif
  76. opt_debug=true;
  77. opt_release=false;
  78. for( int k=1;k<argc;++k ){
  79. char *t=argv[k];
  80. if( t[0]!='-' ){
  81. if( opt_infile.size() ) fail( "Only one input file may be specified" );
  82. opt_infile=realpath(t);
  83. continue;
  84. }
  85. switch( t[1] ){
  86. case 'q':
  87. opt_quiet=true;
  88. break;
  89. case 'v':
  90. opt_verbose=true;
  91. break;
  92. case 'a':
  93. opt_makeall=true;
  94. break;
  95. case 'd':
  96. opt_debug=true;
  97. opt_release=false;
  98. break;
  99. case 'r':
  100. opt_debug=false;
  101. opt_release=true;
  102. break;
  103. case 'h':
  104. opt_threaded=true;
  105. break;
  106. case 'z':
  107. opt_trace=true;
  108. break;
  109. case 't':
  110. if( ++k<argc ) opt_apptype=tolower(argv[k]);
  111. else fail( "Command line error" );
  112. break;
  113. case 'g':
  114. if( ++k<argc ) opt_arch=tolower(argv[k]);
  115. else fail( "Command line error" );
  116. break;
  117. case 'm':
  118. if( ++k<argc ) opt_module=tolower(argv[k]);
  119. else fail( "Command line error" );
  120. break;
  121. case 'f':
  122. if( ++k<argc ) opt_framework=tolower(argv[k]);
  123. else fail( "Command line error" );
  124. break;
  125. case 'o':
  126. if( ++k<argc ) opt_outfile=realpath( argv[k] );
  127. else fail( "Command line error" );
  128. break;
  129. default:
  130. fail( "Command line error" );
  131. }
  132. }
  133. if( opt_arch=="ppc" ){
  134. env_config.insert( "bigendian" );
  135. }else if( opt_arch=="x86" ){
  136. env_config.insert( "littleendian" );
  137. }else{
  138. fail( "Command line error" );
  139. }
  140. env_config.insert( opt_arch );
  141. env_config.insert( env_platform );
  142. env_config.insert( env_platform+opt_arch );
  143. env_config.insert( opt_debug ? "debug" : "release" );
  144. if( opt_threaded ) env_config.insert( "threaded" );
  145. config_mung=opt_debug ? "debug" : "release";
  146. if( opt_threaded ) config_mung+=".mt";
  147. config_mung="."+config_mung+"."+env_platform+"."+opt_arch;
  148. if( opt_module.size() ){
  149. vector<string> ids;
  150. splitModule( opt_module,ids );
  151. int k;
  152. for( k=0;k<ids.size();++k ) global_mung+=ids[k]+"_";
  153. }else{
  154. global_mung="bb_";
  155. }
  156. }
  157. void fixpath( string &path ){
  158. int i;
  159. for( i=0;i<path.size();++i ){
  160. if( path[i]=='\\' ) path[i]='/';
  161. }
  162. }
  163. void sys( string cmd ){
  164. if( opt_verbose ) cout<<cmd<<endl;
  165. #if _WIN32
  166. // simon was here with win98 cludge
  167. char path[8192];
  168. int i,n;
  169. n=_snprintf(path,8192,cmd.c_str());
  170. for (i=0;i<n;i++)
  171. {
  172. if (path[i]==0) break;
  173. if (path[i]=='/') path[i]='\\';
  174. }
  175. // printf("%d%s",n,path);
  176. if( system( path ) )
  177. exit(-1);
  178. #else
  179. if( system( cmd.c_str() ) )
  180. exit(-1);
  181. #endif
  182. }
  183. string modulePath( string mod,bool create ){
  184. string path=env_blitzpath+"/mod";
  185. if( !mod.size() ) return path;
  186. mod+=".";
  187. while( mod.size() ){
  188. int i=mod.find( '.' );
  189. string t=mod.substr(0,i);
  190. mod=mod.substr(i+1);
  191. path+='/'+t+".mod";
  192. if( create ){
  193. mkdir( path.c_str(),0777 );
  194. if( !ftime(path) ) fail( "mkdir failed!" );
  195. }
  196. }
  197. return path;
  198. }
  199. void splitModule( string mod,vector<string> &ids ){
  200. if( !mod.size() ) return;
  201. int i;
  202. while( (i=mod.find('.'))!=string::npos ){
  203. ids.push_back(mod.substr(0,i));
  204. mod=mod.substr(i+1);
  205. }
  206. ids.push_back(mod);
  207. }
  208. string moduleIdent( string mod ){
  209. int i=mod.rfind('.');
  210. return i==string::npos ? mod : mod.substr(i+1);
  211. }
  212. string moduleInterface( string mod ){
  213. string path=modulePath( mod,false )+"/"+moduleIdent(mod)+config_mung+".i";
  214. if( ftime( path ) ) return path;
  215. fail( "Can't find interface for module '%s'",mod.c_str() );
  216. return "";
  217. /*
  218. string path=modulePath( mod,false );
  219. string d_ext=".debug."+env_platform+"."+opt_arch+".i";
  220. string r_ext=".release."+env_platform+"."+opt_arch+".i";
  221. string f1=path+"/"+moduleIdent(mod)+r_ext;
  222. string f2=path+"/"+moduleIdent(mod)+d_ext;
  223. if( opt_debug ) std::swap(f1,f2);
  224. if( ftime(f1) ) return f1;
  225. if( ftime(f2) ) return f2;
  226. fail( "Can't find interface for module '%s'",mod.c_str() );
  227. return "";
  228. */
  229. }
  230. void enumModules( string mod,vector<string> &mods ){
  231. string path=modulePath( mod,false );
  232. DIR *d=opendir( path.c_str() );
  233. if( !d ) return;
  234. string d_ext=".debug."+env_platform+"."+opt_arch+".i";
  235. string r_ext=".release."+env_platform+"."+opt_arch+".i";
  236. while( dirent *e=readdir( d ) ){
  237. string f=e->d_name;
  238. if( getext(f)!="mod" ) continue;
  239. string id=stripall(f);
  240. string tmod=mod.size() ? mod+"."+id : id;
  241. enumModules( tmod,mods );
  242. string path=modulePath( tmod,false )+"/"+id;
  243. if( ftime(path+d_ext) || ftime(path+r_ext) ){
  244. mods.push_back( tmod );
  245. }
  246. }
  247. closedir(d);
  248. }
  249. time_t ftime( string path ){
  250. struct stat st;
  251. fixpath(path);
  252. if( !stat( path.c_str(),&st ) ) return st.st_mtime;
  253. return 0;
  254. }
  255. string getcwd(){
  256. char buf[256];
  257. if( !getcwd( buf,255 ) ) fail( "getcwd failed" );
  258. string path=string(buf);
  259. fixpath(path);
  260. return buf;
  261. }
  262. void setcwd( string path ){
  263. fixpath(path);
  264. chdir( path.c_str() );
  265. }
  266. string getdir( string path ){
  267. fixpath(path);
  268. int n=path.rfind( '/' );
  269. if( n==string::npos ) return "";
  270. return path.substr(0,n);
  271. }
  272. string getext( string path ){
  273. fixpath(path);
  274. int n=path.rfind( '.' );
  275. if( n==string::npos ) return "";
  276. if( path.find( '/',n+1 )!=string::npos ) return "";
  277. return path.substr(n+1);
  278. }
  279. string stripdir( string path ){
  280. fixpath(path);
  281. int n=path.rfind( '/' );
  282. if( n==string::npos ) n=path.rfind( '\\' );
  283. if( n==string::npos ) return path;
  284. return path.substr(n+1);
  285. }
  286. string stripext( string path ){
  287. fixpath(path);
  288. int n=path.rfind( '.' );
  289. if( n==string::npos ) return path;
  290. if( path.find( '/',n+1 )!=string::npos ) return path;
  291. if( path.find( '\\',n+1 )!=string::npos ) return path;
  292. return path.substr(0,n);
  293. }
  294. string stripall( string path ){
  295. return stripext(stripdir(path));
  296. }
  297. string realpath( string path ){
  298. fixpath(path);
  299. string dir=getdir(path);
  300. string file=stripdir(path);
  301. static char buf[MAX_PATH+8];
  302. if( dir.size() ){
  303. // printf( "Calling realpath( %s ), MAX_PATH=%i PATH_MAX=%i\n",dir.c_str(),MAX_PATH,PATH_MAX );fflush( stdout );
  304. if( !_realpath( dir.c_str(),buf ) ){
  305. fail( "realpath failed for %s",path.c_str() );
  306. }
  307. dir=buf;
  308. }else{
  309. dir=getcwd();
  310. }
  311. fixpath( dir );
  312. return dir+"/"+file;
  313. }
  314. string tolower( string t ){
  315. for( int k=0;k<t.size();++k ){
  316. t[k]=tolower(t[k]);
  317. }
  318. return t;
  319. }
  320. int64 toint( string t ){
  321. if( !t.size() ) return 0;
  322. int i,sgn=1;
  323. for( i=0;i<t.size() && (t[i]=='+' || t[i]=='-');++i ) if( t[i]=='-' ) sgn=-sgn;
  324. int64 n=0;
  325. if( t[i]=='%' ){
  326. for( ++i;i<t.size();++i ){
  327. int c=t[i];
  328. if( c!='0' && c!='1' ) break;
  329. n=n*2+(c-'0');
  330. }
  331. }else if( t[i]=='$' ){
  332. for( ++i;i<t.size();++i ){
  333. int c=toupper(t[i]);
  334. if( !isxdigit(c) ) break;
  335. if( c>='A' ) c-=('A'-'0'-10);
  336. n=n*16+(c-'0');
  337. }
  338. }else{
  339. for( ;i<t.size();++i ){
  340. int c=t[i];
  341. if( !isdigit(c) ) break;
  342. n=n*10+(c-'0');
  343. }
  344. }
  345. return sgn>0 ? n : -n;
  346. }
  347. double tofloat( string t ){
  348. double zero=0.0;
  349. string q=tolower(t);
  350. if( q=="nan#" ){
  351. return 0.0/zero;
  352. }else if( q=="inf#" || q=="+inf#" ){
  353. return 1.0/zero;
  354. }else if( q=="-inf#" ){
  355. return -1.0/zero;
  356. }
  357. return atof(t.c_str());
  358. }
  359. string fromint( int64 n ){
  360. // Can't use %lld 'coz it doesn't work on mingw!
  361. // char buf[64];
  362. // sprintf( buf,"%lld",n );
  363. // return buf;
  364. char buf[64],*p=buf+64;
  365. int neg=n<0;
  366. if( neg ){
  367. n=-n;
  368. if( n<0 ) return "-9223372036854775808";
  369. }
  370. *--p=0;
  371. do{
  372. *--p=n%10+'0';
  373. }while(n/=10);
  374. if( neg ) *--p='-';
  375. return p;
  376. }
  377. string fromfloat( float n ){
  378. char buf[64];
  379. if( isnan(n) ){
  380. sprintf( buf,"nan" );
  381. }else if( isinf(n) ){
  382. if( n>0 ) sprintf( buf,"inf" );
  383. else sprintf( buf,"-inf" );
  384. }else{
  385. sprintf( buf,"%#.9g",n );
  386. }
  387. return buf;
  388. }
  389. string fromdouble( double n ){
  390. char buf[64];
  391. if( isnan(n) ){
  392. sprintf( buf,"nan" );
  393. }else if( isinf(n) ){
  394. if( n>0 ) sprintf( buf,"inf" );
  395. else sprintf( buf,"-inf" );
  396. }else{
  397. sprintf( buf,"%#.17lg",n );
  398. }
  399. return buf;
  400. }
  401. string tostring( bstring w ){
  402. string t;
  403. t.resize(w.size());
  404. for( int k=0;k<t.size();++k ) t[k]=w[k];
  405. return t;
  406. }
  407. bstring tobstring( string t ){
  408. bstring w;
  409. w.resize(t.size());
  410. for( int k=0;k<w.size();++k ) w[k]=t[k] & 0xff;
  411. return w;
  412. }
  413. bstring tobstring( const char *p ){
  414. bstring w;
  415. w.resize(strlen(p));
  416. for( int k=0;k<w.size();++k ) w[k]=p[k] & 0xff;
  417. return w;
  418. }
  419. string source_info;
  420. void fail( const char *fmt,... ){
  421. char buf[256];
  422. va_list args;
  423. va_start( args,fmt );
  424. vsprintf( buf,fmt,args );
  425. cerr<<"Compile Error: "<<buf<<endl;
  426. if( source_info.size() ) cerr<<"["<<source_info<<"]"<<endl;
  427. exit(-1);
  428. }
  429. #if __APPLE__
  430. #include <sys/sysctl.h>
  431. static int sysctlbyname_with_pid (const char *name, pid_t pid,
  432. void *oldp, size_t *oldlenp,
  433. void *newp, size_t newlen)
  434. {
  435. if (pid == 0) {
  436. if (sysctlbyname(name, oldp, oldlenp, newp, newlen) == -1) {
  437. return -1;
  438. }
  439. }else{
  440. int mib[CTL_MAXNAME];
  441. size_t len = CTL_MAXNAME;
  442. if (sysctlnametomib(name, mib, &len) == -1) {
  443. return -1;
  444. }
  445. mib[len] = pid;
  446. len++;
  447. if (sysctl(mib, len, oldp, oldlenp, newp, newlen) == -1) {
  448. return -1;
  449. }
  450. }
  451. return 0;
  452. }
  453. int is_pid_native (pid_t pid)
  454. {
  455. int ret = 0;
  456. size_t sz = sizeof(ret);
  457. if (sysctlbyname_with_pid("sysctl.proc_native", pid, &ret, &sz, NULL, 0) == -1) {
  458. if (errno == ENOENT) {
  459. // sysctl doesn't exist, which means that this version of Mac OS
  460. // pre-dates Rosetta, so the application must be native.
  461. return 1;
  462. }
  463. return -1;
  464. }
  465. return ret;
  466. }
  467. #endif