home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 December / PCWKCD1296.iso / sharewar / quake106 / utils / common / cmdlib.c < prev    next >
C/C++ Source or Header  |  1996-09-12  |  14KB  |  868 lines

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