30 #define ERROR_LENGTH 64
31 #define RS_MAX_TRIES 5
51 static int Parsing_paused = 0;
55 static int Mission_text_size = 0;
61 return ((ch ==
' ') || (ch ==
'\t') || (ch ==
EOLN));
67 return ((ch ==
' ') || (ch ==
'\t'));
72 return ((ch ==
'(') || (ch ==
')'));
95 int i = strlen(str) - 1;
106 int i = str.length() - 1;
130 memmove(str, str+first, len-first);
151 for (i = 0; (first +
i) < len; i++)
152 str[i] = str[first + i];
176 memmove(str, str + s, e - s + 1);
199 newlen = last - first + 1;
211 for (i = 0; i < newlen; i++)
212 str[i] = str[first + i];
235 va_start(args, format);
239 nprintf((
"Parse",
"%s", buffer.c_str()));
280 if ( !incomment && (*p ==
'/') && (*(p+1) ==
'*') ) {
288 if ( multiline && (*(p-1) ==
'*') && (*p ==
'/') ) {
294 if ( !multiline && incomment )
314 if (error_level == 0) {
322 va_start(args, format);
337 char terminators[128];
339 Assert((more_terminators == NULL) || (strlen(more_terminators) < 125));
341 terminators[0] =
EOLN;
344 if (more_terminators != NULL)
345 strcat_s(terminators, more_terminators);
349 while (strchr(terminators, *
Mp) == NULL)
360 in_quotes = !in_quotes;
385 if (end && *
Mp ==
'#')
411 endlen = strlen(end);
416 if (end && *
Mp ==
'#')
435 int len1, len2, endlen;
438 len1 = strlen(pstr1);
439 len2 = strlen(pstr2);
441 endlen = strlen(end);
446 if (end && *
Mp ==
'#')
482 nprintf((
"Error",
"Error: Unable to find required token [%s]\n", pstr));
483 Warning(
LOCATION,
"Error: Unable to find required token [%s]\n", pstr);
558 }
else if ( !
strnicmp(str2,
Mp, strlen(str2)) ) {
569 Assertion(arg_count > 0,
"optional_string_one_of() called with arg_count of %d; get a coder!\n", arg_count);
576 va_start(vl, arg_count);
577 for (idx = 0; idx < arg_count; idx++)
579 pstr = va_arg(vl,
char*);
603 if ((*
Mp ==
'#') || (end && !
strnicmp(end,
Mp, strlen(end)))) {
613 diag_printf(
"Required string [%s] not found\n", pstr);
640 if ((*
Mp ==
'#') || (end && !
strnicmp(end,
Mp, strlen(end))) ||
641 (end2 && !
strnicmp(end2,
Mp, strlen(end2)))) {
651 diag_printf(
"Optional string [%s] not found\n", pstr);
682 }
else if (
strnicmp(str2,
Mp, strlen(str2)) == 0) {
694 nprintf((
"Error",
"Error: Unable to find either required token [%s] or [%s]\n", str1, str2));
695 Warning(
LOCATION,
"Error: Unable to find either required token [%s] or [%s]\n", str1, str2);
710 Assertion(arg_count > 0,
"required_string_one_of() called with arg_count of %d; get a coder!\n", arg_count);
720 va_start(vl, arg_count);
721 for (idx = 0; idx < arg_count; idx++) {
722 expected = va_arg(vl,
char*);
723 if (
strnicmp(expected,
Mp, strlen(expected)) == 0) {
731 if (!message.compare(
"")) {
732 va_start(vl, arg_count);
733 message =
"Required token = ";
734 for (idx = 0; idx < arg_count; idx++) {
736 message += va_arg(vl,
char*);
738 if (arg_count == 2 && idx == 0) {
740 }
else if (idx == arg_count - 2) {
742 }
else if (idx < arg_count - 2) {
768 }
else if (!
strnicmp(str2,
Mp, strlen(str2))) {
779 diag_printf(
"Unable to find either required token [%s] or [%s]\n", str1, str2);
786 void copy_to_eoln(
char *outstr,
char *more_terminators,
char *instr,
int max)
790 char terminators[128];
792 Assert((more_terminators == NULL) || (strlen(more_terminators) < 125));
794 terminators[0] =
EOLN;
797 if (more_terminators != NULL)
798 strcat_s(terminators, more_terminators);
802 while (((ch = *instr++) != 0) && (strchr(terminators, ch) == NULL) && (count < max)) {
817 char terminators[128];
819 Assert((more_terminators == NULL) || (strlen(more_terminators) < 125));
821 terminators[0] =
EOLN;
824 if (more_terminators != NULL)
825 strcat_s(terminators, more_terminators);
830 while (((ch = *instr++) != 0) && (strchr(terminators, ch) == NULL)) {
831 outstr.append(1, ch);
843 while (((ch = *instr++)>0) && (ch !=
EOLN) && (ch !=
EOF_CHAR) && (count < max)) {
845 in_quotes = !in_quotes;
872 while (((ch = *instr++)>0) && (ch !=
EOLN) && (ch !=
EOF_CHAR)) {
874 in_quotes = !in_quotes;
884 outstr.append(1, ch);
892 char *foundstr =
stristr(instr, endstr);
901 if ( (foundstr - instr) <= 0 ) {
907 rstr = (
char*)
vm_malloc((foundstr - instr + 1)*
sizeof(char));
910 strncpy(rstr, instr, foundstr-instr);
911 rstr[foundstr-instr] =
'\0';
913 Error(
LOCATION,
"Could not allocate enough memory in alloc_text_until");
926 Assert(outstr && instr && endstr);
928 foundstr =
stristr(instr, endstr);
930 if (foundstr == NULL) {
931 nprintf((
"Error",
"Error. Looking for [%s], but never found it.\n", endstr));
935 if (foundstr - instr + strlen(endstr) < (
uint) max_chars) {
936 strncpy(outstr, instr, foundstr - instr);
937 outstr[foundstr - instr] = 0;
940 nprintf((
"Error",
"Error. Too much text (" SIZE_T_ARG " chars, %i allowed) before %s\n",
941 foundstr - instr - strlen(endstr), max_chars, endstr));
946 diag_printf(
"Here's the partial wad of text:\n%.30s\n", outstr);
955 foundstr =
stristr(instr, endstr);
957 if (foundstr == NULL) {
958 nprintf((
"Error",
"Error. Looking for [%s], but never found it.\n", endstr));
962 outstr.assign(instr, foundstr - instr);
964 diag_printf(
"Here's the partial wad of text:\n%.30s\n", outstr.c_str());
995 Mp += strlen(outstr);
1004 Mp += outstr.length();
1016 Assert(startstr != NULL && endstr != NULL);
1020 uint elen = strlen(endstr);
1021 uint slen = strlen(startstr);
1039 else if(!
strnicmp(pos, endstr, elen))
1065 rval = (
char*)
vm_malloc((flen + extra_chars + 1)*
sizeof(char));
1069 strncpy(rval, Mp, flen);
1098 Assertion (sexp_variable_index != -1,
"Didn't find variable name \"%s\"", str);
1104 else if (*
Mp ==
'"')
1112 Error(
LOCATION,
"Invalid entry \"%s\" found in get_string_or_variable. Must be a quoted string or a string variable name.", str);
1133 Assertion (sexp_variable_index != -1,
"Didn't find variable name \"%s\"", str.c_str());
1139 else if (*
Mp ==
'"')
1147 Error(
LOCATION,
"Invalid entry \"%s\" found in get_string_or_variable. Must be a quoted string or a string variable name.", str.c_str());
1161 len = strcspn(
Mp + 1,
"\"");
1163 if (max >= 0 && len >= max)
1164 error_display(0,
"String too long. Length = %i. Max is %i.\n", len, max);
1166 strncpy(str,
Mp + 1, len);
1180 len = strcspn(
Mp + 1,
"\"");
1181 str.assign(
Mp + 1, len);
1193 int final_len = len - 1;
1200 memset( outstr, 0, len );
1219 Mp += strlen(read_str);
1229 Mp += strlen(read_str);
1236 Mp += strlen(read_str);
1242 Error(
LOCATION,
"Unhandled string type %d in stuff_string!", type);
1247 if (strlen(read_str) == 0) {
1249 error_display(1,
"A file name was expected but no name was supplied!\n");
1265 if ( strlen(read_str) > (
uint)final_len )
1266 error_display(0,
"Token too long: [%s]. Length = %i. Max is %i.\n", read_str, strlen(read_str), final_len);
1268 strncpy(outstr, read_str, final_len);
1271 diag_printf(
"Stuffed string = [%.30s]\n", outstr);
1301 Mp += read_str.length();
1311 Mp += read_str.length();
1318 Mp += read_str.length();
1324 Error(
LOCATION,
"Unhandled string type %d in stuff_string!", type);
1329 if (read_str.empty()) {
1331 error_display(1,
"A file name was expected but no name was supplied!\n");
1350 diag_printf(
"Stuffed string = [%.30s]\n", outstr.c_str());
1358 int final_len = len - 1;
1377 diag_printf(
"Stuffed string = [%.30s]\n", outstr);
1400 diag_printf(
"Stuffed string = [%.30s]\n", outstr.c_str());
1413 if (tmp_result.empty())
1427 if((*dest) != NULL) {
1441 unsigned int len = strlen(str);
1444 for (i=0; i<
len; i++)
1451 else if (str[i] ==
'\n')
1452 str[i-num_cr] =
' ';
1453 else if (num_cr > 0)
1454 str[i-num_cr] = str[
i];
1458 str[len-num_cr] = 0;
1465 unsigned int len = str.length();
1468 for (i=0; i<
len; i++)
1475 else if (str[i] ==
'\n')
1476 str[i-num_cr] =
' ';
1477 else if (num_cr > 0)
1478 str[i-num_cr] = str[
i];
1482 str.resize(len-num_cr);
1720 for (ch = line; *ch !=
'\0'; ch++)
1733 for (SCP_string::iterator ii = line.begin(); ii != line.end(); ++ii)
1741 const char *ch = text;
1747 if (*ch ==
'\0' || len == 8)
1751 if (*ch == separator)
1775 SCP_string::iterator ch = text_pos;
1781 if (ch == text.end() || len == 8)
1785 if (*ch == separator)
1810 if (
strnicmp(line_start,
";;FSO ", 6))
1813 int major, minor, build, revis;
1824 const char *ch = line_start + 6;
1825 while ((*ch) !=
';') {
1826 Assertion((*ch) !=
'\0',
"String that was already guaranteed to end with semicolons did not end with semicolons; it's possible we have fallen into an alternate universe. Failing string: [%s]\n", line_start);
1830 Assertion((*ch) ==
';',
"String that was guaranteed to have double semicolons did not; it's possible we have fallen into an alternate universe. Failing string: [%s]\n", line_start);
1833 tag_len = ch - line_start;
1834 compatible_version =
true;
1839 compatible_version =
false;
1845 compatible_version =
false;
1851 compatible_version =
false;
1857 compatible_version =
false;
1869 void strip_comments(
char *line,
bool &in_quote,
bool &in_multiline_comment_a,
bool &in_multiline_comment_b)
1871 char *writep = line;
1875 while (*readp !=
'\r' && *readp !=
'\n' && *readp !=
'\0')
1880 bool compatible_version;
1884 if (!strncmp(readp,
"/*", 2))
1887 if (!in_multiline_comment_b)
1888 in_multiline_comment_a =
true;
1890 else if (!strncmp(readp,
"!*", 2))
1893 if (!in_multiline_comment_a)
1894 in_multiline_comment_b =
true;
1896 else if (!strncmp(readp,
"*/", 2))
1898 if (in_multiline_comment_a)
1900 in_multiline_comment_a =
false;
1905 else if (!strncmp(readp,
"*!", 2))
1907 if (in_multiline_comment_b)
1909 in_multiline_comment_b =
false;
1919 if (compatible_version)
1931 else if (*readp ==
';')
1939 in_quote = !in_quote;
1942 if (!in_multiline_comment_a && !in_multiline_comment_b)
1944 if (writep != readp)
1955 if (writep != readp || *readp !=
'\0')
1965 int i, num_chars_read=0;
1969 for ( i = 0; i < max_line_len-1; i++ ) {
1971 if ( (cur - start) >= max_size ) {
1973 if ( lineout > t ) {
1974 return num_chars_read;
1981 }
while ( c == 13 );
1984 if ( c==
'\n' )
break;
1988 return num_chars_read;
2004 if ( Parsing_paused && ((processed_text == NULL) || (raw_text == NULL)) ) {
2005 Error(
LOCATION,
"ERROR: Neither processed_text nor raw_text may be NULL when parsing is paused!!\n");
2011 if (processed_text == NULL)
2014 if (raw_text == NULL)
2028 if ( Parsing_paused && ((processed_text == NULL) || (raw_text == NULL)) ) {
2029 Error(
LOCATION,
"ERROR: Neither \"processed_text\" nor \"raw_text\" may be NULL when parsing is paused!!\n");
2036 if (raw_text == NULL)
2040 if (raw_text != array)
2041 strcpy(raw_text, array);
2043 if (processed_text == NULL)
2053 if (!strncmp(text,
"\xEF\xBB\xBF", 3))
2056 if (!strncmp(text,
"\xFE\xFF", 2))
2059 if (!strncmp(text,
"\xFF\xFE", 2))
2062 if (!strncmp(text,
"\x00\x00\xFE\xFF", 4))
2065 if (!strncmp(text,
"\xFF\xFE\x00\x00", 4))
2073 Assert( !Parsing_paused );
2085 Mission_text_size = 0;
2092 if (size <= Mission_text_size)
2096 static ubyte parse_atexit = 0;
2098 if (!parse_atexit) {
2117 Error(
LOCATION,
"Unable to allocate enough memory for Mission_text! Aborting...\n");
2123 Mission_text_size =
size;
2130 int file_is_encrypted;
2131 int file_is_unicode;
2138 nprintf((
"Error",
"Wokka! Error opening file (%s)!\n", filename));
2146 nprintf((
"Error",
"Oh noes!! File is empty! (%s)!\n", filename));
2154 if (raw_text == NULL)
2158 cfread(raw_text,
MIN(file_len, 10), 1, mf);
2164 if ( file_is_unicode )
2167 Error(
LOCATION,
"%s is in Unicode/UTF format and cannot be read by FreeSpace Open. Please convert it to ASCII/ANSI\n", filename);
2170 if ( file_is_encrypted )
2172 int unscrambled_len;
2173 char *scrambled_text;
2174 scrambled_text = (
char*)
vm_malloc(file_len+1);
2176 cfread(scrambled_text, file_len, 1, mf);
2178 unencrypt(scrambled_text, file_len, raw_text, &unscrambled_len);
2179 file_len = unscrambled_len;
2184 cfread(raw_text, file_len, 1, mf);
2188 raw_text[file_len] =
'\0';
2199 bool in_quote =
false;
2200 bool in_multiline_comment_a =
false;
2201 bool in_multiline_comment_b =
false;
2202 int raw_text_len = strlen(raw_text);
2204 if (processed_text == NULL)
2207 if (raw_text == NULL)
2210 Assert( processed_text != NULL );
2211 Assert( raw_text != NULL );
2213 mp = processed_text;
2217 int num_chars_read = 0;
2219 mp_raw += num_chars_read;
2222 if (!strcmp(outbuf,
"1402, \"Sie haben IPX-Protokoll als Protokoll ausgew\xE4hlt, aber dieses Protokoll ist auf Ihrer Maschine nicht installiert.\".\"\n")) {
2225 }
else if (!strcmp(outbuf,
"1117, \"\\r\\n\"Aucun web browser trouva. Del\xE0 isn't on emm\xE9nagea ou if \\r\\non est emm\xE9nagea, ca isn't set pour soient la default browser.\\r\\n\\r\\n\"\n")) {
2226 char *ch = &outbuf[11];
2231 }
else if (!strcmp(outbuf,
"1337, \"(fr)Loading\"\n")) {
2233 }
else if (!strcmp(outbuf,
"3966, \"Es sieht so aus, als habe Staffel Kappa Zugriff auf die GTVA-Zugangscodes f\xFCr das System gehabt. Das ist ein ernstes Sicherheitsleck. Ihre IFF-Kennung erschien als \"verb\xFCndet\", so da\xDF sie sich dem Konvoi ungehindert n\xE4hern konnten. Zum Gl\xFC\x63k flogen Sie und Alpha 2 Geleitschutz und lie\xDF\x65n den Schwindel auffliegen, bevor Kappa ihren Befehl ausf\xFChren konnte.\"\n")) {
2238 strip_comments(outbuf, in_quote, in_multiline_comment_a, in_multiline_comment_b);
2244 if (*str == (
Lcl_pl ? -33 : -31)) {
2298 if ((ch !=
'.') && (ch !=
'-') && (ch !=
'+') && ((ch <
'0') || (ch >
'9'))) {
2303 return (
float)atof(
Mp);
2317 if ((ch !=
'-') && (ch !=
'+') && ((ch <
'0') || (ch >
'9'))) {
2335 Mp += strspn(
Mp,
"+-0123456789.");
2351 skip_len = strspn(
Mp,
"+-0123456789.");
2352 if(*(
Mp+skip_len) ==
',') {
2379 Mp += strspn(
Mp,
"+-0123456789");
2395 skip_len = strspn(
Mp,
"+-0123456789");
2396 if(*(
Mp+skip_len) ==
',') {
2439 Error(
LOCATION,
"Invalid variable type \"%s\" found in mission. Variable must be a number variable!", str);
2445 Error(
LOCATION,
"Invalid variable name \"%s\" found.", str);
2449 if (positive_value && value < 0)
2486 Error(
LOCATION,
"Invalid variable type \"%s\" found in mission. Variable must be a number variable!", str);
2492 Error(
LOCATION,
"Invalid variable name \"%s\" found.", str);
2496 if (positive_value && value < 0)
2503 ilp[count++] =
value;
2505 ilp[count++] =
index;
2550 if( isdigit(token[0]))
2564 || !
stricmp(token,
"ita vero")
2584 Warning(
LOCATION,
"Boolean '%s' type unknown; assuming 'no/false'",token);
2594 bool trash_buf =
false;
2599 error_display(1,
"Reading boolean list. Found [%c]. Expecting '('.\n", *
Mp);
2609 if(count < max_bools)
2630 error_display(0,
"Boolean list has more than allowed arguments; max is %d. Arguments over max will be ignored.", max_bools);
2657 Mp += strspn(
Mp,
"+-0123456789");
2673 for(i = 0; i < num_strings; i++)
2675 for(j = 0; j < defs_size; j++)
2678 (*dest) |= defs[j].
def;
2697 error_display(1,
"Reading string list. Found [%c]. Expecting '('.\n", *
Mp);
2707 while (*
Mp !=
')') {
2709 error_display(0,
"Missing quotation marks in string list.");
2715 slp.push_back( buf );
2731 error_display(1,
"Reading string list. Found [%c]. Expecting '('.\n", *
Mp);
2739 while (*
Mp !=
')') {
2740 Assert ( count < max_strings );
2742 error_display(0,
"Missing quotation marks in string list.");
2746 if (count < max_strings) {
2762 switch (lookup_type) {
2766 return "Ship Classes";
2768 return "Weapon Pool";
2770 return "Weapon Types";
2772 return "Untyped integer list";
2775 return "Unknown lookup type, tell a coder!";
2784 int count = 0, ok_flag = 1, dummy;
2788 error_display(1,
"Reading integer list. Found [%c]. Expecting '('.\n", *
Mp);
2795 while (*
Mp !=
')') {
2796 Assertion(count < max_ints,
"Too many entries in integer list. Expected %d, found %d.\nList type was %s", max_ints, count+1,
get_lookup_type_name(lookup_type));
2802 switch (lookup_type) {
2838 Error(
LOCATION,
"Unable to find string \"%s\" in stuff_int_list\n\nMany possible sources for this error. Get a programmer!\n", str);
2839 }
else if (num == -2) {
2840 if (str[0] !=
'\0') {
2841 Warning(
LOCATION,
"Unable to find WEAPON_LIST_TYPE string \"%s\" in stuff_int_list\n\nMany possible sources for this error. Get a programmer!\n", str);
2848 if (count < max_ints) {
2854 if (ok_flag && (count < max_ints))
2884 int index, sexp_variable_index, variable_found;
2890 error_display(1,
"Reading loadout list. Found [%c]. Expecting '('.\n", *
Mp);
2897 while (*
Mp !=
')') {
2898 if (count >= max_ints) {
2908 if (variable_found) {
2912 if(sexp_variable_index<0) {
2913 Error(
LOCATION,
"Invalid SEXP variable name \"%s\" found in stuff_loadout_list.", str);
2919 switch (lookup_type) {
2938 Warning(
LOCATION,
"Invalid type \"%s\" found in loadout of mission file...skipping", str);
2949 Warning(
LOCATION,
"Ship type \"%s\" found in loadout of mission file. This class is not marked as a player ship...skipping", str);
2954 nprintf((
"Warning",
"Warning: Weapon type %s found in loadout of mission file. This class is not marked as a player allowed weapon...skipping\n", str));
2956 Warning(
LOCATION,
"Weapon type \"%s\" found in loadout of mission file. This class is not marked as a player allowed weapon...skipping", str);
2961 if (count < max_ints) {
2962 ilp[count++] =
index;
2973 if (count < max_ints) {
2974 ilp[count++] = sexp_variable_index;
2994 error_display(1,
"Reading float list. Found [%c]. Expecting '('.\n", *
Mp);
3002 Assert(count < max_floats);
3003 if (count < max_floats) {
3027 error_display(1,
"Marking integer list. Found [%c]. Expecting '('.\n", *
Mp);
3034 while (*
Mp !=
')') {
3040 switch(lookup_type) {
3058 if ( (num < 0) || (num >= max_ints) )
3059 Error(
LOCATION,
"Unable to find string \"%s\" in mark_int_list.\n", str);
3067 Assert((tval >= 0) && (tval < max_ints));
3068 if (tval >= 0 && tval < max_ints) {
3094 error_display(1,
"Reading parenthesized vec3d. Found [%c]. Expecting '('.\n", *
Mp);
3101 error_display(1,
"Reading parenthesized vec3d. Found [%c]. Expecting ')'.\n", *
Mp);
3121 error_display(1,
"Reading vec3d list. Found [%c]. Expecting '('.\n", *
Mp);
3129 while (*
Mp !=
')') {
3130 Assert(count < max_vecs);
3131 if (count < max_vecs) {
3152 error_display(1,
"Reading vec3d list. Found [%c]. Expecting '('.\n", *
Mp);
3160 while (*
Mp !=
')') {
3163 vec_list.push_back(temp);
3170 return vec_list.size();
3187 int string_lookup(
char *str1,
char *strlist[],
int max,
char *description,
int say_errors)
3191 for (i=0; i<max; i++) {
3192 Assert(strlen(strlist[i]) != 0);
3194 if (!
stricmp(str1, strlist[i]))
3199 error_display(0,
"Unable to find [%s] in %s list.\n", str1, description);
3210 int checking_ship_classes = (
stricmp(
id,
"$class:") == 0);
3215 *addr =
string_lookup(token, strlist, max, description, !checking_ship_classes);
3218 if (*addr < 0 && checking_ship_classes)
3252 int max,
char *description)
3260 *addr =
string_lookup(token, strlist, *total, description, 0);
3265 strcpy(strlist[*total], token);
3274 Assert( !Parsing_paused );
3291 Assert( Parsing_paused );
3292 if (!Parsing_paused)
3322 nprintf((
"Parse",
"\nParse complete.\n"));
3333 int i,
w,
len, last_was_white = 0;
3339 if ( (w <= max_pixel_w) && !strstr(src,
"\n") ) {
3344 for (i=0; i<
len; i++) {
3346 if ( w > max_pixel_w )
3349 if (src[i] ==
'\n') {
3355 if (!last_was_white)
3368 if ( (w > max_pixel_w) && ((i == 0) || !brk) ) {
3390 #define SPLIT_STR_BUFFER_SIZE 512
3412 int split_str(
const char *
src,
int max_pixel_w,
int *n_chars,
const char **p_str,
int max_lines,
char ignore_char)
3415 const char *breakpoint = NULL;
3416 int sw, new_line = 1,
line_num = 0, last_was_white = 0;
3417 int ignore_until_whitespace, buf_index;
3428 ignore_until_whitespace = 0;
3439 for (; *
src; src++) {
3455 if (ignore_until_whitespace) {
3457 ignore_until_whitespace = 0;
3476 if (*src == ignore_char) {
3477 ignore_until_whitespace = 1;
3482 if (!last_was_white)
3495 buffer[buf_index] = *
src;
3497 buffer[buf_index] = 0;
3500 if (sw >= max_pixel_w) {
3504 end = src = breakpoint;
3514 if (line_num < max_lines) {
3525 if (!new_line && p_str[
line_num]) {
3527 Assert(n_chars[line_num]);
3537 const char *breakpoint = NULL;
3538 int sw, new_line = 1,
line_num = 0, last_was_white = 0;
3539 int ignore_until_whitespace = 0, buf_index = 0;
3555 for (; *
src; src++) {
3562 p_str.push_back(src);
3568 if (ignore_until_whitespace) {
3570 ignore_until_whitespace = 0;
3582 n_chars.push_back(src - p_str.at(
line_num));
3591 if (*src == ignore_char) {
3592 ignore_until_whitespace = 1;
3597 if (!last_was_white)
3610 buffer[buf_index] = *
src;
3612 buffer[buf_index] = 0;
3615 if (sw >= max_pixel_w) {
3619 end = src = breakpoint;
3626 n_chars.push_back(end - p_str.at(
line_num));
3637 if (!new_line && p_str.at(
line_num)) {
3638 n_chars.push_back(src - p_str.at(
line_num));
3653 if (!*str1 || !*str2)
3657 int len1 = strlen(str1);
3658 int len2 = strlen(str2);
3661 if (tolower(*(str1+len1-1) ==
's'))
3665 if (tolower(*(str2+len2-1) ==
's'))
3680 const char *
stristr(
const char *str,
const char *substr)
3685 if (str == NULL || substr == NULL || *substr ==
'\0')
3689 char substr_ch_lower = (char)tolower(*substr);
3690 char substr_ch_upper = (char)toupper(*substr);
3693 const char *upper_bound = str + strlen(str) - strlen(substr);
3699 if ((*
start == substr_ch_upper) || (*
start == substr_ch_lower))
3702 for (
const char *str_ch =
start+1, *substr_ch = substr+1; *substr_ch !=
'\0'; str_ch++, substr_ch++)
3705 if (*str_ch == *substr_ch)
3709 if (tolower(*str_ch) == tolower(*substr_ch))
3713 goto stristr_continue_outer_loop;
3720 stristr_continue_outer_loop:
3734 if (str == NULL || substr == NULL || *substr ==
'\0')
3738 char substr_ch_lower = (char)tolower(*substr);
3739 char substr_ch_upper = (char)toupper(*substr);
3742 const char *upper_bound = str + strlen(str) - strlen(substr);
3748 if ((*
start == substr_ch_upper) || (*
start == substr_ch_lower))
3751 for (
const char *str_ch =
start+1, *substr_ch = substr+1; *substr_ch !=
'\0'; str_ch++, substr_ch++)
3754 if (*str_ch == *substr_ch)
3758 if (tolower(*str_ch) == tolower(*substr_ch))
3762 goto stristr_continue_outer_loop;
3769 stristr_continue_outer_loop:
3785 if ((*text !=
'+') && (*text !=
'-') && !isdigit(*text))
3789 for (
const char *
p = text + 1; *
p !=
'\0';
p++)
3804 #if defined(_MSC_VER) && _MSC_VER < 1800
3812 int needed_length = vsnprintf(
nullptr, 0, format, copy);
3815 if (needed_length < 0) {
3820 dest.resize(static_cast<size_t>(needed_length));
3821 vsnprintf(&dest[0], dest.size() + 1,
format, ap);
3827 va_start(args, format);
3841 while ((p != src) && (*(p-1) ==
' '))
3857 while (index > 0 && src[index-1] ==
' ')
3871 return strchr(src,
'#');
3878 return strchr(src,
'#');
3884 size_t pos = src.find(
'#');
3885 return (pos == SCP_string::npos) ? -1 :
pos;
3891 Assert(str && oldstr && newstr);
3894 char *ch =
stristr(str, oldstr);
3900 if ((range > 0) && ((ch - str) > range))
3906 if (strlen(str) + strlen(newstr) - strlen(oldstr) > max_len)
3918 strcpy_s(temp,
sizeof(
char)*max_len, ch + strlen(oldstr));
3924 strcpy(ch + strlen(newstr), temp);
3945 while ((val =
replace_one(str, oldstr, newstr, max_len, range)) > 0)
3951 range += strlen(newstr) - strlen(oldstr);
3955 return (val < 0) ? val : tally;
3961 if ((foundHere = context.find(from, 0)) != SCP_string::npos)
3963 context.replace(foundHere, from.length(), to);
3971 if ((foundHere = context.find(from, 0)) != SCP_string::npos)
3973 context.replace(foundHere, strlen(from), to);
3981 size_t from_len = from.length();
3982 size_t to_len = to.length();
3984 size_t lookHere = 0;
3986 while ((foundHere = context.find(from, lookHere)) != SCP_string::npos)
3988 context.replace(foundHere, from_len, to);
3989 lookHere = foundHere + to_len;
3997 size_t from_len = strlen(from);
3998 size_t to_len = strlen(to);
4000 size_t lookHere = 0;
4002 while ((foundHere = context.find(from, lookHere)) != SCP_string::npos)
4004 context.replace(foundHere, from_len, to);
4005 lookHere = foundHere + to_len;
4016 Assert( (s1 != NULL) && (s2 != NULL) );
4019 char *s1_end = (
char *)strrchr(s1,
'.');
4020 char *s2_end = (
char *)strrchr(s2,
'.');
4023 size_t s1_len, s2_len;
4026 s1_len = (s1_end - s1);
4028 s1_len = strlen(s1);
4031 s2_len = (s2_end - s2);
4033 s2_len = strlen(s2);
4036 if (s2_len != s1_len)
4045 char *
p = strrchr(str,
'.');
4058 size_t pos = str.rfind(
'.');
4059 if (pos != SCP_string::npos)
4076 while(*src !=
'\0') {
4086 int old_pos, new_pos, triad_count;
4087 char backward_buf[32];
4093 if ((integer < 1000) || (integer < 10000 && !use_comma_with_four_digits))
4099 for (old_pos = strlen(buf) - 1; old_pos >= 0; old_pos--)
4101 backward_buf[new_pos] = buf[old_pos];
4105 if (triad_count == 3 && old_pos > 0)
4107 backward_buf[new_pos] =
',';
4112 backward_buf[new_pos] =
'\0';
4116 for (old_pos = strlen(backward_buf) - 1; old_pos >= 0; old_pos--)
4118 buf[new_pos] = backward_buf[old_pos];
4121 buf[new_pos] =
'\0';
4130 val = sscanf(text,
";;FSO %i.%i.%i.%i;;", major, minor, build, revis);
4135 val = sscanf(text,
";;FSO %i.%i.%i;;", major, minor, build);
4139 *build = *revis = 0;
4140 val = sscanf(text,
";;FSO %i.%i;;", major, minor);
4144 *minor = *build = *revis = 0;
4145 val = sscanf(text,
";;FSO %i;;", major);
4149 *major = *minor = *build = *revis = 0;
4156 Assert(num_allowed_lines > 0);
4157 size_t find_from = 0;
4159 while (find_from < text.size())
4161 if (num_allowed_lines <= 0)
4163 text.resize(find_from);
4164 text.append(
"[...]");
4168 size_t pos = text.find(
'\n', find_from);
4169 if (pos == SCP_string::npos)
4172 num_allowed_lines--;
4173 find_from = pos + 1;
4186 for (i=0; i<
size; i++)
4198 for (i=0; i<
size; i++)
4208 int i, num_files = 0;
4210 if ( (name_check == NULL) || (parse_callback == NULL) || ((*name_check) !=
'*') ) {
4211 Assertion(
false,
"parse_modular_table() called with invalid arguments; get a coder!\n");
4215 num_files =
cf_get_file_list(tbl_file_names, path_type, name_check, sort_type);
4219 for (i = 0; i < num_files; i++){
4220 tbl_file_names[
i] +=
".tbm";
4221 mprintf((
"TBM => Starting parse of '%s' ...\n", tbl_file_names[i].c_str()));
4222 (*parse_callback)(tbl_file_names[
i].c_str());
GLenum GLsizei GLenum format
void advance_to_eoln(char *more_terminators)
#define CAMPAIGN_LOADOUT_WEAPON_LIST
#define vm_malloc_q(size)
int ship_info_lookup(const char *token)
int stuff_string_list(SCP_vector< SCP_string > &slp)
char Error_str[ERROR_LENGTH]
char Current_filename_sub[MAX_PATH_LEN]
void format_integer_with_commas(char *buf, int integer, bool use_comma_with_four_digits)
int check_for_string(const char *pstr)
void copy_text_until(char *outstr, char *instr, char *endstr, int max_chars)
int parse_string_flag_list(int *dest, flag_def_list defs[], int defs_size)
weapon_info Weapon_info[MAX_WEAPON_TYPES]
int stuff_int_optional(int *i, bool raw)
int scan_fso_version_string(const char *text, int *major, int *minor, int *build, int *revis)
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
int maybe_convert_foreign_character(int ch)
void drop_trailing_white_space(char *str)
void unencrypt(char *scrambled_text, int scrambled_len, char *text, int *text_len)
GLsizei const GLfloat * value
int required_string_one_of(int arg_count,...)
Checks for one of any of the given required strings.
void copy_to_eoln(char *outstr, char *more_terminators, char *instr, int max)
int replace_all(char *str, char *oldstr, char *newstr, uint max_len, int range)
char * stuff_and_malloc_string(int type, char *terminators)
int check_for_string_raw(const char *pstr)
void parse_int_list(int *ilist, int size)
void stuff_malloc_string(char **dest, int type, char *terminators)
int weapon_info_lookup(const char *name=NULL)
void stuff_string_line(char *outstr, int len)
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
int Cmdline_noparseerrors
void stuff_boolean_flag(int *i, int flag, bool a_to_eol)
int subsystem_stricmp(const char *str1, const char *str2)
int stuff_float_optional(float *f, bool raw)
char * drop_white_space(char *str)
struct vec3d::@225::@227 xyz
void compact_multitext_string(char *str)
#define Assertion(expr, msg,...)
sexp_variable Sexp_variables[MAX_SEXP_VARIABLES]
int parse_get_line(char *lineout, int max_line_len, char *start, int max_size, char *cur)
GLenum GLuint GLenum GLsizei const GLchar * message
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
void stuff_matrix(matrix *mp)
int replace_one(char *str, char *oldstr, char *newstr, uint max_len, int range)
int get_index_sexp_variable_name(const char *text)
int required_string_either(char *str1, char *str2)
Checks for one of two required strings.
GLenum GLuint GLenum GLsizei const GLchar * buf
int match_and_stuff(int f_type, char *strlist[], int max, char *description)
int Num_unknown_loadout_classes
#define SPLIT_STR_BUFFER_SIZE
void stuff_float(float *f)
void copy_to_next_white(char *outstr, char *instr, int max)
void sprintf(SCP_string &dest, const char *format,...)
void backspace(char *src)
#define PARSING_FOUND_VARIABLE
int strextcmp(const char *s1, const char *s2)
void debug_show_mission_text()
char Current_filename[MAX_PATH_LEN]
struct matrix::@228::@230 vec
void stuff_string_until(char *outstr, char *endstr, int len)
void vsprintf(SCP_string &dest, const char *format, va_list ap)
int optional_string_fred(char *pstr, char *end, char *end2)
void parse_float_list(float *plist, int size)
#define PARSING_FOUND_STRING
#define strnicmp(s1, s2, n)
void stuff_string(char *outstr, int type, int len, char *terminators)
int required_string(const char *pstr)
char * alloc_text_until(char *instr, char *endstr)
int stuff_int_or_variable(int &i, bool positive_value=false)
int is_unicode(char *text)
char * get_pointer_to_first_hash_symbol(char *src)
bool can_construe_as_integer(const char *text)
int split_str(const char *src, int max_pixel_w, int *n_chars, const char **p_str, int max_lines, char ignore_char)
int optional_string(const char *pstr)
#define MISSION_LOADOUT_SHIP_LIST
void find_and_stuff(char *id, int *addr, int f_type, char *strlist[], int max, char *description)
void stuff_parenthesized_vec3d(vec3d *vp)
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
int skip_to_start_of_string_either(char *pstr1, char *pstr2, char *end)
int stuff_loadout_list(int *ilp, int max_ints, int lookup_type)
bool Parsing_modular_table
void process_raw_file_text(char *processed_text, char *raw_text)
void allocate_mission_text(int size)
int get_string(char *str, int max)
const char * get_lookup_type_name(int lookup_type)
bool matches_version_specific_tag(const char *line_start, bool &compatible_version, int &tag_len)
bool get_number_before_separator(int &number, int &number_chars, const char *text, char separator)
void stuff_vec3d(vec3d *vp)
void truncate_message_lines(SCP_string &text, int num_allowed_lines)
void read_file_text_from_array(const char *array, char *processed_text, char *raw_text)
void strip_comments(char *line, bool &in_quote, bool &in_multiline_comment_a, bool &in_multiline_comment_b)
void stuff_boolean(int *i, bool a_to_eol)
bool end_string_at_first_hash_symbol(char *src)
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
void reset_parse(char *text)
const char * stristr(const char *str, const char *substr)
GLuint const GLchar * name
void read_raw_file_text(const char *filename, int mode, char *raw_text)
GLboolean GLboolean GLboolean b
int required_string_fred(char *pstr, char *end)
int stuff_int_list(int *ilp, int max_ints, int lookup_type)
int get_string_or_variable(char *str)
void display_parse_diagnostics()
#define WIF_PLAYER_ALLOWED
int optional_string_either(char *str1, char *str2)
int is_parenthesis(char ch)
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
char * split_str_once(char *src, int max_pixel_w)
void find_and_stuff_or_add(char *id, int *addr, int f_type, char *strlist[], int *total, int max, char *description)
void mark_int_list(int *ilp, int max_ints, int lookup_type)
int stuff_vec3d_list(vec3d *vlp, int max_vecs)
SCP_vector< ship_info > Ship_info
int is_encrypted(char *scrambled_text)
void fhash_add_str(const char *str, int id)
void error_display(int error_level, char *format,...)
void ignore_white_space()
int is_gray_space(char ch)
void advance_to_next_white()
void drop_leading_white_space(char *str)
#define NOT_SET_BY_SEXP_VARIABLE
int parse_modular_table(const char *name_check, void(*parse_callback)(const char *filename), int path_type, int sort_type)
#define SEXP_VARIABLE_NUMBER
void stuff_ubyte(ubyte *i)
#define MISSION_LOADOUT_WEAPON_LIST
void find_and_stuff_optional(char *id, int *addr, int f_type, char *strlist[], int max, char *description)
int optional_string_one_of(int arg_count,...)
int stuff_bool_list(bool *blp, int max_bools)
void stuff_string_white(char *outstr, int len)
int is_white_space(char ch)
int ship_name_lookup(const char *name, int inc_players)
void lcl_ext_localize(const char *in, char *out, size_t max_len, int *id)
int string_lookup(char *str1, char *strlist[], int max, char *description, int say_errors)
void clean_loadout_list_entry()
bool drop_extension(char *str)
int cfclose(CFILE *cfile)
GLenum const GLvoid * addr
int stuff_float_list(float *flp, int max_floats)
void diag_printf(char *format,...)
int cf_get_file_list(SCP_vector< SCP_string > &list, int pathtype, const char *filter, int sort=CF_SORT_NONE, SCP_vector< file_list_info > *info=NULL)
#define CAMPAIGN_LOADOUT_SHIP_LIST
char Current_filename_save[MAX_PATH_LEN]
char * alloc_block(char *startstr, char *endstr, int extra_chars)
int skip_to_string(char *pstr, char *end)
int cfilelength(CFILE *cfile)
int get_index_of_first_hash_symbol(SCP_string &src)
int required_string_either_fred(char *str1, char *str2)
#define SEXP_VARIABLE_STRING
int skip_to_start_of_string(char *pstr, char *end)
#define MAX_SEXP_VARIABLES
void maybe_convert_foreign_characters(char *line)
int cfseek(CFILE *fp, int offset, int where)