1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 #include "q_shared.h"
21
22 #define DEG2RAD( a ) (( a * M_PI ) / 180.0F)
23
24 vec3_t vec3_origin = {0,0,0};
25
26 //============================================================================
27
RotatePointAroundVector(vec3_t dst,const vec3_t dir,const vec3_t point,float degrees)28 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
29 {
30 float m[3][3];
31 float im[3][3];
32 float zrot[3][3];
33 float tmpmat[3][3];
34 float rot[3][3];
35
36 vec3_t vr, vup, vf;
37
38 vf[0] = dir[0];
39 vf[1] = dir[1];
40 vf[2] = dir[2];
41
42 PerpendicularVector( vr, dir );
43 CrossProduct( vr, vf, vup );
44
45 m[0][0] = vr[0];
46 m[1][0] = vr[1];
47 m[2][0] = vr[2];
48
49 m[0][1] = vup[0];
50 m[1][1] = vup[1];
51 m[2][1] = vup[2];
52
53 m[0][2] = vf[0];
54 m[1][2] = vf[1];
55 m[2][2] = vf[2];
56
57 //r1: copies a bunch of stuff we overwrite, better to do individually
58 //memcpy( im, m, sizeof( im ) );
59
60 im[0][0] = m[0][0]; //r1
61 im[0][1] = m[1][0];
62 im[0][2] = m[2][0];
63
64 im[1][0] = m[0][1];
65 im[1][1] = m[1][1]; //r1
66 im[1][2] = m[2][1];
67
68 im[2][0] = m[0][2];
69 im[2][1] = m[1][2];
70 im[2][2] = m[2][2]; //r1
71
72 //wtf?
73 //memset( zrot, 0, sizeof( zrot ) );
74 //zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
75
76 zrot[0][0] = (float)cos( DEG2RAD( degrees ) );
77 zrot[0][1] = (float)sin( DEG2RAD( degrees ) );
78 zrot[0][2] = 0;
79
80 zrot[1][0] = (float)-sin( DEG2RAD( degrees ) );
81 zrot[1][1] = (float)cos( DEG2RAD( degrees ) );
82 zrot[1][2] = 0;
83
84 zrot[2][0] = 0.0f;
85 zrot[2][1] = 0.0f;
86 zrot[2][2] = 1.0f;
87
88 R_ConcatRotations( m, zrot, tmpmat );
89 R_ConcatRotations( tmpmat, im, rot );
90
91 dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
92 dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
93 dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
94 }
95
_Q_assert(char * expression,char * function,uint32 line)96 void _Q_assert (char *expression, char *function, uint32 line)
97 {
98 Com_Printf ("Q_assert: Assertion '%s' failed on %s:%u\n", LOG_GENERAL, expression, function, line);
99 #ifndef GAME_DLL
100 Sys_DebugBreak ();
101 #endif
102 }
103
AngleVectors(vec3_t angles,vec3_t forward,vec3_t right,vec3_t up)104 void AngleVectors (vec3_t angles, vec3_t /*@out@*//*@null@*/ forward, vec3_t /*@out@*//*@null@*/right, vec3_t /*@out@*//*@null@*/up)
105 {
106 float angle;
107 static float sr, sp, sy, cr, cp, cy;
108 // static to help MS compiler fp bugs
109
110 angle = angles[YAW] * M_PI2_DIV_360;
111 sy = (float)sin(angle);
112 cy = (float)cos(angle);
113
114 angle = angles[PITCH] * M_PI2_DIV_360;
115 sp = (float)sin(angle);
116 cp = (float)cos(angle);
117
118 if (right || up)
119 {
120 angle = angles[ROLL] * M_PI2_DIV_360;
121 sr = (float)sin(angle);
122 cr = (float)cos(angle);
123 }
124
125 if (forward)
126 {
127 forward[0] = cp*cy;
128 forward[1] = cp*sy;
129 forward[2] = -sp;
130 }
131
132 if (right)
133 {
134 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
135 right[1] = (-1*sr*sp*sy+-1*cr*cy);
136 right[2] = -1*sr*cp;
137 }
138
139 if (up)
140 {
141 up[0] = (cr*sp*cy+-sr*-sy);
142 up[1] = (cr*sp*sy+-sr*cy);
143 up[2] = cr*cp;
144 }
145 }
146
147
ProjectPointOnPlane(vec3_t dst,const vec3_t p,const vec3_t normal)148 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
149 {
150 float d;
151 vec3_t n;
152 float inv_denom;
153
154 inv_denom = 1.0F / DotProduct( normal, normal );
155
156 d = DotProduct( normal, p ) * inv_denom;
157
158 n[0] = normal[0] * inv_denom;
159 n[1] = normal[1] * inv_denom;
160 n[2] = normal[2] * inv_denom;
161
162 dst[0] = p[0] - d * n[0];
163 dst[1] = p[1] - d * n[1];
164 dst[2] = p[2] - d * n[2];
165 }
166
167 /*
168 ** assumes "src" is normalized
169 */
PerpendicularVector(vec3_t dst,const vec3_t src)170 void PerpendicularVector( vec3_t dst, const vec3_t src )
171 {
172 int pos;
173 int i;
174 float minelem = 1.0F;
175 vec3_t tempvec = {0.0, 0.0, 0.0};
176
177 /*
178 ** find the smallest magnitude axially aligned vector
179 */
180 for ( pos = 0, i = 0; i < 3; i++ )
181 {
182 if ( (float)fabs( src[i] ) < minelem )
183 {
184 pos = i;
185 minelem = (float)(float)fabs( src[i] );
186 }
187 }
188 tempvec[pos] = 1.0F;
189
190 /*
191 ** project the point onto the plane defined by src
192 */
193 ProjectPointOnPlane( dst, tempvec, src );
194
195 /*
196 ** normalize the result
197 */
198 VectorNormalize( dst );
199 }
200
201
202
203 /*
204 ================
205 R_ConcatRotations
206 ================
207 */
R_ConcatRotations(float in1[3][3],float in2[3][3],float out[3][3])208 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
209 {
210 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
211 in1[0][2] * in2[2][0];
212 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
213 in1[0][2] * in2[2][1];
214 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
215 in1[0][2] * in2[2][2];
216 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
217 in1[1][2] * in2[2][0];
218 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
219 in1[1][2] * in2[2][1];
220 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
221 in1[1][2] * in2[2][2];
222 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
223 in1[2][2] * in2[2][0];
224 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
225 in1[2][2] * in2[2][1];
226 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
227 in1[2][2] * in2[2][2];
228 }
229
230
231 /*
232 ================
233 R_ConcatTransforms
234 ================
235 */
R_ConcatTransforms(float in1[3][4],float in2[3][4],float out[3][4])236 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
237 {
238 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
239 in1[0][2] * in2[2][0];
240 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
241 in1[0][2] * in2[2][1];
242 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
243 in1[0][2] * in2[2][2];
244 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
245 in1[0][2] * in2[2][3] + in1[0][3];
246 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
247 in1[1][2] * in2[2][0];
248 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
249 in1[1][2] * in2[2][1];
250 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
251 in1[1][2] * in2[2][2];
252 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
253 in1[1][2] * in2[2][3] + in1[1][3];
254 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
255 in1[2][2] * in2[2][0];
256 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
257 in1[2][2] * in2[2][1];
258 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
259 in1[2][2] * in2[2][2];
260 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
261 in1[2][2] * in2[2][3] + in1[2][3];
262 }
263
264
265 //============================================================================
266
267 //int sse2_enabled = 0;
268
269 #if defined _M_IX86 && !defined C_ONLY && !defined linux && !defined SSE2
270
271
272 /*__declspec( naked ) void __cdecl Q_ftol2( float f, int *out )
273 {
274 __asm fld dword ptr [esp+4]
275 __asm fistp dword ptr [esp+8]
276 __asm ret
277 }*/
278
Q_ftol(float f)279 __declspec( naked ) int EXPORT Q_ftol( float f )
280 {
281 __asm
282 {
283 fld dword ptr [esp+4]
284 push eax
285 fistp dword ptr [esp]
286 pop eax
287 ret
288 }
289 }
290
291 /*__declspec( naked ) void __cdecl Q_ftolsse( float f, int *out )
292 {
293 __asm movd xmm0, [esp+4]
294 __asm cvttss2si eax, xmm0
295 __asm mov [esp+8], eax
296 __asm ret
297 }
298
299 __declspec( naked ) void __cdecl Q_ftol( float f, int *out )
300 {
301 __asm cmp sse2_enabled, 0
302 __asm jz nonsse
303 __asm call Q_ftolsse
304 __asm ret
305 nonsse:
306 __asm call Q_ftol86
307 __asm ret
308 }
309
310 __declspec (naked) void __cdecl Q_sseinit (void)
311 {
312 __asm mov eax, 1
313 __asm cpuid
314 __asm test edx, 4000000h
315 __asm jz nosse
316 __asm mov sse2_enabled, 1
317 nosse:
318 __asm ret
319 }*/
320
Q_fastfloats(float * f,int * outptr)321 __declspec (naked) void EXPORT Q_fastfloats (float *f, int *outptr)
322 {
323 /*__asm cmp sse2_enabled, 0
324 __asm jz nonsse
325 __asm mov eax, [esp+4]
326 __asm movups xmm1, [eax]
327 __asm cvttps2dq xmm0, xmm1
328 __asm mov eax, [esp+8]
329 __asm movdqu [eax], xmm0
330 __asm ret
331 nonsse:*/
332 __asm mov eax, [esp+8]
333 __asm mov ebx, [esp+4]
334
335 __asm fld dword ptr [ebx]
336 __asm fistp dword ptr [eax]
337 __asm fld dword ptr [ebx+4]
338 __asm fistp dword ptr [eax+4]
339 __asm fld dword ptr [ebx+8]
340 __asm fistp dword ptr [eax+8]
341 __asm ret
342 }
343
344 #else
345
Q_ftol(float f)346 int EXPORT Q_ftol( float f )
347 {
348 return (int)f;
349 }
350
Q_fastfloats(float * f,int * outptr)351 void EXPORT Q_fastfloats (float *f, int *outptr)
352 {
353 outptr[0] = (int)f[0];
354 outptr[1] = (int)f[1];
355 outptr[2] = (int)f[2];
356 }
357
358 /*void Q_ftol2 (float f, int *out)
359 {
360 *out = (int)f;
361 }*/
362
363 #endif
364
365 /*
366 ===============
367 LerpAngle
368
369 ===============
370 */
LerpAngle(float a2,float a1,float frac)371 float LerpAngle (float a2, float a1, float frac)
372 {
373 if (a1 - a2 > 180)
374 a1 -= 360;
375 if (a1 - a2 < -180)
376 a1 += 360;
377 return a2 + frac * (a1 - a2);
378 }
379
380
anglemod(float a)381 float anglemod(float a)
382 {
383 #if 0
384 if (a >= 0)
385 a -= 360*(int)(a/360);
386 else
387 a += 360*( 1 + (int)(-a/360) );
388 #else
389 //a = (0.0054931640625f) * ((int)(a*(182.0444444444444444444444444444444444444444444444444444444444444444f))& 65535);
390 a = (360.0f/65536.0f) * ((int)(a*(65536.0f/360.0f)) & 65535);
391 #endif
392 return a;
393 }
394
395 //int i;
396 //vec3_t corners[2];
397
398
399 // this is the slow, general version
BoxOnPlaneSide2(vec3_t emins,vec3_t emaxs,struct cplane_s * p)400 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
401 {
402 int i;
403 float dist1, dist2;
404 int sides;
405 vec3_t corners[2];
406
407 for (i=0 ; i<3 ; i++)
408 {
409 if (FLOAT_LT_ZERO(p->normal[i]))
410 {
411 corners[0][i] = emins[i];
412 corners[1][i] = emaxs[i];
413 }
414 else
415 {
416 corners[1][i] = emins[i];
417 corners[0][i] = emaxs[i];
418 }
419 }
420 dist1 = DotProduct (p->normal, corners[0]) - p->dist;
421 dist2 = DotProduct (p->normal, corners[1]) - p->dist;
422 sides = 0;
423 if (FLOAT_GE_ZERO(dist1))
424 sides = 1;
425 if (FLOAT_LT_ZERO(dist2))
426 sides |= 2;
427
428 return sides;
429 }
430
431 /*
432 ==================
433 BoxOnPlaneSide
434
435 Returns 1, 2, or 1 + 2
436 ==================
437 */
438 #if !id386 || defined __linux__ || defined __FreeBSD__
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)439 int EXPORT BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
440 {
441 float dist1, dist2;
442 int sides;
443
444 // fast axial cases
445 //r1: these never seem to hit?
446 /*if (p->type < 3)
447 {
448 Sys_DebugBreak ();
449 if (p->dist <= emins[p->type])
450 return 1;
451 if (p->dist >= emaxs[p->type])
452 return 2;
453 return 3;
454 }*/
455
456 // general case
457 switch (p->signbits)
458 {
459 case 0:
460 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
461 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
462 break;
463 case 1:
464 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
465 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
466 break;
467 case 2:
468 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
469 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
470 break;
471 case 3:
472 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
473 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
474 break;
475 case 4:
476 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
477 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
478 break;
479 case 5:
480 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
481 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
482 break;
483 case 6:
484 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
485 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
486 break;
487 case 7:
488 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
489 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
490 break;
491 default:
492 dist1 = dist2 = 0; // shut up compiler
493 break;
494 }
495
496 sides = 0;
497 if (dist1 >= p->dist)
498 sides = 1;
499 if (dist2 < p->dist)
500 sides |= 2;
501
502 return sides;
503 }
504 #else
505 //#pragma warning( disable: 4035 )
506
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)507 __declspec( naked ) int __cdecl BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
508 {
509 //static int bops_initialized;
510 static int Ljmptab[8];
511
512 __asm
513 {
514 push esi
515 push ebx
516
517 lea eax, Ljmptab
518
519 cmp dword ptr [eax], 0
520 je short notinitialized
521 //mov bops_initialized, 1
522
523 initialized:
524
525 mov ecx,ds:dword ptr[8+4+esp]
526 mov ebx,ds:dword ptr[8+8+esp]
527 mov edx,ds:dword ptr[8+12+esp]
528 ;xor eax,eax
529 ;mov al,ds:byte ptr[17+edx]
530 movzx esi, ds:byte ptr[17+edx]
531 ;r1 - removed, Lerror will crash and so will illegal access, this should
532 ;never happen anyway and just causes a branch
533 ;cmp al,8
534 ;jge Lerror
535 fld ds:dword ptr[0+edx]
536 fld st(0)
537 jmp dword ptr[eax+esi*4]
538 Lcase0:
539 fmul ds:dword ptr[ebx]
540 fld ds:dword ptr[0+4+edx]
541 fxch st(2)
542 fmul ds:dword ptr[ecx]
543 fxch st(2)
544 fld st(0)
545 fmul ds:dword ptr[4+ebx]
546 fld ds:dword ptr[0+8+edx]
547 fxch st(2)
548 fmul ds:dword ptr[4+ecx]
549 fxch st(2)
550 fld st(0)
551 fmul ds:dword ptr[8+ebx]
552 fxch st(5)
553 faddp st(3),st(0)
554 fmul ds:dword ptr[8+ecx]
555 fxch st(1)
556 faddp st(3),st(0)
557 fxch st(3)
558 faddp st(2),st(0)
559 jmp short LSetSides
560 Lcase1:
561 fmul ds:dword ptr[ecx]
562 fld ds:dword ptr[0+4+edx]
563 fxch st(2)
564 fmul ds:dword ptr[ebx]
565 fxch st(2)
566 fld st(0)
567 fmul ds:dword ptr[4+ebx]
568 fld ds:dword ptr[0+8+edx]
569 fxch st(2)
570 fmul ds:dword ptr[4+ecx]
571 fxch st(2)
572 fld st(0)
573 fmul ds:dword ptr[8+ebx]
574 fxch st(5)
575 faddp st(3),st(0)
576 fmul ds:dword ptr[8+ecx]
577 fxch st(1)
578 faddp st(3),st(0)
579 fxch st(3)
580 faddp st(2),st(0)
581 jmp short LSetSides
582 Lcase2:
583 fmul ds:dword ptr[ebx]
584 fld ds:dword ptr[0+4+edx]
585 fxch st(2)
586 fmul ds:dword ptr[ecx]
587 fxch st(2)
588 fld st(0)
589 fmul ds:dword ptr[4+ecx]
590 fld ds:dword ptr[0+8+edx]
591 fxch st(2)
592 fmul ds:dword ptr[4+ebx]
593 fxch st(2)
594 fld st(0)
595 fmul ds:dword ptr[8+ebx]
596 fxch st(5)
597 faddp st(3),st(0)
598 fmul ds:dword ptr[8+ecx]
599 fxch st(1)
600 faddp st(3),st(0)
601 fxch st(3)
602 faddp st(2),st(0)
603 jmp short LSetSides
604 Lcase3:
605 fmul ds:dword ptr[ecx]
606 fld ds:dword ptr[0+4+edx]
607 fxch st(2)
608 fmul ds:dword ptr[ebx]
609 fxch st(2)
610 fld st(0)
611 fmul ds:dword ptr[4+ecx]
612 fld ds:dword ptr[0+8+edx]
613 fxch st(2)
614 fmul ds:dword ptr[4+ebx]
615 fxch st(2)
616 fld st(0)
617 fmul ds:dword ptr[8+ebx]
618 fxch st(5)
619 faddp st(3),st(0)
620 fmul ds:dword ptr[8+ecx]
621 fxch st(1)
622 faddp st(3),st(0)
623 fxch st(3)
624 faddp st(2),st(0)
625 jmp short LSetSides
626 Lcase4:
627 fmul ds:dword ptr[ebx]
628 fld ds:dword ptr[0+4+edx]
629 fxch st(2)
630 fmul ds:dword ptr[ecx]
631 fxch st(2)
632 fld st(0)
633 fmul ds:dword ptr[4+ebx]
634 fld ds:dword ptr[0+8+edx]
635 fxch st(2)
636 fmul ds:dword ptr[4+ecx]
637 fxch st(2)
638 fld st(0)
639 fmul ds:dword ptr[8+ecx]
640 fxch st(5)
641 faddp st(3),st(0)
642 fmul ds:dword ptr[8+ebx]
643 fxch st(1)
644 faddp st(3),st(0)
645 fxch st(3)
646 faddp st(2),st(0)
647 jmp short LSetSides
648 Lcase5:
649 fmul ds:dword ptr[ecx]
650 fld ds:dword ptr[0+4+edx]
651 fxch st(2)
652 fmul ds:dword ptr[ebx]
653 fxch st(2)
654 fld st(0)
655 fmul ds:dword ptr[4+ebx]
656 fld ds:dword ptr[0+8+edx]
657 fxch st(2)
658 fmul ds:dword ptr[4+ecx]
659 fxch st(2)
660 fld st(0)
661 fmul ds:dword ptr[8+ecx]
662 fxch st(5)
663 faddp st(3),st(0)
664 fmul ds:dword ptr[8+ebx]
665 fxch st(1)
666 faddp st(3),st(0)
667 fxch st(3)
668 faddp st(2),st(0)
669 jmp short LSetSides
670 Lcase6:
671 fmul ds:dword ptr[ebx]
672 fld ds:dword ptr[0+4+edx]
673 fxch st(2)
674 fmul ds:dword ptr[ecx]
675 fxch st(2)
676 fld st(0)
677 fmul ds:dword ptr[4+ecx]
678 fld ds:dword ptr[0+8+edx]
679 fxch st(2)
680 fmul ds:dword ptr[4+ebx]
681 fxch st(2)
682 fld st(0)
683 fmul ds:dword ptr[8+ecx]
684 fxch st(5)
685 faddp st(3),st(0)
686 fmul ds:dword ptr[8+ebx]
687 fxch st(1)
688 faddp st(3),st(0)
689 fxch st(3)
690 faddp st(2),st(0)
691 jmp short LSetSides
692 Lcase7:
693 fmul ds:dword ptr[ecx]
694 fld ds:dword ptr[0+4+edx]
695 fxch st(2)
696 fmul ds:dword ptr[ebx]
697 fxch st(2)
698 fld st(0)
699 fmul ds:dword ptr[4+ecx]
700 fld ds:dword ptr[0+8+edx]
701 fxch st(2)
702 fmul ds:dword ptr[4+ebx]
703 fxch st(2)
704 fld st(0)
705 fmul ds:dword ptr[8+ecx]
706 fxch st(5)
707 faddp st(3),st(0)
708 fmul ds:dword ptr[8+ebx]
709 fxch st(1)
710 faddp st(3),st(0)
711 fxch st(3)
712 faddp st(2),st(0)
713
714 ;padding for LSetsides
715 lea esp, [esp]
716 lea esp, [esp]
717 LSetSides:
718 faddp st(2),st(0)
719 fcomp ds:dword ptr[12+edx]
720 xor ecx,ecx
721 fnstsw ax
722 fcomp ds:dword ptr[12+edx]
723 and ah,1
724 xor ah,1
725 add cl,ah
726 fnstsw ax
727 and ah,1
728 add ah,ah
729 add cl,ah
730 pop ebx
731 pop esi
732 mov eax,ecx
733 ret
734 //Lerror:
735 // int 3
736 notinitialized:
737 mov dword ptr [eax], offset Lcase0
738 mov dword ptr [eax+4], offset Lcase1
739 mov dword ptr [eax+8], offset Lcase2
740 mov dword ptr [eax+12], offset Lcase3
741 mov dword ptr [eax+16], offset Lcase4
742 mov dword ptr [eax+20], offset Lcase5
743 mov dword ptr [eax+24], offset Lcase6
744 mov dword ptr [eax+28], offset Lcase7
745 jmp initialized
746 }
747 }
748 //#pragma warning( default: 4035 )
749 #endif
750
751 /*void ClearBounds (vec3_t mins, vec3_t maxs)
752 {
753 mins[0] = mins[1] = mins[2] = 99999;
754 maxs[0] = maxs[1] = maxs[2] = -99999;
755 }*/
756
AddPointToBounds(vec3_t v,vec3_t mins,vec3_t maxs)757 void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
758 {
759 if (v[0] < mins[0])
760 mins[0] = v[0];
761
762 if (v[0] > maxs[0])
763 maxs[0] = v[0];
764
765 if (v[1] < mins[1])
766 mins[1] = v[1];
767
768 if (v[1] > maxs[1])
769 maxs[1] = v[1];
770
771 if (v[2] < mins[2])
772 mins[2] = v[2];
773
774 if (v[2] > maxs[2])
775 maxs[2] = v[2];
776 }
777
778
779 //r1: macroified
780 /*int VectorCompare (vec3_t v1, vec3_t v2)
781 {
782 if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2])
783 return 0;
784
785 return 1;
786 }*/
787
788
VectorNormalize(vec3_t v)789 vec_t VectorNormalize (vec3_t v)
790 {
791 float length, ilength;
792
793 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
794 length = (float)sqrt (length); // FIXME
795
796 if (FLOAT_NE_ZERO(length))
797 {
798 ilength = 1/length;
799 v[0] *= ilength;
800 v[1] *= ilength;
801 v[2] *= ilength;
802 }
803
804 return length;
805
806 }
807
VectorNormalize2(vec3_t v,vec3_t out)808 vec_t VectorNormalize2 (vec3_t v, vec3_t out)
809 {
810 float length, ilength;
811
812 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
813 length = (float)sqrt (length); // FIXME
814
815 if (FLOAT_NE_ZERO(length))
816 {
817 ilength = 1/length;
818 out[0] = v[0]*ilength;
819 out[1] = v[1]*ilength;
820 out[2] = v[2]*ilength;
821 }
822
823 return length;
824 }
825
826 /*void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
827 {
828 vecc[0] = veca[0] + scale*vecb[0];
829 vecc[1] = veca[1] + scale*vecb[1];
830 vecc[2] = veca[2] + scale*vecb[2];
831 }*/
832
833
_DotProduct(vec3_t v1,vec3_t v2)834 vec_t _DotProduct (vec3_t v1, vec3_t v2)
835 {
836 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
837 }
838
_VectorSubtract(vec3_t veca,vec3_t vecb,vec3_t out)839 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
840 {
841 out[0] = veca[0]-vecb[0];
842 out[1] = veca[1]-vecb[1];
843 out[2] = veca[2]-vecb[2];
844 }
845
_VectorAdd(vec3_t veca,vec3_t vecb,vec3_t out)846 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
847 {
848 out[0] = veca[0]+vecb[0];
849 out[1] = veca[1]+vecb[1];
850 out[2] = veca[2]+vecb[2];
851 }
852
_VectorCopy(vec3_t in,vec3_t out)853 void _VectorCopy (vec3_t in, vec3_t out)
854 {
855 out[0] = in[0];
856 out[1] = in[1];
857 out[2] = in[2];
858 }
859
860 /*void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
861 {
862 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
863 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
864 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
865 }*/
866
867 double EXPORT sqrt(double x);
868
VectorLength(vec3_t v)869 vec_t VectorLength(vec3_t v)
870 {
871 float length;
872
873 length = 0;
874
875 length += v[0]*v[0];
876 length += v[1]*v[1];
877 length += v[2]*v[2];
878
879 length = (float)sqrtf (length); // FIXME
880
881 return length;
882 }
883
884 /*void VectorInverse (vec3_t v)
885 {
886 v[0] = -v[0];
887 v[1] = -v[1];
888 v[2] = -v[2];
889 }
890
891 void VectorScale (vec3_t in, vec_t scale, vec3_t out)
892 {
893 out[0] = in[0]*scale;
894 out[1] = in[1]*scale;
895 out[2] = in[2]*scale;
896 }*/
897
898
Q_log2(int val)899 int Q_log2(int val)
900 {
901 int answer=0;
902 while (val>>=1)
903 answer++;
904 return answer;
905 }
906
907
908
909 //====================================================================================
910
911 /*
912 ============
913 COM_SkipPath
914 ============
915 */
COM_SkipPath(char * pathname)916 char *COM_SkipPath (char *pathname)
917 {
918 char *last;
919
920 last = pathname;
921 while (pathname[0])
922 {
923 if (pathname[0] == '/')
924 last = pathname+1;
925 pathname++;
926 }
927 return last;
928 }
929
930 /*
931 ============
932 COM_StripExtension
933 ============
934 */
COM_StripExtension(const char * in,char * out)935 void COM_StripExtension (const char *in, char *out)
936 {
937 while (*in && *in != '.')
938 *out++ = *in++;
939 *out = 0;
940 }
941
942 /*
943 ============
944 COM_FileExtension
945 ============
946 */
COM_FileExtension(char * in)947 char *COM_FileExtension (char *in)
948 {
949 static char exten[8];
950 int i;
951
952 while (*in && *in != '.')
953 in++;
954 if (!*in)
955 return "";
956 in++;
957 for (i=0 ; i<7 && *in ; i++,in++)
958 exten[i] = *in;
959 exten[i] = 0;
960 return exten;
961 }
962
963 /*
964 ============
965 COM_FileBase
966 ============
967 */
COM_FileBase(char * in,char * out)968 void COM_FileBase (char *in, char *out)
969 {
970 char *s, *s2;
971
972 s = in + strlen(in) - 1;
973
974 while (s != in && *s != '.')
975 s--;
976
977 for (s2 = s ; s2 != in && *s2 != '/' ; s2--)
978 ;
979
980 if (s-s2 < 2)
981 out[0] = 0;
982 else
983 {
984 s--;
985 strncpy (out,s2+1, s-s2);
986 out[s-s2] = 0;
987 }
988 }
989
990 /*
991 ============
992 COM_FilePath
993
994 Returns the path up to, but not including the last /
995 ============
996 */
COM_FilePath(const char * in,char * out)997 void COM_FilePath (const char *in, char *out)
998 {
999 const char *s;
1000
1001 s = in + strlen(in) - 1;
1002
1003 while (s != in && *s != '/')
1004 s--;
1005
1006 strncpy (out, in, s-in);
1007 out[s-in] = 0;
1008 }
1009
1010
1011 /*
1012 ==================
1013 COM_DefaultExtension
1014 ==================
1015 */
COM_DefaultExtension(char * path,const char * extension)1016 void COM_DefaultExtension (char *path, const char *extension)
1017 {
1018 char *src;
1019 //
1020 // if path doesn't have a .EXT, append extension
1021 // (extension should include the .)
1022 //
1023 src = path + strlen(path) - 1;
1024
1025 while (*src != '/' && src != path)
1026 {
1027 if (*src == '.')
1028 return; // it has an extension
1029 src--;
1030 }
1031
1032 strcat (path, extension);
1033 }
1034
1035 /*
1036 ============================================================================
1037
1038 BYTE ORDER FUNCTIONS
1039
1040 ============================================================================
1041 */
1042
1043 //r1: endianness sucks. this is a waste of function calls for everything.
1044 //define Q_BIGENDIAN if you're on a mac or some other big endian system.
1045
1046 //need this for network ports
ShortSwap(int16 l)1047 int16 ShortSwap (int16 l)
1048 {
1049 byte b1,b2;
1050
1051 b1 = l&255;
1052 b2 = (l>>8)&255;
1053
1054 return (b1<<8) + b2;
1055 }
1056
LongSwap(int32 l)1057 int32 LongSwap (int32 l)
1058 {
1059 byte b1,b2,b3,b4;
1060
1061 b1 = l&255;
1062 b2 = (l>>8)&255;
1063 b3 = (l>>16)&255;
1064 b4 = (l>>24)&255;
1065
1066 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
1067 }
1068
1069 #if Q_BIGENDIAN
1070
1071 qboolean bigendien;
1072
1073 // can't just use function pointers, or dll linkage can
1074 // mess up when qcommon is included in multiple places
1075
1076 int16 (*_LittleShort) (int16 l);
1077 int32 (*_LittleLong) (int32 l);
1078 float (*_LittleFloat) (float l);
1079
LittleShort(int16 l)1080 int16 LittleShort(int16 l) {return _LittleShort(l);}
LittleLong(int32 l)1081 int32 LittleLong (int32 l) {return _LittleLong(l);}
LittleFloat(float l)1082 float LittleFloat (float l) {return _LittleFloat(l);}
1083
ShortNoSwap(int16 l)1084 int16 ShortNoSwap (int16 l)
1085 {
1086 return l;
1087 }
1088
LongNoSwap(int32 l)1089 int32 LongNoSwap (int32 l)
1090 {
1091 return l;
1092 }
1093
FloatSwap(float f)1094 float FloatSwap (float f)
1095 {
1096 union
1097 {
1098 float f;
1099 byte b[4];
1100 } dat1, dat2;
1101
1102
1103 dat1.f = f;
1104 dat2.b[0] = dat1.b[3];
1105 dat2.b[1] = dat1.b[2];
1106 dat2.b[2] = dat1.b[1];
1107 dat2.b[3] = dat1.b[0];
1108 return dat2.f;
1109 }
1110
FloatNoSwap(float f)1111 float FloatNoSwap (float f)
1112 {
1113 return f;
1114 }
1115
1116 /*
1117 ================
1118 Swap_Init
1119 ================
1120 */
Swap_Init(void)1121 void Swap_Init (void)
1122 {
1123 byte swaptest[2] = {1,0};
1124
1125 // set the byte swapping variables in a portable manner
1126 if ( *(int16 *)swaptest == 1)
1127 {
1128 bigendien = false;
1129 _LittleShort = ShortNoSwap;
1130 _LittleLong = LongNoSwap;
1131 _LittleFloat = FloatNoSwap;
1132 }
1133 else
1134 {
1135 bigendien = true;
1136 _LittleShort = ShortSwap;
1137 _LittleLong = LongSwap;
1138 _LittleFloat = FloatSwap;
1139 }
1140 }
1141 #else
Swap_Init(void)1142 void Swap_Init (void){}
1143 #endif
1144
1145 /*
1146 ============
1147 va
1148
1149 does a varargs printf into a temp buffer, so I don't need to have
1150 varargs versions of all text functions.
1151 FIXME: make this buffer size safe someday
1152 ============
1153 */
va(const char * format,...)1154 char *va(const char *format, ...)
1155 {
1156 va_list argptr;
1157
1158 static char string[2][1024];
1159 static int index;
1160
1161 index ^= 1;
1162
1163 va_start (argptr, format);
1164 vsnprintf (string[index], sizeof(string[index])-1, format, argptr);
1165 va_end (argptr);
1166
1167 return string[index];
1168 }
1169
1170
1171 char com_token[MAX_TOKEN_CHARS];
1172
1173 /*
1174 ==============
1175 COM_Parse
1176
1177 Parse a token out of a string
1178 ==============
1179 */
COM_Parse(char ** data_p)1180 const char *COM_Parse (char **data_p)
1181 {
1182 int c;
1183 int len;
1184 char *data;
1185
1186 data = *data_p;
1187 len = 0;
1188 com_token[0] = 0;
1189
1190 if (!data)
1191 {
1192 *data_p = NULL;
1193 return "";
1194 }
1195
1196 // skip whitespace
1197 skipwhite:
1198 while ( (c = *data) <= ' ')
1199 {
1200 if (c == 0)
1201 {
1202 *data_p = NULL;
1203 return "";
1204 }
1205 data++;
1206 }
1207
1208 // skip // comments
1209 if (c=='/' && data[1] == '/')
1210 {
1211 while (*data && *data != '\n')
1212 data++;
1213 goto skipwhite;
1214 }
1215
1216 // handle quoted strings specially
1217 if (c == '\"')
1218 {
1219 data++;
1220 for (;;)
1221 {
1222 c = *data++;
1223 if (c== '\"' || !c)
1224 {
1225 //bugfix from skuller
1226 goto finish;
1227 }
1228 if (len < MAX_TOKEN_CHARS)
1229 {
1230 com_token[len] = c;
1231 len++;
1232 }
1233 }
1234 }
1235
1236 // parse a regular word
1237 do
1238 {
1239 if (len < MAX_TOKEN_CHARS)
1240 {
1241 com_token[len] = c;
1242 len++;
1243 }
1244 data++;
1245 c = *data;
1246 } while (c>32);
1247
1248 finish:
1249
1250 if (len == MAX_TOKEN_CHARS)
1251 {
1252 len = 0;
1253 }
1254 com_token[len] = 0;
1255
1256 *data_p = data;
1257 return com_token;
1258 }
1259
1260
1261 /*
1262 ===============
1263 Com_PageInMemory
1264
1265 ===============
1266 */
1267 int paged_total;
1268
Com_PageInMemory(byte * buffer,int size)1269 void Com_PageInMemory (byte *buffer, int size)
1270 {
1271 int i;
1272
1273 for (i=size-1 ; i>0 ; i-=4096)
1274 paged_total += buffer[i];
1275 }
1276
1277
1278
1279 /*
1280 ============================================================================
1281
1282 LIBRARY REPLACEMENT FUNCTIONS
1283
1284 ============================================================================
1285 */
1286
1287 // FIXME: replace all Q_stricmp with Q_stricmp
1288 #if defined _WIN32 && defined _M_AMD64
Q_strncasecmp(const char * s1,const char * s2,size_t n)1289 int Q_strncasecmp (const char *s1, const char *s2, size_t n)
1290 {
1291 int c1, c2;
1292
1293 do
1294 {
1295 c1 = *s1++;
1296 c2 = *s2++;
1297
1298 if (!n--)
1299 return 0; // strings are equal until end point
1300
1301 if (c1 != c2)
1302 {
1303 if (c1 >= 'a' && c1 <= 'z')
1304 c1 -= ('a' - 'A');
1305 if (c2 >= 'a' && c2 <= 'z')
1306 c2 -= ('a' - 'A');
1307 if (c1 != c2)
1308 return -1; // strings not equal
1309 }
1310 } while (c1);
1311
1312 return 0; // strings are equal
1313 }
1314
Q_stricmp(const char * s1,const char * s2)1315 int Q_stricmp (const char *s1, const char *s2)
1316 {
1317 return Q_strncasecmp (s1, s2, 99999);
1318 }
1319 #endif
1320
1321
Com_sprintf(char * dest,int size,const char * fmt,...)1322 int Com_sprintf (char /*@out@*/*dest, int size, const char *fmt, ...)
1323 {
1324 int len;
1325 va_list argptr;
1326 char bigbuffer[0x10000];
1327
1328 va_start (argptr,fmt);
1329 len = Q_vsnprintf (bigbuffer, sizeof(bigbuffer), fmt, argptr);
1330 va_end (argptr);
1331
1332 if (len == -1 || len == size)
1333 {
1334 Com_Printf ("Com_sprintf: overflow of size %d\n", LOG_GENERAL, size);
1335 len = size-1;
1336 }
1337
1338 bigbuffer[size-1] = '\0';
1339 strcpy (dest, bigbuffer);
1340
1341 return len;
1342 }
1343
1344 /*
1345 =====================================================================
1346
1347 INFO STRINGS
1348
1349 =====================================================================
1350 */
1351
1352 /*
1353 ===============
1354 Info_ValueForKey
1355
1356 Searches the string for the given
1357 key and returns the associated value, or an empty string.
1358 ===============
1359 */
Info_ValueForKey(const char * s,const char * key)1360 char *Info_ValueForKey (const char *s, const char *key)
1361 {
1362 char pkey[512];
1363 static char value[2][512]; // use two buffers so compares
1364 // work without stomping on each other
1365 static int valueindex;
1366 char *o;
1367
1368 valueindex ^= 1;
1369 if (*s == '\\')
1370 s++;
1371 for (;;)
1372 {
1373 o = pkey;
1374 while (*s != '\\')
1375 {
1376 if (!*s)
1377 return "";
1378 *o++ = *s++;
1379 }
1380 *o = 0;
1381 s++;
1382
1383 o = value[valueindex];
1384
1385 while (*s != '\\' && *s)
1386 {
1387 if (!*s)
1388 return "";
1389 *o++ = *s++;
1390 }
1391 *o = 0;
1392
1393 if (!strcmp (key, pkey) )
1394 return value[valueindex];
1395
1396 if (!*s)
1397 return "";
1398 s++;
1399 }
1400 }
1401
Info_KeyExists(const char * s,const char * key)1402 qboolean Info_KeyExists (const char *s, const char *key)
1403 {
1404 char pkey[512];
1405 char *o;
1406
1407 if (*s == '\\')
1408 s++;
1409
1410 for (;;)
1411 {
1412 o = pkey;
1413 while (*s != '\\')
1414 {
1415 if (!*s)
1416 return false;
1417 *o++ = *s++;
1418 }
1419 *o = 0;
1420 s++;
1421
1422 while (*s != '\\' && *s)
1423 s++;
1424
1425 if (!strcmp (key, pkey) )
1426 return true;
1427
1428 if (!*s)
1429 return false;
1430 s++;
1431 }
1432 }
1433
Info_RemoveKey(char * s,const char * key)1434 void Info_RemoveKey (char *s, const char *key)
1435 {
1436 char *start;
1437 char pkey[512];
1438 char value[512];
1439 char *o;
1440
1441 if (strchr (key, '\\'))
1442 {
1443 Com_Printf ("Info_RemoveKey: Tried to remove illegal key '%s'\n", LOG_WARNING|LOG_GENERAL, key);
1444 return;
1445 }
1446
1447 for (;;)
1448 {
1449 start = s;
1450 if (*s == '\\')
1451 s++;
1452 o = pkey;
1453 while (*s != '\\')
1454 {
1455 if (!*s)
1456 return;
1457 *o++ = *s++;
1458 }
1459 *o = 0;
1460 s++;
1461
1462 o = value;
1463 while (*s != '\\' && *s)
1464 {
1465 if (!*s)
1466 return;
1467 *o++ = *s++;
1468 }
1469 *o = 0;
1470
1471 if (!strcmp (key, pkey) )
1472 {
1473 //r1: overlapping src+dst with strcpy = no
1474 //strcpy (start, s); // remove this part
1475 size_t memlen;
1476
1477 memlen = strlen(s);
1478 memmove (start, s, memlen);
1479 start[memlen] = 0;
1480 return;
1481 }
1482
1483 if (!*s)
1484 return;
1485 }
1486
1487 }
1488
1489
1490 /*
1491 ==================
1492 Info_Validate
1493
1494 Some characters are illegal in info strings because they
1495 can mess up the server's parsing
1496 ==================
1497 */
Info_Validate(const char * s)1498 qboolean Info_Validate (const char *s)
1499 {
1500 if (strchr (s, '"'))
1501 return false;
1502
1503 if (strchr (s, ';'))
1504 return false;
1505
1506 return true;
1507 }
1508
Info_CheckBytes(const char * s)1509 qboolean Info_CheckBytes (const char *s)
1510 {
1511 while (s[0])
1512 {
1513 if (s[0] < 32 || s[0] >= 127)
1514 return false;
1515 s++;
1516 }
1517
1518 return true;
1519 }
1520
Info_SetValueForKey(char * s,const char * key,const char * value)1521 void Info_SetValueForKey (char *s, const char *key, const char *value)
1522 {
1523 char newi[MAX_INFO_STRING], *v;
1524 int c;
1525
1526 if (strchr (key, '\\') || strchr (value, '\\') )
1527 {
1528 Com_Printf ("Can't use keys or values with a \\ (attempted to set key '%s')\n", LOG_GENERAL, key);
1529 return;
1530 }
1531
1532 if (strchr (key, ';') || strchr (value, ';') )
1533 {
1534 Com_Printf ("Can't use keys or values with a semicolon (attempted to set key '%s')\n", LOG_GENERAL, key);
1535 return;
1536 }
1537
1538 if (strchr (key, '"') || strchr (value, '"') )
1539 {
1540 Com_Printf ("Can't use keys or values with a \" (attempted to set key '%s')\n", LOG_GENERAL, key);
1541 return;
1542 }
1543
1544 if (strlen(key) > MAX_INFO_KEY-1 || strlen(value) > MAX_INFO_KEY-1)
1545 {
1546 Com_Printf ("Keys and values must be < 64 characters (attempted to set key '%s')\n", LOG_GENERAL, key);
1547 return;
1548 }
1549
1550 Info_RemoveKey (s, key);
1551
1552 if (!value || !value[0])
1553 return;
1554
1555 Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
1556
1557 if (strlen(newi) + strlen(s) > MAX_INFO_STRING)
1558 {
1559 Com_Printf ("Info string length exceeded while trying to set '%s'\n", LOG_GENERAL, newi);
1560 return;
1561 }
1562
1563 // only copy ascii values
1564 s += strlen(s);
1565 v = newi;
1566 while (*v)
1567 {
1568 c = *v++;
1569 c &= 127; // strip high bits
1570 if (c >= 32 && c < 127)
1571 *s++ = c;
1572 }
1573 s[0] = 0;
1574 }
1575
1576 //====================================================================
1577
1578 #ifndef _WIN32
Q_vsnprintf(char * buff,size_t len,const char * fmt,va_list va)1579 int Q_vsnprintf (char *buff, size_t len, const char *fmt, va_list va)
1580 {
1581 int ret;
1582
1583 ret = vsnprintf (buff, len, fmt, va);
1584 if (ret > -1 && ret < len)
1585 return ret;
1586
1587 return -1;
1588 }
1589
1590 /*int Q_snprintf (char *buff, size_t len, const char *fmt, ...)
1591 {
1592 int ret;
1593
1594 va_list argptr;
1595
1596 va_start (argptr, fmt);
1597 ret = Q_vsnprintf (buff, len, fmt, argptr);
1598 va_end (argptr);
1599
1600 return ret;
1601 }*/
1602
Q_strlwr(char * str)1603 void Q_strlwr (char *str)
1604 {
1605 while (*str)
1606 {
1607 if (isupper(*str))
1608 *str = tolower(*str);
1609 str++;
1610 }
1611 }
1612 #endif
1613
1614 /*
1615 Copyright (C) 1996, 1997, 1998, 1999, 2000 Florian Schintke
1616
1617 This is free software; you can redistribute it and/or modify it under
1618 the terms of the GNU General Public License as published by the Free
1619 Software Foundation; either version 2, or (at your option) any later
1620 version.
1621
1622 This is distributed in the hope that it will be useful, but WITHOUT
1623 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1624 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1625 for more details.
1626
1627 You should have received a copy of the GNU General Public License with
1628 the c2html, java2html, pas2html or perl2html source package as the
1629 file COPYING. If not, write to the Free Software Foundation, Inc.,
1630 59 Temple Place - Suite 330, Boston, MA
1631 02111-1307, USA.
1632 */
1633
1634 /* Documenttitle and purpose: */
1635 /* Implementation of the UN*X wildcards in C. So they are */
1636 /* available in a portable way and can be used whereever */
1637 /* needed. */
1638 /* */
1639 /* Version: */
1640 /* 1.2 */
1641 /* */
1642 /* Test cases: */
1643 /* Please look into the Shellscript testwildcards.main */
1644 /* */
1645 /* Author(s): */
1646 /* Florian Schintke (schintke@gmx.de) */
1647 /* */
1648 /* Tester: */
1649 /* Florian Schintke (schintke@gmx.de) */
1650 /* */
1651 /* Testing state: */
1652 /* tested with the atac tool */
1653 /* Latest test state is documented in testwildcards.report */
1654 /* The program that tested this functions is available as */
1655 /* testwildcards.c */
1656 /* */
1657 /* Dates: */
1658 /* First editing: unknown, but before 04/02/1997 */
1659 /* Last Change : 04/07/2000 */
1660 /* */
1661 /* Known Bugs: */
1662 /* */
1663
1664 int set (char **wildcard, char **test);
1665 /* Scans a set of characters and returns 0 if the set mismatches at this */
1666 /* position in the teststring and 1 if it is matching */
1667 /* wildcard is set to the closing ] and test is unmodified if mismatched */
1668 /* and otherwise the char pointer is pointing to the next character */
1669
1670 int asterisk (char **wildcard, char **test);
1671 /* scans an asterisk */
1672
wildcardfit(char * wildcard,char * test)1673 int wildcardfit (char *wildcard, char *test)
1674 {
1675 int fit = 1;
1676
1677 for (; ('\000' != *wildcard) && (1 == fit) && ('\000' != *test); wildcard++)
1678 {
1679 switch (*wildcard)
1680 {
1681 case '[':
1682 wildcard++; /* leave out the opening square bracket */
1683 fit = set (&wildcard, &test);
1684 /* we don't need to decrement the wildcard as in case */
1685 /* of asterisk because the closing ] is still there */
1686 break;
1687 case '?':
1688 test++;
1689 break;
1690 case '*':
1691 fit = asterisk (&wildcard, &test);
1692 /* the asterisk was skipped by asterisk() but the loop will */
1693 /* increment by itself. So we have to decrement */
1694 wildcard--;
1695 break;
1696 default:
1697 fit = (int) (*wildcard == *test);
1698 test++;
1699 }
1700 }
1701 while ((*wildcard == '*') && (1 == fit))
1702 /* here the teststring is empty otherwise you cannot */
1703 /* leave the previous loop */
1704 wildcard++;
1705 return (int) ((1 == fit) && ('\0' == *test) && ('\0' == *wildcard));
1706 }
1707
set(char ** wildcard,char ** test)1708 int set (char **wildcard, char **test)
1709 {
1710 int fit = 0;
1711 int negation = 0;
1712 int at_beginning = 1;
1713
1714 if ('!' == **wildcard)
1715 {
1716 negation = 1;
1717 (*wildcard)++;
1718 }
1719 while ((']' != **wildcard) || (1 == at_beginning))
1720 {
1721 if (0 == fit)
1722 {
1723 if (('-' == **wildcard)
1724 && ((*(*wildcard - 1)) < (*(*wildcard + 1)))
1725 && (']' != *(*wildcard + 1))
1726 && (0 == at_beginning))
1727 {
1728 if (((**test) >= (*(*wildcard - 1)))
1729 && ((**test) <= (*(*wildcard + 1))))
1730 {
1731 fit = 1;
1732 (*wildcard)++;
1733 }
1734 }
1735 else if ((**wildcard) == (**test))
1736 {
1737 fit = 1;
1738 }
1739 }
1740 (*wildcard)++;
1741 at_beginning = 0;
1742 }
1743 if (1 == negation)
1744 /* change from zero to one and vice versa */
1745 fit = 1 - fit;
1746 if (1 == fit)
1747 (*test)++;
1748
1749 return (fit);
1750 }
1751
asterisk(char ** wildcard,char ** test)1752 int asterisk (char **wildcard, char **test)
1753 {
1754 /* Warning: uses multiple returns */
1755 int fit = 1;
1756
1757 /* erase the leading asterisk */
1758 (*wildcard)++;
1759 while (('\000' != (**test))
1760 && (('?' == **wildcard)
1761 || ('*' == **wildcard)))
1762 {
1763 if ('?' == **wildcard)
1764 (*test)++;
1765 (*wildcard)++;
1766 }
1767 /* Now it could be that test is empty and wildcard contains */
1768 /* aterisks. Then we delete them to get a proper state */
1769 while ('*' == (**wildcard))
1770 (*wildcard)++;
1771
1772 if (('\0' == (**test)) && ('\0' != (**wildcard)))
1773 return (fit = 0);
1774 if (('\0' == (**test)) && ('\0' == (**wildcard)))
1775 return (fit = 1);
1776 else
1777 {
1778 /* Neither test nor wildcard are empty! */
1779 /* the first character of wildcard isn't in [*?] */
1780 if (0 == wildcardfit(*wildcard, (*test)))
1781 {
1782 do
1783 {
1784 (*test)++;
1785 /* skip as much characters as possible in the teststring */
1786 /* stop if a character match occurs */
1787 while (((**wildcard) != (**test))
1788 && ('[' != (**wildcard))
1789 && ('\0' != (**test)))
1790 (*test)++;
1791 }
1792 while ((('\0' != **test))?
1793 (0 == wildcardfit (*wildcard, (*test)))
1794 : (0 != (fit = 0)));
1795 }
1796 if (('\0' == **test) && ('\0' == **wildcard))
1797 fit = 1;
1798 return (fit);
1799 }
1800 }
1801