5 //#include <sys/time.h>
7 #define PATHSEPERATOR '/'
10 extern jmp_buf qcccompileerror;
13 // I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
16 #if (_MSC_VER >= 1400)
17 //with MSVC 8, use MS extensions
18 #define snprintf linuxlike_snprintf_vc8
19 int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
20 #define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
23 #define snprintf linuxlike_snprintf
24 int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
25 #define vsnprintf linuxlike_vsnprintf
26 int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
31 // set these before calling CheckParm
38 const unsigned int type_size[12] = {1, //void
39 sizeof(string_t)/4, //string
44 sizeof(func_t)/4,//function
45 1, //pointer (its an int index)
47 1, //fixme: how big should a variant be?
48 0, //ev_struct. variable sized.
49 0 //ev_union. variable sized.
53 ============================================================================
57 ============================================================================
59 short (*PRBigShort) (short l);
60 short (*PRLittleShort) (short l);
61 int (*PRBigLong) (int l);
62 int (*PRLittleLong) (int l);
63 float (*PRBigFloat) (float l);
64 float (*PRLittleFloat) (float l);
67 short QCC_SwapShort (short l)
77 short QCC_Short (short l)
83 int QCC_SwapLong (int l)
92 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
101 float QCC_SwapFloat (float l)
103 union {qbyte b[4]; float f;} in, out;
114 float QCC_Float (float l)
121 union {qbyte b[2]; unsigned short s;} ed;
125 PRBigShort = QCC_SwapShort;
126 PRLittleShort = QCC_Short;
127 PRBigLong = QCC_SwapLong;
128 PRLittleLong = QCC_Long;
129 PRBigFloat = QCC_SwapFloat;
130 PRLittleFloat = QCC_Float;
134 PRBigShort = QCC_Short;
135 PRLittleShort = QCC_SwapShort;
136 PRBigLong = QCC_Long;
137 PRLittleLong = QCC_SwapLong;
138 PRBigFloat = QCC_Float;
139 PRLittleFloat = QCC_SwapFloat;
152 double I_FloatTime (void)
158 gettimeofday(&tp, &tzp);
163 return tp.tv_usec/1000000.0;
166 return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
173 int QC_strncasecmp (const char *s1, const char *s2, int n)
183 return 0; // strings are equal until end point
187 if (c1 >= 'a' && c1 <= 'z')
189 if (c2 >= 'a' && c2 <= 'z')
192 return -1; // strings not equal
195 return 0; // strings are equal
203 int QC_strcasecmp (const char *s1, const char *s2)
205 return QC_strncasecmp(s1, s2, 0x7fffffff);
209 int QC_strncasecmp(const char *s1, const char *s2, int n);
210 int QC_strcasecmp (const char *s1, const char *s2)
212 return QC_strncasecmp(s1, s2, 0x7fffffff);
224 Parse a token out of a string
227 char *QCC_COM_Parse (char *data)
240 while ( (c = *data) <= ' ')
245 return NULL; // end of file;
251 if (c=='/' && data[1] == '/')
253 while (*data && *data != '\n')
259 if (c=='/' && data[1] == '*')
261 while (data[1] && (data[0] != '*' || data[1] != '/'))
268 // handle quoted strings specially
275 if (c=='\\' && *data == '\"')
276 c = *data++; //allow C-style string escapes
277 else if (c=='\\' && *data == '\\')
278 c = *data++; // \ is now a special character so it needs to be marked up using itself
279 else if (c=='\\' && *data == 'n')
280 { // and do new lines while we're at it.
289 else if (c=='\0'||c=='\n')
299 // parse single characters
300 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c==',')
308 // parse a regular word
315 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c=='\"' || c==',')
324 char *QCC_COM_Parse2 (char *data)
337 while ( (c = *data) <= ' ')
342 return NULL; // end of file;
348 if (c=='/' && data[1] == '/')
350 while (*data && *data != '\n')
356 // handle quoted strings specially
363 if (c=='\\' && *data == '\"')
364 c = *data++; //allow C-style string escapes
365 else if (c=='\\' && *data == '\\')
366 c = *data++; // \ is now a special character so it needs to be marked up using itself
367 else if (c=='\\' && *data == 'n')
368 { // and do new lines while we're at it.
372 else if (c=='\"'||c=='\0')
379 if (c >= '0' && c <= '9')
381 if (c == '0' && data[1] == 'x')
388 { //parse regular number
393 if ((c<'0'|| c>'9') && (c<'a'||c>'f') && (c<'A'||c>'F') && c != '.')
401 { //parse regular number
406 if ((c<'0'|| c>'9') && c != '.')
415 else if ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '_')
423 } while ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '_');
437 char *VARGS qcva (char *text, ...)
440 static char msg[2048];
442 va_start (argptr,text);
443 QC_vsnprintf (msg,sizeof(msg)-1, text,argptr);
452 char *QC_strupr (char *start)
464 char *QC_strlower (char *start)
478 =============================================================================
482 =============================================================================
489 For abnormal program terminations
492 void VARGS QCC_Error (int errortype, const char *error, ...)
494 extern int numsourcefiles;
498 va_start (argptr,error);
499 QC_vsnprintf (msg,sizeof(msg)-1, error,argptr);
502 printf ("\n************ ERROR ************\n%s\n", msg);
505 editbadfile(strings+s_file, pr_source_line);
510 longjmp(qcccompileerror, 1);
512 print ("Press any key\n");
523 Checks for the given parameter in the program's command line arguments
524 Returns the argument number (1 to argc-1) or 0 if not present
527 int QCC_CheckParm (char *check)
531 for (i = 1;i<myargc;i++)
533 if ( !QC_strcasecmp(check, myargv[i]) )
548 int SafeOpenWrite (char *filename)
554 handle = open(filename,O_WRONLY | O_CREAT | O_TRUNC | O_BINARY
558 QCC_Error ("Error opening %s: %s",filename,strerror(errno));
564 int SafeOpenRead (char *filename)
568 handle = open(filename,O_RDONLY | O_BINARY);
571 QCC_Error ("Error opening %s: %s",filename,strerror(errno));
577 void SafeRead (int handle, void *buffer, long count)
579 if (read (handle,buffer,count) != count)
580 QCC_Error ("File read failure");
584 void SafeWrite (int handle, void *buffer, long count)
586 if (write (handle,buffer,count) != count)
587 QCC_Error ("File write failure");
592 void *SafeMalloc (long size)
596 ptr = (void *)Hunk_Alloc (size);
599 QCC_Error ("Malloc failure for %lu bytes",size);
608 void DefaultExtension (char *path, char *extension)
612 // if path doesn't have a .EXT, append extension
613 // (extension should include the .)
615 src = path + strlen(path) - 1;
617 while (*src != PATHSEPERATOR && src != path)
620 return; // it has an extension
624 strcat (path, extension);
628 void DefaultPath (char *path, char *basepath)
632 if (path[0] == PATHSEPERATOR)
633 return; // absolute path location
635 strcpy (path,basepath);
640 void StripFilename (char *path)
644 length = strlen(path)-1;
645 while (length > 0 && path[length] != PATHSEPERATOR)
655 void ExtractFilePath (char *path, char *dest)
659 src = path + strlen(path) - 1;
662 // back up until a \ or the start
664 while (src != path && *(src-1) != PATHSEPERATOR)
667 memcpy (dest, path, src-path);
671 void ExtractFileBase (char *path, char *dest)
675 src = path + strlen(path) - 1;
678 // back up until a \ or the start
680 while (src != path && *(src-1) != PATHSEPERATOR)
683 while (*src && *src != '.')
690 void ExtractFileExtension (char *path, char *dest)
694 src = path + strlen(path) - 1;
697 // back up until a . or the start
699 while (src != path && *(src-1) != '.')
703 *dest = 0; // no extension
716 long ParseHex (char *hex)
727 if (*str >= '0' && *str <= '9')
729 else if (*str >= 'a' && *str <= 'f')
730 num += 10 + *str-'a';
731 else if (*str >= 'A' && *str <= 'F')
732 num += 10 + *str-'A';
734 QCC_Error (ERR_BADHEX, "Bad hex number: %s",hex);
742 long ParseNum (char *str)
745 return ParseHex (str+1);
746 if (str[0] == '0' && str[1] == 'x')
747 return ParseHex (str+2);
758 //buffer size and max size are different. buffer is bigger.
760 #define MAXQCCFILES 3
768 } qccfile[MAXQCCFILES];
769 int SafeOpenWrite (char *filename, int maxsize)
772 for (i = 0; i < MAXQCCFILES; i++)
774 if (!qccfile[i].buff)
776 strcpy(qccfile[i].name, filename);
777 qccfile[i].buffsize = maxsize;
778 qccfile[i].maxofs = 0;
780 // if (maxsize > 8192)
781 // qccfile[i].buffismalloc = 1;
783 // qccfile[i].buffismalloc = 0;
784 // if (qccfile[i].buffismalloc)
785 qccfile[i].buff = malloc(qccfile[i].buffsize);
787 // qccfile[i].buff = memalloc(qccfile[i].buffsize);
791 QCC_Error(ERR_TOOMANYOPENFILES, "Too many open files on file %s", filename);
795 void ResizeBuf(int hand, int newsize)
797 // int wasmal = qccfile[hand].buffismalloc;
800 if (qccfile[hand].buffsize >= newsize)
801 return; //already big enough
803 // if (newsize > 8192)
805 // qccfile[hand].buffismalloc = true;
806 nb = malloc(newsize);
810 // qccfile[hand].buffismalloc = false;
811 // nb = memalloc(newsize);
814 memcpy(nb, qccfile[hand].buff, qccfile[hand].maxofs);
816 free(qccfile[hand].buff);
818 // memfree(qccfile[hand].buff);
819 qccfile[hand].buff = nb;
820 qccfile[hand].buffsize = newsize;
822 void SafeWrite(int hand, void *buf, long count)
824 if (qccfile[hand].ofs +count >= qccfile[hand].buffsize)
825 ResizeBuf(hand, qccfile[hand].ofs + count+(64*1024));
827 memcpy(&qccfile[hand].buff[qccfile[hand].ofs], buf, count);
828 qccfile[hand].ofs+=count;
829 if (qccfile[hand].ofs > qccfile[hand].maxofs)
830 qccfile[hand].maxofs = qccfile[hand].ofs;
832 int SafeSeek(int hand, int ofs, int mode)
834 if (mode == SEEK_CUR)
835 return qccfile[hand].ofs;
838 ResizeBuf(hand, ofs+1024);
839 qccfile[hand].ofs = ofs;
840 if (qccfile[hand].ofs > qccfile[hand].maxofs)
841 qccfile[hand].maxofs = qccfile[hand].ofs;
845 void SafeClose(int hand)
847 externs->WriteFile(qccfile[hand].name, qccfile[hand].buff, qccfile[hand].maxofs);
848 // if (qccfile[hand].buffismalloc)
849 free(qccfile[hand].buff);
851 // memfree(qccfile[hand].buff);
852 qccfile[hand].buff = NULL;
855 qcc_cachedsourcefile_t *qcc_sourcefile;
856 long QCC_LoadFile (char *filename, void **bufferptr)
860 len = externs->FileSize(filename);
863 QCC_Error(ERR_COULDNTOPENFILE, "Couldn't open file %s", filename);
866 // Abort("failed to find file %s", filename);
868 mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+2);
870 ((qcc_cachedsourcefile_t*)mem)->next = qcc_sourcefile;
871 qcc_sourcefile = (qcc_cachedsourcefile_t*)mem;
872 qcc_sourcefile->size = len;
873 mem += sizeof(qcc_cachedsourcefile_t);
874 strcpy(qcc_sourcefile->filename, filename);
875 qcc_sourcefile->file = mem;
876 qcc_sourcefile->type = FT_CODE;
878 externs->ReadFile(filename, mem, len+2);
885 void QCC_AddFile (char *filename)
889 len = externs->FileSize(filename);
891 Abort("failed to find file %s", filename);
892 mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+1);
894 ((qcc_cachedsourcefile_t*)mem)->next = qcc_sourcefile;
895 qcc_sourcefile = (qcc_cachedsourcefile_t*)mem;
896 qcc_sourcefile->size = len;
897 mem += sizeof(qcc_cachedsourcefile_t);
898 strcpy(qcc_sourcefile->filename, filename);
899 qcc_sourcefile->file = mem;
900 qcc_sourcefile->type = FT_DATA;
902 externs->ReadFile(filename, mem, len+1);
905 void *FS_ReadToMem(char *filename, void *mem, int *len)
909 *len = externs->FileSize(filename);
910 mem = memalloc(*len);
912 return externs->ReadFile(filename, mem, *len);
915 void FS_CloseFromMem(void *mem)
923 void StripExtension (char *path)
927 length = strlen(path)-1;
928 while (length > 0 && path[length] != '.')
931 if (path[length] == '/')
932 return; // no extension