cmdlib.c 20 KB

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