]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/mediasource/extra/fteqcc-src/qcc_cmdlib.c
Rename the compiled fteqcc to fteqcc-win32 (as that's what it is)
[voretournament/voretournament.git] / misc / mediasource / extra / fteqcc-src / qcc_cmdlib.c
1 // cmdlib.c
2
3 #include "qcc.h"
4 #include <ctype.h>
5 //#include <sys/time.h>
6
7 #define PATHSEPERATOR   '/'
8
9 #ifndef QCC
10 extern jmp_buf qcccompileerror;
11 #endif
12
13 // set these before calling CheckParm
14 int myargc;
15 char **myargv;
16
17 char    qcc_token[1024];
18 int             qcc_eof;
19
20 const unsigned int              type_size[12] = {1,     //void
21                                                 sizeof(string_t)/4,     //string
22                                                 1,      //float
23                                                 3,      //vector
24                                                 1,      //entity
25                                                 1,      //field
26                                                 sizeof(func_t)/4,//function
27                                                 1,  //pointer (its an int index)
28                                                 1,      //integer
29                                                 1,      //fixme: how big should a variant be?
30                                                 0,      //ev_struct. variable sized.
31                                                 0       //ev_union. variable sized.
32                                                 };
33
34 /*
35 ============================================================================
36
37                                         BYTE ORDER FUNCTIONS
38
39 ============================================================================
40 */
41 short   (*PRBigShort) (short l);
42 short   (*PRLittleShort) (short l);
43 int     (*PRBigLong) (int l);
44 int     (*PRLittleLong) (int l);
45 float   (*PRBigFloat) (float l);
46 float   (*PRLittleFloat) (float l);
47
48
49 short   QCC_SwapShort (short l)
50 {
51         qbyte    b1,b2;
52
53         b1 = l&255;
54         b2 = (l>>8)&255;
55
56         return (b1<<8) + b2;
57 }
58
59 short   QCC_Short (short l)
60 {
61         return l;
62 }
63
64
65 int    QCC_SwapLong (int l)
66 {
67         qbyte    b1,b2,b3,b4;
68
69         b1 = (qbyte)l;
70         b2 = (qbyte)(l>>8);
71         b3 = (qbyte)(l>>16);
72         b4 = (qbyte)(l>>24);
73
74         return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
75 }
76
77 int    QCC_Long (int l)
78 {
79         return l;
80 }
81
82
83 float   QCC_SwapFloat (float l)
84 {
85         union {qbyte b[4]; float f;} in, out;
86         
87         in.f = l;
88         out.b[0] = in.b[3];
89         out.b[1] = in.b[2];
90         out.b[2] = in.b[1];
91         out.b[3] = in.b[0];
92         
93         return out.f;
94 }
95
96 float   QCC_Float (float l)
97 {
98         return l;
99 }
100
101 void SetEndian(void)
102 {
103         union {qbyte b[2]; unsigned short s;} ed;
104         ed.s = 255;
105         if (ed.b[0] == 255)
106         {
107                 PRBigShort              = QCC_SwapShort;
108                 PRLittleShort   = QCC_Short;
109                 PRBigLong               = QCC_SwapLong;
110                 PRLittleLong    = QCC_Long;
111                 PRBigFloat              = QCC_SwapFloat;
112                 PRLittleFloat   = QCC_Float;
113         }
114         else
115         {
116                 PRBigShort              = QCC_Short;
117                 PRLittleShort   = QCC_SwapShort;
118                 PRBigLong               = QCC_Long;
119                 PRLittleLong    = QCC_SwapLong;
120                 PRBigFloat              = QCC_Float;
121                 PRLittleFloat   = QCC_SwapFloat;
122         }
123 }
124
125
126
127 #ifndef MINIMAL
128 /*
129 ================
130 I_FloatTime
131 ================
132 */
133 /*
134 double I_FloatTime (void)
135 {
136         struct timeval tp;
137         struct timezone tzp;
138         static int              secbase;
139
140         gettimeofday(&tp, &tzp);
141         
142         if (!secbase)
143         {
144                 secbase = tp.tv_sec;
145                 return tp.tv_usec/1000000.0;
146         }
147         
148         return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
149 }
150
151   */
152
153
154 #ifdef QCC
155 int QC_strncasecmp (const char *s1, const char *s2, int n)
156 {
157         int             c1, c2;
158         
159         while (1)
160         {
161                 c1 = *s1++;
162                 c2 = *s2++;
163
164                 if (!n--)
165                         return 0;               // strings are equal until end point
166                 
167                 if (c1 != c2)
168                 {
169                         if (c1 >= 'a' && c1 <= 'z')
170                                 c1 -= ('a' - 'A');
171                         if (c2 >= 'a' && c2 <= 'z')
172                                 c2 -= ('a' - 'A');
173                         if (c1 != c2)
174                                 return -1;              // strings not equal
175                 }
176                 if (!c1)
177                         return 0;               // strings are equal
178 //              s1++;
179 //              s2++;
180         }
181         
182         return -1;
183 }
184
185 int QC_strcasecmp (const char *s1, const char *s2)
186 {
187         return QC_strncasecmp(s1, s2, 0x7fffffff);
188 }
189
190 #else
191 int QC_strncasecmp(const char *s1, const char *s2, int n);
192 int QC_strcasecmp (const char *s1, const char *s2)
193 {
194         return QC_strncasecmp(s1, s2, 0x7fffffff);
195 }
196
197 #endif
198
199
200
201 #endif  //minimal
202 /*
203 ==============
204 COM_Parse
205
206 Parse a token out of a string
207 ==============
208 */
209 char *QCC_COM_Parse (char *data)
210 {
211         int             c;
212         int             len;
213         
214         len = 0;
215         qcc_token[0] = 0;
216         
217         if (!data)
218                 return NULL;
219                 
220 // skip whitespace
221 skipwhite:
222         while ( (c = *data) <= ' ')
223         {
224                 if (c == 0)
225                 {
226                         qcc_eof = true;
227                         return NULL;                    // end of file;
228                 }
229                 data++;
230         }
231         
232 // skip // comments
233         if (c=='/' && data[1] == '/')
234         {
235                 while (*data && *data != '\n')
236                         data++;
237                 goto skipwhite;
238         }
239
240         // skip /* comments
241         if (c=='/' && data[1] == '*')
242         {
243                 while (data[1] && (data[0] != '*' || data[1] != '/'))
244                         data++;
245                 data+=2;
246                 goto skipwhite;
247         }
248         
249
250 // handle quoted strings specially
251         if (c == '\"')
252         {
253                 data++;
254                 do
255                 {
256                         c = *data++;
257                         if (c=='\\' && *data == '\"')
258                                 c = *data++;    //allow C-style string escapes
259                         else if (c=='\\' && *data == '\\')
260                                 c = *data++;    // \ is now a special character so it needs to be marked up using itself
261                         else if (c=='\\' && *data == 'n')
262                         {                                       // and do new lines while we're at it.
263                                 c = '\n';
264                                 data++;
265                         }
266                         else if (c=='\"')
267                         {
268                                 qcc_token[len] = 0;
269                                 return data;
270                         }
271                         else if (c=='\0'||c=='\n')
272                         {
273                                 qcc_token[len] = 0;
274                                 return data;
275                         }
276                         qcc_token[len] = c;
277                         len++;
278                 } while (1);
279         }
280
281 // parse single characters
282         if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c==',')
283         {
284                 qcc_token[len] = c;
285                 len++;
286                 qcc_token[len] = 0;
287                 return data+1;
288         }
289
290 // parse a regular word
291         do
292         {
293                 qcc_token[len] = c;
294                 data++;
295                 len++;
296                 c = *data;
297                 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c=='\"' || c==',')
298                         break;
299         } while (c>32);
300         
301         qcc_token[len] = 0;
302         return data;
303 }
304
305 //more C tokens...
306 char *QCC_COM_Parse2 (char *data)
307 {
308         int             c;
309         int             len;
310         
311         len = 0;
312         qcc_token[0] = 0;
313         
314         if (!data)
315                 return NULL;
316                 
317 // skip whitespace
318 skipwhite:
319         while ( (c = *data) <= ' ')
320         {
321                 if (c == 0)
322                 {
323                         qcc_eof = true;
324                         return NULL;                    // end of file;
325                 }
326                 data++;
327         }
328         
329 // skip // comments
330         if (c=='/' && data[1] == '/')
331         {
332                 while (*data && *data != '\n')
333                         data++;
334                 goto skipwhite;
335         }
336         
337
338 // handle quoted strings specially
339         if (c == '\"')
340         {
341                 data++;
342                 do
343                 {
344                         c = *data++;
345                         if (c=='\\' && *data == '\"')
346                                 c = *data++;    //allow C-style string escapes
347                         else if (c=='\\' && *data == '\\')
348                                 c = *data++;    // \ is now a special character so it needs to be marked up using itself
349                         else if (c=='\\' && *data == 'n')
350                         {                                       // and do new lines while we're at it.
351                                 c = '\n';
352                                 data++;
353                         }
354                         else if (c=='\"'||c=='\0')
355                         qcc_token[len] = c;
356                         len++;
357                 } while (1);
358         }
359
360 // parse numbers
361         if (c >= '0' && c <= '9')
362         {
363                 if (c == '0' && data[1] == 'x')
364                 {       //parse hex
365                         qcc_token[0] = '0';
366                         c='x';
367                         len=1;
368                         data++;
369                         for(;;)
370                         {       //parse regular number
371                                 qcc_token[len] = c;
372                                 data++;
373                                 len++;
374                                 c = *data;
375                                 if ((c<'0'|| c>'9') && (c<'a'||c>'f') && (c<'A'||c>'F') && c != '.')
376                                         break;
377                         }
378
379                 }
380                 else
381                 {
382                         for(;;)
383                         {       //parse regular number
384                                 qcc_token[len] = c;
385                                 data++;
386                                 len++;
387                                 c = *data;
388                                 if ((c<'0'|| c>'9') && c != '.')
389                                         break;
390                         }
391                 }
392                 
393                 qcc_token[len] = 0;
394                 return data;
395         }
396 // parse words
397         else if ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '_')
398         {
399                 do
400                 {
401                         qcc_token[len] = c;
402                         data++;
403                         len++;
404                         c = *data;
405                 } while ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '_');
406                 
407                 qcc_token[len] = 0;
408                 return data;
409         }
410         else
411         {
412                 qcc_token[len] = c;
413                 len++;
414                 qcc_token[len] = 0;
415                 return data+1;
416         }
417 }
418
419 char *VARGS qcva (char *text, ...)
420 {
421         va_list argptr;
422         static char msg[2048];  
423
424         va_start (argptr,text);
425         QC_vsnprintf (msg,sizeof(msg)-1, text,argptr);
426         va_end (argptr);
427
428         return msg;
429 }
430
431
432 #ifndef MINIMAL
433
434 char *QC_strupr (char *start)
435 {
436         char    *in;
437         in = start;
438         while (*in)
439         {
440                 *in = toupper(*in);
441                 in++;
442         }
443         return start;
444 }
445
446 char *QC_strlower (char *start)
447 {
448         char    *in;
449         in = start;
450         while (*in)
451         {
452                 *in = tolower(*in);
453                 in++;
454         }
455         return start;
456 }
457
458
459 /*
460 =============================================================================
461
462                                                 MISC FUNCTIONS
463
464 =============================================================================
465 */
466
467 /*
468 =================
469 Error
470
471 For abnormal program terminations
472 =================
473 */
474 void VARGS QCC_Error (int errortype, const char *error, ...)
475 {
476         extern int numsourcefiles;
477         va_list argptr;
478         char msg[2048]; 
479
480         va_start (argptr,error);
481         QC_vsnprintf (msg,sizeof(msg)-1, error,argptr);
482         va_end (argptr);
483
484         printf ("\n************ ERROR ************\n%s\n", msg);
485
486
487         editbadfile(strings+s_file, pr_source_line);
488
489         numsourcefiles = 0;
490
491 #ifndef QCC
492         longjmp(qcccompileerror, 1);    
493 #else
494         print ("Press any key\n");
495         getch();
496 #endif
497         exit (1);
498 }
499
500
501 /*
502 =================
503 CheckParm
504
505 Checks for the given parameter in the program's command line arguments
506 Returns the argument number (1 to argc-1) or 0 if not present
507 =================
508 */
509 int QCC_CheckParm (char *check)
510 {
511         int             i;
512
513         for (i = 1;i<myargc;i++)
514         {
515                 if ( !QC_strcasecmp(check, myargv[i]) )
516                         return i;
517         }
518
519         return 0;
520 }
521
522 /*
523
524
525 #ifndef O_BINARY
526 #define O_BINARY 0
527 #endif
528
529 #ifdef QCC
530 int SafeOpenWrite (char *filename)
531 {
532         int     handle;
533
534         umask (0);
535         
536         handle = open(filename,O_WRONLY | O_CREAT | O_TRUNC | O_BINARY
537         , 0666);
538
539         if (handle == -1)
540                 QCC_Error ("Error opening %s: %s",filename,strerror(errno));
541
542         return handle;
543 }
544 #endif
545
546 int SafeOpenRead (char *filename)
547 {
548         int     handle;
549
550         handle = open(filename,O_RDONLY | O_BINARY);
551
552         if (handle == -1)
553                 QCC_Error ("Error opening %s: %s",filename,strerror(errno));
554
555         return handle;
556 }
557
558
559 void SafeRead (int handle, void *buffer, long count)
560 {
561         if (read (handle,buffer,count) != count)
562                 QCC_Error ("File read failure");
563 }
564
565 #ifdef QCC
566 void SafeWrite (int handle, void *buffer, long count)
567 {
568         if (write (handle,buffer,count) != count)
569                 QCC_Error ("File write failure");
570 }
571 #endif
572
573
574 void *SafeMalloc (long size)
575 {
576         void *ptr;
577
578         ptr = (void *)Hunk_Alloc (size);
579
580         if (!ptr)
581                 QCC_Error ("Malloc failure for %lu bytes",size);
582
583         return ptr;
584 }
585
586 */
587
588
589
590 void DefaultExtension (char *path, char *extension)
591 {
592         char    *src;
593 //
594 // if path doesn't have a .EXT, append extension
595 // (extension should include the .)
596 //
597         src = path + strlen(path) - 1;
598
599         while (*src != PATHSEPERATOR && src != path)
600         {
601                 if (*src == '.')
602                         return;                 // it has an extension
603                 src--;
604         }
605
606         strcat (path, extension);
607 }
608
609
610 void DefaultPath (char *path, char *basepath)
611 {
612         char    temp[128];
613
614         if (path[0] == PATHSEPERATOR)
615                 return;                   // absolute path location
616         strcpy (temp,path);
617         strcpy (path,basepath);
618         strcat (path,temp);
619 }
620
621
622 void    StripFilename (char *path)
623 {
624         int             length;
625
626         length = strlen(path)-1;
627         while (length > 0 && path[length] != PATHSEPERATOR)
628                 length--;
629         path[length] = 0;
630 }
631
632 /*
633 ====================
634 Extract file parts
635 ====================
636 */
637 void ExtractFilePath (char *path, char *dest)
638 {
639         char    *src;
640
641         src = path + strlen(path) - 1;
642
643 //
644 // back up until a \ or the start
645 //
646         while (src != path && *(src-1) != PATHSEPERATOR)
647                 src--;
648
649         memcpy (dest, path, src-path);
650         dest[src-path] = 0;
651 }
652
653 void ExtractFileBase (char *path, char *dest)
654 {
655         char    *src;
656
657         src = path + strlen(path) - 1;
658
659 //
660 // back up until a \ or the start
661 //
662         while (src != path && *(src-1) != PATHSEPERATOR)
663                 src--;
664
665         while (*src && *src != '.')
666         {
667                 *dest++ = *src++;
668         }
669         *dest = 0;
670 }
671
672 void ExtractFileExtension (char *path, char *dest)
673 {
674         char    *src;
675
676         src = path + strlen(path) - 1;
677
678 //
679 // back up until a . or the start
680 //
681         while (src != path && *(src-1) != '.')
682                 src--;
683         if (src == path)
684         {
685                 *dest = 0;      // no extension
686                 return;
687         }
688
689         strcpy (dest,src);
690 }
691
692
693 /*
694 ==============
695 ParseNum / ParseHex
696 ==============
697 */
698 long ParseHex (char *hex)
699 {
700         char    *str;
701         long    num;
702
703         num = 0;
704         str = hex;
705
706         while (*str)
707         {
708                 num <<= 4;
709                 if (*str >= '0' && *str <= '9')
710                         num += *str-'0';
711                 else if (*str >= 'a' && *str <= 'f')
712                         num += 10 + *str-'a';
713                 else if (*str >= 'A' && *str <= 'F')
714                         num += 10 + *str-'A';
715                 else
716                         QCC_Error (ERR_BADHEX, "Bad hex number: %s",hex);
717                 str++;
718         }
719
720         return num;
721 }
722
723
724 long ParseNum (char *str)
725 {
726         if (str[0] == '$')
727                 return ParseHex (str+1);
728         if (str[0] == '0' && str[1] == 'x')
729                 return ParseHex (str+2);
730         return atol (str);
731 }
732
733
734
735
736
737
738
739
740 //buffer size and max size are different. buffer is bigger.
741
742 #define MAXQCCFILES 3
743 struct {
744         char name[64];
745         char *buff;
746 //      int buffismalloc;
747         int buffsize;
748         int ofs;
749         int maxofs;
750 } qccfile[MAXQCCFILES];
751 int SafeOpenWrite (char *filename, int maxsize)
752 {
753         int i;
754         for (i = 0; i < MAXQCCFILES; i++)
755         {
756                 if (!qccfile[i].buff)
757                 {
758                         strcpy(qccfile[i].name, filename);
759                         qccfile[i].buffsize = maxsize;
760                         qccfile[i].maxofs = 0;
761                         qccfile[i].ofs = 0;
762 //                      if (maxsize > 8192)
763 //                              qccfile[i].buffismalloc = 1;
764 //                      else
765 //                              qccfile[i].buffismalloc = 0;
766 //                      if (qccfile[i].buffismalloc)
767                                 qccfile[i].buff = malloc(qccfile[i].buffsize);
768 //                      else
769 //                              qccfile[i].buff = memalloc(qccfile[i].buffsize);
770                         return i;
771                 }
772         }
773         QCC_Error(ERR_TOOMANYOPENFILES, "Too many open files on file %s", filename);
774         return -1;
775 }
776
777 void ResizeBuf(int hand, int newsize)
778 {
779 //      int wasmal = qccfile[hand].buffismalloc;        
780         char *nb;
781
782         if (qccfile[hand].buffsize >= newsize)
783                 return; //already big enough
784
785 //      if (newsize > 8192)
786 //      {
787 //              qccfile[hand].buffismalloc = true;
788                 nb = malloc(newsize);
789 //      }
790 //      else
791 //      {
792 //              qccfile[hand].buffismalloc = false;
793 //              nb = memalloc(newsize);
794 //      }
795         
796         memcpy(nb, qccfile[hand].buff, qccfile[hand].maxofs);
797 //      if (wasmal)
798                 free(qccfile[hand].buff);
799 //      else
800 //              memfree(qccfile[hand].buff);
801         qccfile[hand].buff = nb;
802         qccfile[hand].buffsize = newsize;
803 }
804 void SafeWrite(int hand, void *buf, long count)
805 {
806         if (qccfile[hand].ofs +count >= qccfile[hand].buffsize)
807                 ResizeBuf(hand, qccfile[hand].ofs + count+(64*1024));
808
809         memcpy(&qccfile[hand].buff[qccfile[hand].ofs], buf, count);
810         qccfile[hand].ofs+=count;
811         if (qccfile[hand].ofs > qccfile[hand].maxofs)
812                 qccfile[hand].maxofs = qccfile[hand].ofs;
813 }
814 int SafeSeek(int hand, int ofs, int mode)
815 {
816         if (mode == SEEK_CUR)
817                 return qccfile[hand].ofs;
818         else
819         {
820                 ResizeBuf(hand, ofs+1024);
821                 qccfile[hand].ofs = ofs;
822                 if (qccfile[hand].ofs > qccfile[hand].maxofs)
823                         qccfile[hand].maxofs = qccfile[hand].ofs;
824                 return 0;
825         }
826 }
827 void SafeClose(int hand)
828 {
829         externs->WriteFile(qccfile[hand].name, qccfile[hand].buff, qccfile[hand].maxofs);       
830 //      if (qccfile[hand].buffismalloc)
831                 free(qccfile[hand].buff);
832 //      else
833 //              memfree(qccfile[hand].buff);
834         qccfile[hand].buff = NULL;
835 }
836
837 qcc_cachedsourcefile_t *qcc_sourcefile;
838 long    QCC_LoadFile (char *filename, void **bufferptr)
839 {
840         char *mem;
841         int len;
842         len = externs->FileSize(filename);
843         if (len < 0)
844         {
845                 QCC_Error(ERR_COULDNTOPENFILE, "Couldn't open file %s", filename);
846 //              if (!Abort)
847                         return -1;
848 //              Abort("failed to find file %s", filename);
849         }
850         mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+2);     
851
852         ((qcc_cachedsourcefile_t*)mem)->next = qcc_sourcefile;
853         qcc_sourcefile = (qcc_cachedsourcefile_t*)mem;
854         qcc_sourcefile->size = len;     
855         mem += sizeof(qcc_cachedsourcefile_t);  
856         strcpy(qcc_sourcefile->filename, filename);
857         qcc_sourcefile->file = mem;
858         qcc_sourcefile->type = FT_CODE;
859         
860         externs->ReadFile(filename, mem, len+2);
861         mem[len] = '\n';
862         mem[len+1] = '\0';
863         *bufferptr=mem;
864         
865         return len;
866 }
867 void    QCC_AddFile (char *filename)
868 {
869         char *mem;
870         int len;
871         len = externs->FileSize(filename);
872         if (len < 0)
873                 Abort("failed to find file %s", filename);
874         mem = qccHunkAlloc(sizeof(qcc_cachedsourcefile_t) + len+1);     
875
876         ((qcc_cachedsourcefile_t*)mem)->next = qcc_sourcefile;
877         qcc_sourcefile = (qcc_cachedsourcefile_t*)mem;
878         qcc_sourcefile->size = len;     
879         mem += sizeof(qcc_cachedsourcefile_t);  
880         strcpy(qcc_sourcefile->filename, filename);
881         qcc_sourcefile->file = mem;
882         qcc_sourcefile->type = FT_DATA;
883
884         externs->ReadFile(filename, mem, len+1);
885         mem[len] = '\0';
886 }
887 void *FS_ReadToMem(char *filename, void *mem, int *len)
888 {
889         if (!mem)
890         {
891                 *len = externs->FileSize(filename);
892                 mem = memalloc(*len);
893         }
894         return externs->ReadFile(filename, mem, *len);
895 }
896
897 void FS_CloseFromMem(void *mem)
898 {
899         memfree(mem);
900 }
901
902
903 #endif
904
905 void    StripExtension (char *path)
906 {
907         int             length;
908
909         length = strlen(path)-1;
910         while (length > 0 && path[length] != '.')
911         {
912                 length--;
913                 if (path[length] == '/')
914                         return;         // no extension
915         }
916         if (length)
917                 path[length] = 0;
918 }