cmdlib.c 20 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // cmdlib.c
  19. #include "cmdlib.h"
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #ifdef WIN32
  23. #include <direct.h>
  24. #include <windows.h>
  25. #endif
  26. #ifdef NeXT
  27. #include <libc.h>
  28. #endif
  29. #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
  30. #define PATHSEPERATOR '/'
  31. // set these before calling CheckParm
  32. int myargc;
  33. char **myargv;
  34. char com_token[1024];
  35. qboolean com_eof;
  36. qboolean archive;
  37. char archivedir[1024];
  38. /*
  39. ===================
  40. ExpandWildcards
  41. Mimic unix command line expansion
  42. ===================
  43. */
  44. #define MAX_EX_ARGC 1024
  45. int ex_argc;
  46. char *ex_argv[MAX_EX_ARGC];
  47. #ifdef _WIN32
  48. #include "io.h"
  49. void ExpandWildcards( int *argc, char ***argv )
  50. {
  51. struct _finddata_t fileinfo;
  52. int handle;
  53. int i;
  54. char filename[1024];
  55. char filebase[1024];
  56. char *path;
  57. ex_argc = 0;
  58. for (i=0 ; i<*argc ; i++)
  59. {
  60. path = (*argv)[i];
  61. if ( path[0] == '-'
  62. || ( !strstr(path, "*") && !strstr(path, "?") ) )
  63. {
  64. ex_argv[ex_argc++] = path;
  65. continue;
  66. }
  67. handle = _findfirst (path, &fileinfo);
  68. if (handle == -1)
  69. return;
  70. ExtractFilePath (path, filebase);
  71. do
  72. {
  73. sprintf (filename, "%s%s", filebase, fileinfo.name);
  74. ex_argv[ex_argc++] = copystring (filename);
  75. } while (_findnext( handle, &fileinfo ) != -1);
  76. _findclose (handle);
  77. }
  78. *argc = ex_argc;
  79. *argv = ex_argv;
  80. }
  81. #else
  82. void ExpandWildcards (int *argc, char ***argv)
  83. {
  84. }
  85. #endif
  86. #ifdef WIN_ERROR
  87. #include <windows.h>
  88. /*
  89. =================
  90. Error
  91. For abnormal program terminations in windowed apps
  92. =================
  93. */
  94. void Error( const char *error, ... )
  95. {
  96. va_list argptr;
  97. char text[1024];
  98. char text2[1024];
  99. int err;
  100. err = GetLastError ();
  101. va_start (argptr,error);
  102. vsprintf (text, error,argptr);
  103. va_end (argptr);
  104. sprintf (text2, "%s\nGetLastError() = %i", text, err);
  105. MessageBox(NULL, text2, "Error", 0 /* MB_OK */ );
  106. exit (1);
  107. }
  108. #else
  109. /*
  110. =================
  111. Error
  112. For abnormal program terminations in console apps
  113. =================
  114. */
  115. void Error( const char *error, ...)
  116. {
  117. va_list argptr;
  118. _printf ("\n************ ERROR ************\n");
  119. va_start (argptr,error);
  120. vprintf (error,argptr);
  121. va_end (argptr);
  122. _printf ("\r\n");
  123. exit (1);
  124. }
  125. #endif
  126. // only printf if in verbose mode
  127. qboolean verbose = qfalse;
  128. void qprintf( const char *format, ... ) {
  129. va_list argptr;
  130. if (!verbose)
  131. return;
  132. va_start (argptr,format);
  133. vprintf (format,argptr);
  134. va_end (argptr);
  135. }
  136. #ifdef WIN32
  137. HWND hwndOut = NULL;
  138. qboolean lookedForServer = qfalse;
  139. UINT wm_BroadcastCommand = -1;
  140. #endif
  141. void _printf( const char *format, ... ) {
  142. va_list argptr;
  143. char text[4096];
  144. ATOM a;
  145. va_start (argptr,format);
  146. vsprintf (text, format, argptr);
  147. va_end (argptr);
  148. printf(text);
  149. #ifdef WIN32
  150. if (!lookedForServer) {
  151. lookedForServer = qtrue;
  152. hwndOut = FindWindow(NULL, "Q3Map Process Server");
  153. if (hwndOut) {
  154. wm_BroadcastCommand = RegisterWindowMessage( "Q3MPS_BroadcastCommand" );
  155. }
  156. }
  157. if (hwndOut) {
  158. a = GlobalAddAtom(text);
  159. PostMessage(hwndOut, wm_BroadcastCommand, 0, (LPARAM)a);
  160. }
  161. #endif
  162. }
  163. /*
  164. qdir will hold the path up to the quake directory, including the slash
  165. f:\quake\
  166. /raid/quake/
  167. gamedir will hold qdir + the game directory (id1, id2, etc)
  168. */
  169. char qdir[1024];
  170. char gamedir[1024];
  171. char writedir[1024];
  172. void SetQdirFromPath( const char *path )
  173. {
  174. char temp[1024];
  175. const char *c;
  176. const char *sep;
  177. int len, count;
  178. if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
  179. { // path is partial
  180. Q_getwd (temp);
  181. strcat (temp, path);
  182. path = temp;
  183. }
  184. // search for "quake2" in path
  185. len = strlen(BASEDIRNAME);
  186. for (c=path+strlen(path)-1 ; c != path ; c--)
  187. {
  188. int i;
  189. if (!Q_strncasecmp (c, BASEDIRNAME, len))
  190. {
  191. //
  192. //strncpy (qdir, path, c+len+2-path);
  193. // the +2 assumes a 2 or 3 following quake which is not the
  194. // case with a retail install
  195. // so we need to add up how much to the next separator
  196. sep = c + len;
  197. count = 1;
  198. while (*sep && *sep != '/' && *sep != '\\')
  199. {
  200. sep++;
  201. count++;
  202. }
  203. strncpy (qdir, path, c+len+count-path);
  204. qprintf ("qdir: %s\n", qdir);
  205. for ( i = 0; i < strlen( qdir ); i++ )
  206. {
  207. if ( qdir[i] == '\\' )
  208. qdir[i] = '/';
  209. }
  210. c += len+count;
  211. while (*c)
  212. {
  213. if (*c == '/' || *c == '\\')
  214. {
  215. strncpy (gamedir, path, c+1-path);
  216. for ( i = 0; i < strlen( gamedir ); i++ )
  217. {
  218. if ( gamedir[i] == '\\' )
  219. gamedir[i] = '/';
  220. }
  221. qprintf ("gamedir: %s\n", gamedir);
  222. if ( !writedir[0] )
  223. strcpy( writedir, gamedir );
  224. else if ( writedir[strlen( writedir )-1] != '/' )
  225. {
  226. writedir[strlen( writedir )] = '/';
  227. writedir[strlen( writedir )+1] = 0;
  228. }
  229. return;
  230. }
  231. c++;
  232. }
  233. Error ("No gamedir in %s", path);
  234. return;
  235. }
  236. }
  237. Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
  238. }
  239. char *ExpandArg (const char *path)
  240. {
  241. static char full[1024];
  242. if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
  243. {
  244. Q_getwd (full);
  245. strcat (full, path);
  246. }
  247. else
  248. strcpy (full, path);
  249. return full;
  250. }
  251. char *ExpandPath (const char *path)
  252. {
  253. static char full[1024];
  254. if (!qdir)
  255. Error ("ExpandPath called without qdir set");
  256. if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
  257. strcpy( full, path );
  258. return full;
  259. }
  260. sprintf (full, "%s%s", qdir, path);
  261. return full;
  262. }
  263. char *ExpandGamePath (const char *path)
  264. {
  265. static char full[1024];
  266. if (!qdir)
  267. Error ("ExpandGamePath called without qdir set");
  268. if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
  269. strcpy( full, path );
  270. return full;
  271. }
  272. sprintf (full, "%s%s", gamedir, path);
  273. return full;
  274. }
  275. char *ExpandPathAndArchive (const char *path)
  276. {
  277. char *expanded;
  278. char archivename[1024];
  279. expanded = ExpandPath (path);
  280. if (archive)
  281. {
  282. sprintf (archivename, "%s/%s", archivedir, path);
  283. QCopyFile (expanded, archivename);
  284. }
  285. return expanded;
  286. }
  287. char *copystring(const char *s)
  288. {
  289. char *b;
  290. b = malloc(strlen(s)+1);
  291. strcpy (b, s);
  292. return b;
  293. }
  294. /*
  295. ================
  296. I_FloatTime
  297. ================
  298. */
  299. double I_FloatTime (void)
  300. {
  301. time_t t;
  302. time (&t);
  303. return t;
  304. #if 0
  305. // more precise, less portable
  306. struct timeval tp;
  307. struct timezone tzp;
  308. static int secbase;
  309. gettimeofday(&tp, &tzp);
  310. if (!secbase)
  311. {
  312. secbase = tp.tv_sec;
  313. return tp.tv_usec/1000000.0;
  314. }
  315. return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
  316. #endif
  317. }
  318. void Q_getwd (char *out)
  319. {
  320. int i = 0;
  321. #ifdef WIN32
  322. _getcwd (out, 256);
  323. strcat (out, "\\");
  324. #else
  325. getwd (out);
  326. strcat (out, "/");
  327. #endif
  328. while ( out[i] != 0 )
  329. {
  330. if ( out[i] == '\\' )
  331. out[i] = '/';
  332. i++;
  333. }
  334. }
  335. void Q_mkdir (const char *path)
  336. {
  337. #ifdef WIN32
  338. if (_mkdir (path) != -1)
  339. return;
  340. #else
  341. if (mkdir (path, 0777) != -1)
  342. return;
  343. #endif
  344. if (errno != EEXIST)
  345. Error ("mkdir %s: %s",path, strerror(errno));
  346. }
  347. /*
  348. ============
  349. FileTime
  350. returns -1 if not present
  351. ============
  352. */
  353. int FileTime (const char *path)
  354. {
  355. struct stat buf;
  356. if (stat (path,&buf) == -1)
  357. return -1;
  358. return buf.st_mtime;
  359. }
  360. /*
  361. ==============
  362. COM_Parse
  363. Parse a token out of a string
  364. ==============
  365. */
  366. char *COM_Parse (char *data)
  367. {
  368. int c;
  369. int len;
  370. len = 0;
  371. com_token[0] = 0;
  372. if (!data)
  373. return NULL;
  374. // skip whitespace
  375. skipwhite:
  376. while ( (c = *data) <= ' ')
  377. {
  378. if (c == 0)
  379. {
  380. com_eof = qtrue;
  381. return NULL; // end of file;
  382. }
  383. data++;
  384. }
  385. // skip // comments
  386. if (c=='/' && data[1] == '/')
  387. {
  388. while (*data && *data != '\n')
  389. data++;
  390. goto skipwhite;
  391. }
  392. // handle quoted strings specially
  393. if (c == '\"')
  394. {
  395. data++;
  396. do
  397. {
  398. c = *data++;
  399. if (c=='\"')
  400. {
  401. com_token[len] = 0;
  402. return data;
  403. }
  404. com_token[len] = c;
  405. len++;
  406. } while (1);
  407. }
  408. // parse single characters
  409. if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
  410. {
  411. com_token[len] = c;
  412. len++;
  413. com_token[len] = 0;
  414. return data+1;
  415. }
  416. // parse a regular word
  417. do
  418. {
  419. com_token[len] = c;
  420. data++;
  421. len++;
  422. c = *data;
  423. if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
  424. break;
  425. } while (c>32);
  426. com_token[len] = 0;
  427. return data;
  428. }
  429. int Q_strncasecmp (const char *s1, const char *s2, int n)
  430. {
  431. int c1, c2;
  432. do
  433. {
  434. c1 = *s1++;
  435. c2 = *s2++;
  436. if (!n--)
  437. return 0; // strings are equal until end point
  438. if (c1 != c2)
  439. {
  440. if (c1 >= 'a' && c1 <= 'z')
  441. c1 -= ('a' - 'A');
  442. if (c2 >= 'a' && c2 <= 'z')
  443. c2 -= ('a' - 'A');
  444. if (c1 != c2)
  445. return -1; // strings not equal
  446. }
  447. } while (c1);
  448. return 0; // strings are equal
  449. }
  450. int Q_stricmp (const char *s1, const char *s2)
  451. {
  452. return Q_strncasecmp (s1, s2, 99999);
  453. }
  454. char *strupr (char *start)
  455. {
  456. char *in;
  457. in = start;
  458. while (*in)
  459. {
  460. *in = toupper(*in);
  461. in++;
  462. }
  463. return start;
  464. }
  465. char *strlower (char *start)
  466. {
  467. char *in;
  468. in = start;
  469. while (*in)
  470. {
  471. *in = tolower(*in);
  472. in++;
  473. }
  474. return start;
  475. }
  476. /*
  477. =============================================================================
  478. MISC FUNCTIONS
  479. =============================================================================
  480. */
  481. /*
  482. =================
  483. CheckParm
  484. Checks for the given parameter in the program's command line arguments
  485. Returns the argument number (1 to argc-1) or 0 if not present
  486. =================
  487. */
  488. int CheckParm (const char *check)
  489. {
  490. int i;
  491. for (i = 1;i<myargc;i++)
  492. {
  493. if ( !Q_stricmp(check, myargv[i]) )
  494. return i;
  495. }
  496. return 0;
  497. }
  498. /*
  499. ================
  500. Q_filelength
  501. ================
  502. */
  503. int Q_filelength (FILE *f)
  504. {
  505. int pos;
  506. int end;
  507. pos = ftell (f);
  508. fseek (f, 0, SEEK_END);
  509. end = ftell (f);
  510. fseek (f, pos, SEEK_SET);
  511. return end;
  512. }
  513. FILE *SafeOpenWrite (const char *filename)
  514. {
  515. FILE *f;
  516. f = fopen(filename, "wb");
  517. if (!f)
  518. Error ("Error opening %s: %s",filename,strerror(errno));
  519. return f;
  520. }
  521. FILE *SafeOpenRead (const char *filename)
  522. {
  523. FILE *f;
  524. f = fopen(filename, "rb");
  525. if (!f)
  526. Error ("Error opening %s: %s",filename,strerror(errno));
  527. return f;
  528. }
  529. void SafeRead (FILE *f, void *buffer, int count)
  530. {
  531. if ( fread (buffer, 1, count, f) != (size_t)count)
  532. Error ("File read failure");
  533. }
  534. void SafeWrite (FILE *f, const void *buffer, int count)
  535. {
  536. if (fwrite (buffer, 1, count, f) != (size_t)count)
  537. Error ("File write failure");
  538. }
  539. /*
  540. ==============
  541. FileExists
  542. ==============
  543. */
  544. qboolean FileExists (const char *filename)
  545. {
  546. FILE *f;
  547. f = fopen (filename, "r");
  548. if (!f)
  549. return qfalse;
  550. fclose (f);
  551. return qtrue;
  552. }
  553. /*
  554. ==============
  555. LoadFile
  556. ==============
  557. */
  558. int LoadFile( const char *filename, void **bufferptr )
  559. {
  560. FILE *f;
  561. int length;
  562. void *buffer;
  563. f = SafeOpenRead (filename);
  564. length = Q_filelength (f);
  565. buffer = malloc (length+1);
  566. ((char *)buffer)[length] = 0;
  567. SafeRead (f, buffer, length);
  568. fclose (f);
  569. *bufferptr = buffer;
  570. return length;
  571. }
  572. /*
  573. ==============
  574. LoadFileBlock
  575. -
  576. rounds up memory allocation to 4K boundry
  577. -
  578. ==============
  579. */
  580. int LoadFileBlock( const char *filename, void **bufferptr )
  581. {
  582. FILE *f;
  583. int length, nBlock, nAllocSize;
  584. void *buffer;
  585. f = SafeOpenRead (filename);
  586. length = Q_filelength (f);
  587. nAllocSize = length;
  588. nBlock = nAllocSize % MEM_BLOCKSIZE;
  589. if ( nBlock > 0) {
  590. nAllocSize += MEM_BLOCKSIZE - nBlock;
  591. }
  592. buffer = malloc (nAllocSize+1);
  593. memset(buffer, 0, nAllocSize+1);
  594. SafeRead (f, buffer, length);
  595. fclose (f);
  596. *bufferptr = buffer;
  597. return length;
  598. }
  599. /*
  600. ==============
  601. TryLoadFile
  602. Allows failure
  603. ==============
  604. */
  605. int TryLoadFile (const char *filename, void **bufferptr)
  606. {
  607. FILE *f;
  608. int length;
  609. void *buffer;
  610. *bufferptr = NULL;
  611. f = fopen (filename, "rb");
  612. if (!f)
  613. return -1;
  614. length = Q_filelength (f);
  615. buffer = malloc (length+1);
  616. ((char *)buffer)[length] = 0;
  617. SafeRead (f, buffer, length);
  618. fclose (f);
  619. *bufferptr = buffer;
  620. return length;
  621. }
  622. /*
  623. ==============
  624. SaveFile
  625. ==============
  626. */
  627. void SaveFile (const char *filename, const void *buffer, int count)
  628. {
  629. FILE *f;
  630. f = SafeOpenWrite (filename);
  631. SafeWrite (f, buffer, count);
  632. fclose (f);
  633. }
  634. void DefaultExtension (char *path, const char *extension)
  635. {
  636. char *src;
  637. //
  638. // if path doesnt have a .EXT, append extension
  639. // (extension should include the .)
  640. //
  641. src = path + strlen(path) - 1;
  642. while (*src != '/' && *src != '\\' && src != path)
  643. {
  644. if (*src == '.')
  645. return; // it has an extension
  646. src--;
  647. }
  648. strcat (path, extension);
  649. }
  650. void DefaultPath (char *path, const char *basepath)
  651. {
  652. char temp[128];
  653. if (path[0] == PATHSEPERATOR)
  654. return; // absolute path location
  655. strcpy (temp,path);
  656. strcpy (path,basepath);
  657. strcat (path,temp);
  658. }
  659. void StripFilename (char *path)
  660. {
  661. int length;
  662. length = strlen(path)-1;
  663. while (length > 0 && path[length] != PATHSEPERATOR)
  664. length--;
  665. path[length] = 0;
  666. }
  667. void StripExtension (char *path)
  668. {
  669. int length;
  670. length = strlen(path)-1;
  671. while (length > 0 && path[length] != '.')
  672. {
  673. length--;
  674. if (path[length] == '/')
  675. return; // no extension
  676. }
  677. if (length)
  678. path[length] = 0;
  679. }
  680. /*
  681. ====================
  682. Extract file parts
  683. ====================
  684. */
  685. // FIXME: should include the slash, otherwise
  686. // backing to an empty path will be wrong when appending a slash
  687. void ExtractFilePath (const char *path, char *dest)
  688. {
  689. const char *src;
  690. src = path + strlen(path) - 1;
  691. //
  692. // back up until a \ or the start
  693. //
  694. while (src != path && *(src-1) != '\\' && *(src-1) != '/')
  695. src--;
  696. memcpy (dest, path, src-path);
  697. dest[src-path] = 0;
  698. }
  699. void ExtractFileBase (const char *path, char *dest)
  700. {
  701. const char *src;
  702. src = path + strlen(path) - 1;
  703. //
  704. // back up until a \ or the start
  705. //
  706. while (src != path && *(src-1) != PATHSEPERATOR)
  707. src--;
  708. while (*src && *src != '.')
  709. {
  710. *dest++ = *src++;
  711. }
  712. *dest = 0;
  713. }
  714. void ExtractFileExtension (const char *path, char *dest)
  715. {
  716. const char *src;
  717. src = path + strlen(path) - 1;
  718. //
  719. // back up until a . or the start
  720. //
  721. while (src != path && *(src-1) != '.')
  722. src--;
  723. if (src == path)
  724. {
  725. *dest = 0; // no extension
  726. return;
  727. }
  728. strcpy (dest,src);
  729. }
  730. /*
  731. ==============
  732. ParseNum / ParseHex
  733. ==============
  734. */
  735. int ParseHex (const char *hex)
  736. {
  737. const char *str;
  738. int num;
  739. num = 0;
  740. str = hex;
  741. while (*str)
  742. {
  743. num <<= 4;
  744. if (*str >= '0' && *str <= '9')
  745. num += *str-'0';
  746. else if (*str >= 'a' && *str <= 'f')
  747. num += 10 + *str-'a';
  748. else if (*str >= 'A' && *str <= 'F')
  749. num += 10 + *str-'A';
  750. else
  751. Error ("Bad hex number: %s",hex);
  752. str++;
  753. }
  754. return num;
  755. }
  756. int ParseNum (const char *str)
  757. {
  758. if (str[0] == '$')
  759. return ParseHex (str+1);
  760. if (str[0] == '0' && str[1] == 'x')
  761. return ParseHex (str+2);
  762. return atol (str);
  763. }
  764. /*
  765. ============================================================================
  766. BYTE ORDER FUNCTIONS
  767. ============================================================================
  768. */
  769. #ifdef _SGI_SOURCE
  770. #define __BIG_ENDIAN__
  771. #endif
  772. #ifdef __BIG_ENDIAN__
  773. short LittleShort (short l)
  774. {
  775. byte b1,b2;
  776. b1 = l&255;
  777. b2 = (l>>8)&255;
  778. return (b1<<8) + b2;
  779. }
  780. short BigShort (short l)
  781. {
  782. return l;
  783. }
  784. int LittleLong (int l)
  785. {
  786. byte b1,b2,b3,b4;
  787. b1 = l&255;
  788. b2 = (l>>8)&255;
  789. b3 = (l>>16)&255;
  790. b4 = (l>>24)&255;
  791. return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
  792. }
  793. int BigLong (int l)
  794. {
  795. return l;
  796. }
  797. float LittleFloat (float l)
  798. {
  799. union {byte b[4]; float f;} in, out;
  800. in.f = l;
  801. out.b[0] = in.b[3];
  802. out.b[1] = in.b[2];
  803. out.b[2] = in.b[1];
  804. out.b[3] = in.b[0];
  805. return out.f;
  806. }
  807. float BigFloat (float l)
  808. {
  809. return l;
  810. }
  811. #else
  812. short BigShort (short l)
  813. {
  814. byte b1,b2;
  815. b1 = l&255;
  816. b2 = (l>>8)&255;
  817. return (b1<<8) + b2;
  818. }
  819. short LittleShort (short l)
  820. {
  821. return l;
  822. }
  823. int BigLong (int l)
  824. {
  825. byte b1,b2,b3,b4;
  826. b1 = l&255;
  827. b2 = (l>>8)&255;
  828. b3 = (l>>16)&255;
  829. b4 = (l>>24)&255;
  830. return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
  831. }
  832. int LittleLong (int l)
  833. {
  834. return l;
  835. }
  836. float BigFloat (float l)
  837. {
  838. union {byte b[4]; float f;} in, out;
  839. in.f = l;
  840. out.b[0] = in.b[3];
  841. out.b[1] = in.b[2];
  842. out.b[2] = in.b[1];
  843. out.b[3] = in.b[0];
  844. return out.f;
  845. }
  846. float LittleFloat (float l)
  847. {
  848. return l;
  849. }
  850. #endif
  851. //=======================================================
  852. // FIXME: byte swap?
  853. // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
  854. // and the initial and final xor values shown below... in other words, the
  855. // CCITT standard CRC used by XMODEM
  856. #define CRC_INIT_VALUE 0xffff
  857. #define CRC_XOR_VALUE 0x0000
  858. static unsigned short crctable[256] =
  859. {
  860. 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  861. 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  862. 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  863. 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  864. 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  865. 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  866. 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  867. 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  868. 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  869. 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  870. 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  871. 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  872. 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  873. 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  874. 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  875. 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  876. 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  877. 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  878. 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  879. 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  880. 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  881. 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  882. 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  883. 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  884. 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  885. 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  886. 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  887. 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  888. 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  889. 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  890. 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  891. 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
  892. };
  893. void CRC_Init(unsigned short *crcvalue)
  894. {
  895. *crcvalue = CRC_INIT_VALUE;
  896. }
  897. void CRC_ProcessByte(unsigned short *crcvalue, byte data)
  898. {
  899. *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
  900. }
  901. unsigned short CRC_Value(unsigned short crcvalue)
  902. {
  903. return crcvalue ^ CRC_XOR_VALUE;
  904. }
  905. //=============================================================================
  906. /*
  907. ============
  908. CreatePath
  909. ============
  910. */
  911. void CreatePath (const char *path)
  912. {
  913. const char *ofs;
  914. char c;
  915. char dir[1024];
  916. #ifdef _WIN32
  917. int olddrive = -1;
  918. if ( path[1] == ':' )
  919. {
  920. olddrive = _getdrive();
  921. _chdrive( toupper( path[0] ) - 'A' + 1 );
  922. }
  923. #endif
  924. if (path[1] == ':')
  925. path += 2;
  926. for (ofs = path+1 ; *ofs ; ofs++)
  927. {
  928. c = *ofs;
  929. if (c == '/' || c == '\\')
  930. { // create the directory
  931. memcpy( dir, path, ofs - path );
  932. dir[ ofs - path ] = 0;
  933. Q_mkdir( dir );
  934. }
  935. }
  936. #ifdef _WIN32
  937. if ( olddrive != -1 )
  938. {
  939. _chdrive( olddrive );
  940. }
  941. #endif
  942. }
  943. /*
  944. ============
  945. QCopyFile
  946. Used to archive source files
  947. ============
  948. */
  949. void QCopyFile (const char *from, const char *to)
  950. {
  951. void *buffer;
  952. int length;
  953. length = LoadFile (from, &buffer);
  954. CreatePath (to);
  955. SaveFile (to, buffer, length);
  956. free (buffer);
  957. }