1 string wordwrap_buffer;
3 void wordwrap_buffer_put(string s)
5 wordwrap_buffer = strcat(wordwrap_buffer, s);
8 string wordwrap(string s, float l)
12 wordwrap_cb(s, l, wordwrap_buffer_put);
20 void wordwrap_buffer_sprint(string s)
22 wordwrap_buffer = strcat(wordwrap_buffer, s);
25 sprint(self, wordwrap_buffer);
30 void wordwrap_sprint(string s, float l)
33 wordwrap_cb(s, l, wordwrap_buffer_sprint);
34 if(wordwrap_buffer != "")
35 sprint(self, strcat(wordwrap_buffer, "\n"));
42 string unescape(string in)
47 // but it doesn't seem to be necessary in my tests at least
52 for(i = 0; i < len; ++i)
54 s = substring(in, i, 1);
57 s = substring(in, i+1, 1);
59 str = strcat(str, "\n");
61 str = strcat(str, "\\");
63 str = strcat(str, substring(in, i, 2));
73 void wordwrap_cb(string s, float l, void(string) callback)
76 local float lleft, i, j, wlen;
80 for (i = 0;i < strlen(s);++i)
82 if (substring(s, i, 2) == "\\n")
88 else if (substring(s, i, 1) == "\n")
93 else if (substring(s, i, 1) == " ")
103 for (j = i+1;j < strlen(s);++j)
104 // ^^ this skips over the first character of a word, which
105 // is ALWAYS part of the word
106 // this is safe since if i+1 == strlen(s), i will become
107 // strlen(s)-1 at the end of this block and the function
108 // will terminate. A space can't be the first character we
109 // read here, and neither can a \n be the start, since these
110 // two cases have been handled above.
112 c = substring(s, j, 1);
119 // we need to keep this tempstring alive even if substring is
120 // called repeatedly, so call strcat even though we're not
130 callback(substring(s, i, wlen));
131 lleft = lleft - wlen;
138 float dist_point_line(vector p, vector l0, vector ldir)
140 ldir = normalize(ldir);
142 // remove the component in line direction
143 p = p - (p * ldir) * ldir;
145 // vlen of the remaining vector
149 void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
178 float median(float a, float b, float c)
181 return bound(a, b, c);
182 return bound(c, b, a);
185 // converts a number to a string with the indicated number of decimals
186 // works for up to 10 decimals!
187 string ftos_decimals(float number, float decimals)
193 // if negative, cut off the sign first
195 return strcat("-", ftos_decimals(-number, decimals));
196 // it now is always positive!
199 number = floor(number * pow(10, decimals) + 0.5);
202 result = ftos(number);
203 len = strlen(result);
204 // does it have a decimal point (should not happen)? If there is one, it is always at len-7)
205 // if ftos had messed it up, which should never happen: "34278.000000"
207 if(substring(result, len - 7, 1) == ".")
209 dprint("ftos(integer) has comma? Can't be. Affected result: ", result, "\n");
210 result = substring(result, 0, len - 7);
215 return result; // don't insert a point for zero decimals
216 // is it too short? If yes, insert leading zeroes
219 result = strcat(substring("0000000000", 0, decimals - len + 1), result);
222 // and now... INSERT THE POINT!
223 tmp = substring(result, len - decimals, decimals);
224 result = strcat(substring(result, 0, len - decimals), ".", tmp);
229 vector colormapPaletteColor(float c, float isPants)
233 case 0: return '0.800000 0.800000 0.800000';
234 case 1: return '0.600000 0.400000 0.000000';
235 case 2: return '0.000000 1.000000 0.501961';
236 case 3: return '0.000000 1.000000 0.000000';
237 case 4: return '1.000000 0.000000 0.000000';
238 case 5: return '0.000000 0.501961 1.000000';
239 case 6: return '0.000000 1.000000 1.000000';
240 case 7: return '0.501961 1.000000 0.000000';
241 case 8: return '0.501961 0.000000 1.000000';
242 case 9: return '1.000000 0.000000 1.000000';
243 case 10: return '1.000000 0.000000 0.501961';
244 case 11: return '0.600000 0.600000 0.600000';
245 case 12: return '1.000000 1.000000 0.000000';
246 case 13: return '0.000000 0.000000 1.000000';
247 case 14: return '1.000000 0.501961 0.000000';
251 '1 0 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 0.0000000000))
252 + '0 1 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 2.0943951024))
253 + '0 0 1' * (0.502 + 0.498 * sin(time / 2.7182818285 + 4.1887902048));
256 '1 0 0' * (0.502 + 0.498 * sin(time / 3.1415926536 + 5.2359877560))
257 + '0 1 0' * (0.502 + 0.498 * sin(time / 3.1415926536 + 3.1415926536))
258 + '0 0 1' * (0.502 + 0.498 * sin(time / 3.1415926536 + 1.0471975512));
259 default: return '0.000 0.000 0.000';
263 // unzone the string, and return it as tempstring. Safe to be called on string_null
264 string fstrunzone(string s)
274 // Databases (hash tables)
275 #define DB_BUCKETS 8192
276 void db_save(float db, string pFilename)
279 fh = fopen(pFilename, FILE_WRITE);
282 print(strcat("^1Can't write DB to ", pFilename));
286 fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
287 for(i = 0; i < n; ++i)
288 fputs(fh, strcat(bufstr_get(db, i), "\n"));
297 float db_load(string pFilename)
299 float db, fh, i, j, n;
304 fh = fopen(pFilename, FILE_READ);
307 if(stof(fgets(fh)) == DB_BUCKETS)
310 while((l = fgets(fh)))
313 bufstr_set(db, i, l);
319 // different count of buckets?
320 // need to reorganize the database then (SLOW)
321 while((l = fgets(fh)))
323 n = tokenizebyseparator(l, "\\");
324 for(j = 2; j < n; j += 2)
325 db_put(db, argv(j-1), uri_unescape(argv(j)));
332 void db_dump(float db, string pFilename)
334 float fh, i, j, n, m;
335 fh = fopen(pFilename, FILE_WRITE);
337 error(strcat("Can't dump DB to ", pFilename));
340 for(i = 0; i < n; ++i)
342 m = tokenizebyseparator(bufstr_get(db, i), "\\");
343 for(j = 2; j < m; j += 2)
344 fputs(fh, strcat("\\", argv(j-1), "\\", argv(j), "\n"));
349 void db_close(float db)
354 string db_get(float db, string pKey)
357 h = mod(crc16(FALSE, pKey), DB_BUCKETS);
358 return uri_unescape(infoget(bufstr_get(db, h), pKey));
361 void db_put(float db, string pKey, string pValue)
364 h = mod(crc16(FALSE, pKey), DB_BUCKETS);
365 bufstr_set(db, h, infoadd(bufstr_get(db, h), pKey, uri_escape(pValue)));
372 db = db_load("foo.db");
373 print("LOADED. FILL...\n");
374 for(i = 0; i < DB_BUCKETS; ++i)
375 db_put(db, ftos(random()), "X");
376 print("FILLED. SAVE...\n");
377 db_save(db, "foo.db");
378 print("SAVED. CLOSE...\n");
383 // Multiline text file buffers
384 float buf_load(string pFilename)
391 fh = fopen(pFilename, FILE_READ);
395 while((l = fgets(fh)))
397 bufstr_set(buf, i, l);
404 void buf_save(float buf, string pFilename)
407 fh = fopen(pFilename, FILE_WRITE);
409 error(strcat("Can't write buf to ", pFilename));
410 n = buf_getsize(buf);
411 for(i = 0; i < n; ++i)
412 fputs(fh, strcat(bufstr_get(buf, i), "\n"));
416 string GametypeNameFromType(float g)
418 if (g == GAME_DEATHMATCH) return "dm";
419 else if (g == GAME_TEAM_DEATHMATCH) return "tdm";
420 else if (g == GAME_DOMINATION) return "dom";
421 else if (g == GAME_CTF) return "ctf";
422 else if (g == GAME_RUNEMATCH) return "rune";
423 else if (g == GAME_LMS) return "lms";
424 else if (g == GAME_ARENA) return "arena";
425 else if (g == GAME_KEYHUNT) return "kh";
426 else if (g == GAME_ONSLAUGHT) return "ons";
427 else if (g == GAME_ASSAULT) return "as";
428 else if (g == GAME_RACE) return "race";
432 string mmsss(float tenths)
436 tenths = floor(tenths + 0.5);
437 minutes = floor(tenths / 600);
438 tenths -= minutes * 600;
439 s = ftos(1000 + tenths);
440 return strcat(ftos(minutes), ":", substring(s, 1, 2), ".", substring(s, 3, 1));
443 string ScoreString(float pFlags, float pValue)
448 pValue = floor(pValue + 0.5); // round
450 if((pValue == 0) && (pFlags & (SFL_HIDE_ZERO | SFL_RANK | SFL_TIME)))
452 else if(pFlags & SFL_RANK)
454 valstr = ftos(pValue);
456 if((l >= 2) && (substring(valstr, l - 2, 1) == "1"))
457 valstr = strcat(valstr, "th");
458 else if(substring(valstr, l - 1, 1) == "1")
459 valstr = strcat(valstr, "st");
460 else if(substring(valstr, l - 1, 1) == "2")
461 valstr = strcat(valstr, "nd");
462 else if(substring(valstr, l - 1, 1) == "3")
463 valstr = strcat(valstr, "rd");
465 valstr = strcat(valstr, "th");
467 else if(pFlags & SFL_TIME)
468 valstr = mmsss(pValue);
470 valstr = ftos(pValue);
475 vector cross(vector a, vector b)
478 '1 0 0' * (a_y * b_z - a_z * b_y)
479 + '0 1 0' * (a_z * b_x - a_x * b_z)
480 + '0 0 1' * (a_x * b_y - a_y * b_x);
483 // compressed vector format:
484 // like MD3, just even shorter
485 // 4 bit pitch (16 angles), 0 is -90, 8 is 0, 16 would be 90
486 // 5 bit yaw (32 angles), 0=0, 8=90, 16=180, 24=270
487 // 7 bit length (logarithmic encoding), 1/8 .. about 7844
488 // length = 2^(length_encoded/8) / 8
489 // if pitch is 90, yaw does nothing and therefore indicates the sign (yaw is then either 11111 or 11110); 11111 is pointing DOWN
490 // thus, valid values are from 0000.11110.0000000 to 1111.11111.1111111
491 // the special value 0 indicates the zero vector
493 float lengthLogTable[128];
495 float invertLengthLog(float x)
497 float l, r, m, lerr, rerr;
499 if(x >= lengthLogTable[127])
501 if(x <= lengthLogTable[0])
509 m = floor((l + r) / 2);
510 if(lengthLogTable[m] < x)
516 // now: r is >=, l is <
517 lerr = (x - lengthLogTable[l]);
518 rerr = (lengthLogTable[r] - x);
524 vector decompressShortVector(float data)
527 float pitch, yaw, len;
530 pitch = (data & 0xF000) / 0x1000;
531 yaw = (data & 0x0F80) / 0x80;
532 len = (data & 0x007F);
534 //print("\ndecompress: pitch ", ftos(pitch)); print("yaw ", ftos(yaw)); print("len ", ftos(len), "\n");
547 yaw = .19634954084936207740 * yaw;
548 pitch = .19634954084936207740 * pitch - 1.57079632679489661922;
549 out_x = cos(yaw) * cos(pitch);
550 out_y = sin(yaw) * cos(pitch);
554 //print("decompressed: ", vtos(out), "\n");
556 return out * lengthLogTable[len];
559 float compressShortVector(vector vec)
562 float pitch, yaw, len;
565 //print("compress: ", vtos(vec), "\n");
566 ang = vectoangles(vec);
570 if(ang_x < -90 && ang_x > +90)
571 error("BOGUS vectoangles");
572 //print("angles: ", vtos(ang), "\n");
574 pitch = floor(0.5 + (ang_x + 90) * 16 / 180) & 15; // -90..90 to 0..14
583 yaw = floor(0.5 + ang_y * 32 / 360) & 31; // 0..360 to 0..32
584 len = invertLengthLog(vlen(vec));
586 //print("compressed: pitch ", ftos(pitch)); print("yaw ", ftos(yaw)); print("len ", ftos(len), "\n");
588 return (pitch * 0x1000) + (yaw * 0x80) + len;
591 void compressShortVector_init()
596 for(i = 0; i < 128; ++i)
598 lengthLogTable[i] = l;
602 if(cvar("developer"))
604 print("Verifying vector compression table...\n");
605 for(i = 0x0F00; i < 0xFFFF; ++i)
606 if(i != compressShortVector(decompressShortVector(i)))
608 print("BROKEN vector compression: ", ftos(i));
609 print(" -> ", vtos(decompressShortVector(i)));
610 print(" -> ", ftos(compressShortVector(decompressShortVector(i))));
619 float CheckWireframeBox(entity forent, vector v0, vector dvx, vector dvy, vector dvz)
621 traceline(v0, v0 + dvx, TRUE, forent); if(trace_fraction < 1) return 0;
622 traceline(v0, v0 + dvy, TRUE, forent); if(trace_fraction < 1) return 0;
623 traceline(v0, v0 + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
624 traceline(v0 + dvx, v0 + dvx + dvy, TRUE, forent); if(trace_fraction < 1) return 0;
625 traceline(v0 + dvx, v0 + dvx + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
626 traceline(v0 + dvy, v0 + dvy + dvx, TRUE, forent); if(trace_fraction < 1) return 0;
627 traceline(v0 + dvy, v0 + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
628 traceline(v0 + dvz, v0 + dvz + dvx, TRUE, forent); if(trace_fraction < 1) return 0;
629 traceline(v0 + dvz, v0 + dvz + dvy, TRUE, forent); if(trace_fraction < 1) return 0;
630 traceline(v0 + dvx + dvy, v0 + dvx + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
631 traceline(v0 + dvx + dvz, v0 + dvx + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
632 traceline(v0 + dvy + dvz, v0 + dvx + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
636 void fixedmakevectors(vector a)
638 // a makevectors that actually inverts vectoangles
644 string fixPriorityList(string order, float from, float to, float complete)
649 n = tokenize_sane(order);
650 for(i = 0; i < n; ++i)
653 if(w >= from && w <= to && w == floor(w))
654 neworder = strcat(neworder, ftos(w), " ");
659 n = tokenize_sane(neworder);
660 for(w = to; w >= from; --w)
662 for(i = 0; i < n; ++i)
663 if(stof(argv(i)) == w)
665 if(i == n) // not found
666 neworder = strcat(neworder, ftos(w), " ");
670 return substring(neworder, 0, strlen(neworder) - 1);
673 string swapInPriorityList(string order, float i, float j)
678 n = tokenize_sane(order);
680 if(i >= 0 && i < n && j >= 0 && j < n && i != j)
683 for(w = 0; w < n; ++w)
686 s = strcat(s, argv(j), " ");
688 s = strcat(s, argv(i), " ");
690 s = strcat(s, argv(w), " ");
692 return substring(s, 0, strlen(s) - 1);
698 float cvar_value_issafe(string s)
700 if(strstrofs(s, "\"", 0) >= 0)
702 if(strstrofs(s, "\\", 0) >= 0)
704 if(strstrofs(s, ";", 0) >= 0)
706 if(strstrofs(s, "$", 0) >= 0)
708 if(strstrofs(s, "\r", 0) >= 0)
710 if(strstrofs(s, "\n", 0) >= 0)
716 void get_mi_min_max(float mode)
721 strunzone(mi_shortname);
722 mi_shortname = mapname;
723 if(!strcasecmp(substring(mi_shortname, 0, 5), "maps/"))
724 mi_shortname = substring(mi_shortname, 5, strlen(mi_shortname) - 5);
725 if(!strcasecmp(substring(mi_shortname, strlen(mi_shortname) - 4, 4), ".bsp"))
726 mi_shortname = substring(mi_shortname, 0, strlen(mi_shortname) - 4);
727 mi_shortname = strzone(mi_shortname);
739 MapInfo_Get_ByName(mi_shortname, 0, 0);
740 if(MapInfo_Map_mins_x < MapInfo_Map_maxs_x)
742 mi_min = MapInfo_Map_mins;
743 mi_max = MapInfo_Map_maxs;
751 tracebox('1 0 0' * mi_x,
752 '0 1 0' * mi_y + '0 0 1' * mi_z,
753 '0 1 0' * ma_y + '0 0 1' * ma_z,
757 if(!trace_startsolid)
758 mi_min_x = trace_endpos_x;
760 tracebox('0 1 0' * mi_y,
761 '1 0 0' * mi_x + '0 0 1' * mi_z,
762 '1 0 0' * ma_x + '0 0 1' * ma_z,
766 if(!trace_startsolid)
767 mi_min_y = trace_endpos_y;
769 tracebox('0 0 1' * mi_z,
770 '1 0 0' * mi_x + '0 1 0' * mi_y,
771 '1 0 0' * ma_x + '0 1 0' * ma_y,
775 if(!trace_startsolid)
776 mi_min_z = trace_endpos_z;
778 tracebox('1 0 0' * ma_x,
779 '0 1 0' * mi_y + '0 0 1' * mi_z,
780 '0 1 0' * ma_y + '0 0 1' * ma_z,
784 if(!trace_startsolid)
785 mi_max_x = trace_endpos_x;
787 tracebox('0 1 0' * ma_y,
788 '1 0 0' * mi_x + '0 0 1' * mi_z,
789 '1 0 0' * ma_x + '0 0 1' * ma_z,
793 if(!trace_startsolid)
794 mi_max_y = trace_endpos_y;
796 tracebox('0 0 1' * ma_z,
797 '1 0 0' * mi_x + '0 1 0' * mi_y,
798 '1 0 0' * ma_x + '0 1 0' * ma_y,
802 if(!trace_startsolid)
803 mi_max_z = trace_endpos_z;
808 void get_mi_min_max_texcoords(float mode)
812 get_mi_min_max(mode);
817 // extend mi_picmax to get a square aspect ratio
818 // center the map in that area
819 extend = mi_picmax - mi_picmin;
820 if(extend_y > extend_x)
822 mi_picmin_x -= (extend_y - extend_x) * 0.5;
823 mi_picmax_x += (extend_y - extend_x) * 0.5;
827 mi_picmin_y -= (extend_x - extend_y) * 0.5;
828 mi_picmax_y += (extend_x - extend_y) * 0.5;
831 // add another some percent
832 extend = (mi_picmax - mi_picmin) * (1 / 64.0);
836 // calculate the texcoords
837 mi_pictexcoord0 = mi_pictexcoord1 = mi_pictexcoord2 = mi_pictexcoord3 = '0 0 0';
838 // first the two corners of the origin
839 mi_pictexcoord0_x = (mi_min_x - mi_picmin_x) / (mi_picmax_x - mi_picmin_x);
840 mi_pictexcoord0_y = (mi_min_y - mi_picmin_y) / (mi_picmax_y - mi_picmin_y);
841 mi_pictexcoord2_x = (mi_max_x - mi_picmin_x) / (mi_picmax_x - mi_picmin_x);
842 mi_pictexcoord2_y = (mi_max_y - mi_picmin_y) / (mi_picmax_y - mi_picmin_y);
843 // then the other corners
844 mi_pictexcoord1_x = mi_pictexcoord0_x;
845 mi_pictexcoord1_y = mi_pictexcoord2_y;
846 mi_pictexcoord3_x = mi_pictexcoord2_x;
847 mi_pictexcoord3_y = mi_pictexcoord0_y;
852 void cvar_settemp(string pKey, string pValue)
854 error("cvar_settemp called from CSQC - use cvar_clientsettemp instead!");
856 void cvar_settemp_restore()
858 error("cvar_settemp_restore called from CSQC - use cvar_clientsettemp instead!");
861 void cvar_settemp(string pKey, string pValue)
863 cvar_set("settemp_list", strcat("1 ", pKey, " ", cvar_string("settemp_var"), " ", cvar_string("settemp_list")));
865 registercvar(cvar_string("settemp_var"), "", 0);
867 registercvar(cvar_string("settemp_var"), "");
869 cvar_set(cvar_string("settemp_var"), cvar_string(pKey));
870 cvar_set("settemp_var", strcat(cvar_string("settemp_var"), "x"));
871 cvar_set(pKey, pValue);
874 void cvar_settemp_restore()
876 // undo what cvar_settemp did
878 n = tokenize_sane(cvar_string("settemp_list"));
879 for(i = 0; i < n - 3; i += 3)
880 cvar_set(argv(i + 1), cvar_string(argv(i + 2)));
881 cvar_set("settemp_list", "0");
885 float almost_equals(float a, float b)
888 eps = (max(a, -a) + max(b, -b)) * 0.001;
889 if(a - b < eps && b - a < eps)
894 float almost_in_bounds(float a, float b, float c)
897 eps = (max(a, -a) + max(c, -c)) * 0.001;
898 return b == median(a - eps, b, c + eps);
904 float (string s) _tokenize_builtin = #58;
905 string (float argnum) _argv_builtin = #59;
906 float (string s, string sep) _tokenizebyseparator_builtin = #479;
908 float (string s) _tokenize_builtin = #441;
909 string (float argnum) _argv_builtin = #442;
910 float (string s, string sep) _tokenizebyseparator_builtin = #479;
913 float MAX_TOKENS = 256;
914 string _argv_sane_buffer[MAX_TOKENS];
915 float _argv_sane_startpos[MAX_TOKENS];
916 float _argv_sane_endpos[MAX_TOKENS];
919 string _argv_sane(float i)
921 // Perl-ish -1 for the last argument
924 return strcat("", _argv_sane_buffer[i]); // force tempstring
927 float _argv_start_index_sane(float i)
929 // Perl-ish -1 for the last argument
932 return _argv_sane_startpos[i];
935 float _argv_end_index_sane(float i)
937 // Perl-ish -1 for the last argument
940 return _argv_sane_endpos[i];
943 string TOKENIZE_SANE_WHITESPACE_CHARS = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
944 string TOKENIZE_SANE_COMMENT_BREAKERS = "\x0d\x0a";
945 // change this if DP changes its type to "char"!
947 float _tokenize_sane(string s)
949 // This MUST match COM_ParseToken_Console!
950 string com_token, tmp;
959 for(i = 0; i < MAX_TOKENS; ++i)
961 if(_argv_sane_buffer[i])
962 strunzone(_argv_sane_buffer[i]);
963 _argv_sane_buffer[i] = string_null;
964 _argv_sane_startpos[i] = 0;
970 for(; data < end && strstrofs(TOKENIZE_SANE_WHITESPACE_CHARS, substring(s, data, 1), 0) >= 0; ++data)
975 if(substring(s, data, 2) == "//")
979 // Any call to the tokenizer ALREADY assumes it's a single line, so we can safely abort if we see a comment.
982 while(data < end && strstrofs(TOKENIZE_SANE_COMMENT_BREAKERS, substring(s, data, 1), 0) >= 0)
984 continue; // go to skipwhite again
987 // I'd like to simply put a "break" here, but then fteqcc says this function has unreachable code
990 else if(substring(s, data, 1) == "\"")
994 _argv_sane_startpos[_argc_sane] = data;
995 for(++data; data < end && substring(s, data, 1) != "\""; ++data)
997 // allow escaped " and \ case
998 tmp = substring(s, data, 2);
999 if(tmp == "\\\"" || tmp == "\\\\")
1001 com_token = strcat(com_token, substring(s, data, 1));
1003 if(substring(s, data, 1) == "\"")
1005 _argv_sane_endpos[_argc_sane] = data;
1006 _argv_sane_buffer[_argc_sane] = strzone(com_token);
1013 _argv_sane_startpos[_argc_sane] = data;
1014 for(; data < end && strstrofs(TOKENIZE_SANE_WHITESPACE_CHARS, substring(s, data, 1), 0) < 0; ++data)
1015 com_token = strcat(com_token, substring(s, data, 1));
1016 _argv_sane_endpos[_argc_sane] = data;
1017 _argv_sane_buffer[_argc_sane] = strzone(com_token);
1027 var void(void) func_null;
1030 // matching the console 1:1
1032 float tokenize_sane(string s)
1035 argv_start_index = _argv_start_index_sane;
1036 argv_end_index = _argv_end_index_sane;
1037 return _tokenize_sane(s);
1040 float tokenize_insane(string s)
1042 argv = _argv_builtin;
1043 argv_start_index = func_null;
1044 argv_end_index = func_null;
1045 return _tokenize_builtin(s);
1048 float tokenizebyseparator(string s, string sep)
1050 argv = _argv_builtin;
1051 argv_start_index = func_null;
1052 argv_end_index = func_null;
1053 return _tokenizebyseparator_builtin(s, sep);