瀏覽代碼

Feat: cumulative update

dzp 1 年之前
父節點
當前提交
66bf3d5d9e
共有 16 個文件被更改,包括 199 次插入119 次删除
  1. 5 0
      NEWS
  2. 30 0
      SCRIPTS
  3. 6 9
      TODO
  4. 9 0
      mods/igr.mods
  5. 29 25
      src/class.c
  6. 14 9
      src/help.c
  7. 21 2
      src/list.c
  8. 16 8
      src/mapper.c
  9. 13 13
      src/net.c
  10. 25 32
      src/regex.c
  11. 1 1
      src/scan.c
  12. 6 6
      src/show.c
  13. 8 1
      src/substitute.c
  14. 3 5
      src/system.c
  15. 1 1
      src/tintin.h
  16. 12 7
      src/validate

+ 5 - 0
NEWS

@@ -1,6 +1,11 @@
 Due to continuous improvements old tintin scripts aren't always compatible
 with new versions. This document tries to list most compatibility conflicts.
 
+TinTin++ 2.02.42
+----------------
+01) %%%s would get escaped to %%s in aliases and actions, this has been changed
+    so only %%%1 gets escaped to %%1, %%%s stays the same.
+
 TinTin++ 2.02.12
 ----------------
 01) The behavior of $variable[] is now identical to $variable[%*].

+ 30 - 0
SCRIPTS

@@ -771,6 +771,36 @@
 	display
 }
 
+#nop -------------------------------------------------------------------------
+#nop Example script for creating clickable menus in the scrolling region.
+#nop -------------------------------------------------------------------------
+
+#con mouse on
+
+#function link {#var result {\e]68;1;%1;%2\a\e[4m%3\e[24m}}
+
+#event {PRESSED LINK MENU MOUSE BUTTON ONE}
+{
+	#local {link} {%4};
+
+	#foreach {*link[]} {key}
+	{
+		#line {substitute} {variables;functions}
+		{
+			#var link[$key] {@link{MENU_ITEM;$link[$key];<faa>$key}}
+		}
+	};
+	#draw Azure scaled box %0+1 %1 %0+1 %1+9 $link[%*]
+}
+
+#event {PRESSED LINK MENU_ITEM MOUSE BUTTON ONE}
+{
+	#showme {<ffa>%4};
+	#buffer refresh
+}
+
+#showme {Example link: @link{MENU;{{bli}{bla}{blo}{blu}};<128>click me}}
+
 #nop -------------------------------------------------------------------------
 #nop This creates two input lines that can be switched between using the tab
 #nop key.

+ 6 - 9
TODO

@@ -1,13 +1,6 @@
-- 3Kingdoms loses color with #config color_patch on
+- Add an example script to display time left on tickers using #info tickers save
 
-#SESSION {3k} {3k.org} {3000};
-user
-pass
-#CONFIG {COLOR PATCH} {on};
-#EVENT {RECEIVED PROMPT}
-{
-  #NOP Do Something;
-};
+- comprehensive memory breakdown for variables/triggers/mapper/etc
 
 - Problem with restoring true color subs.
 #sub bla {<F00AA00>bla}
@@ -62,6 +55,7 @@ pass
 
 - look into invalid { } in MSDP / GMCP handling
 
+- MSLP jump link handling
 
 - mapper.c FAST handling
 
@@ -95,6 +89,9 @@ pass
 
 - #daemon attach fails under high cpu load
 
+- https://github.com/scandum/tintin/issues/161
+  Add note to package maintainers
+
 ----------------
   - add shadow session support with access to all events.
 

+ 9 - 0
mods/igr.mods

@@ -1,5 +1,14 @@
 Jan 2024        2.02.42
 ------------------------------------------------------------------------------
+substitute.c    %%%s would get escaped to %%s in aliases and actions. This was
+                changed so only %%%1 gets escaped to %%1, %%%s stays the same.
+
+list.c          Added an error message when using #list add on invalid lists.
+
+map.c           #map info save will save to info[MAP] instead of info[map].
+
+system.c        Fixed a bug limiting #script to 50KB of output.
+
 net.c           Fixed a bug causing #config color_patch to strip all colors.
 
 data.c          Classes are properly cleared when removed with #kill.

+ 29 - 25
src/class.c

@@ -229,40 +229,44 @@ DO_CLASS(class_close)
 {
 	if (node == NULL)
 	{
-		show_message(ses, LIST_CLASS, "#CLASS {%s} DOES NOT EXIST.", arg1);
+		node = search_node_list(ses->list[LIST_CLASS], arg1);
+
+		if (node == NULL)
+		{
+			show_message(ses, LIST_CLASS, "#CLASS {%s} DOES NOT EXIST.", arg1);
+			return ses;
+		}
+	}
+
+	if (atoi(node->arg3) == 0)
+	{
+		show_message(ses, LIST_CLASS, "#CLASS {%s} IS ALREADY CLOSED.", arg1);
 	}
 	else
 	{
-		if (atoi(node->arg3) == 0)
-		{
-			show_message(ses, LIST_CLASS, "#CLASS {%s} IS ALREADY CLOSED.", arg1);
-		}
-		else
-		{
-			show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN CLOSED.", arg1);
+		show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN CLOSED.", arg1);
 
-			update_node_list(ses->list[LIST_CLASS], arg1, "", "0", node->arg4);
+		update_node_list(ses->list[LIST_CLASS], arg1, "", "0", node->arg4);
 
-			if (!strcmp(ses->group, arg1))
-			{
-				check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS DEACTIVATED", ses->group);
-				check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS DEACTIVATED %s", ses->group, ses->group);
+		if (!strcmp(ses->group, arg1))
+		{
+			check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS DEACTIVATED", ses->group);
+			check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS DEACTIVATED %s", ses->group, ses->group);
 
-				node = ses->list[LIST_CLASS]->list[0];
+			node = ses->list[LIST_CLASS]->list[0];
 
-				if (atoi(node->arg3))
-				{
-					RESTRING(ses->group, node->arg1);
+			if (atoi(node->arg3))
+			{
+				RESTRING(ses->group, node->arg1);
 
-					show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN ACTIVATED.", node->arg1);
+				show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN ACTIVATED.", node->arg1);
 
-					check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS ACTIVATED", node->arg1);
-					check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS ACTIVATED %s", arg1, arg1);
-				}
-				else
-				{
-					RESTRING(ses->group, "");
-				}
+				check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS ACTIVATED", node->arg1);
+				check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS ACTIVATED %s", arg1, arg1);
+			}
+			else
+			{
+				RESTRING(ses->group, "");
 			}
 		}
 	}

+ 14 - 9
src/help.c

@@ -1378,7 +1378,7 @@ struct help_type help_table[] =
 		"<278>         The edit command can be used to turn the default line editor into a\n"
 		"<278>         text editor.\n"
 		"\n"
-		"<278>         <178>#edit create <arguments>\n"
+		"<278>         <178>#edit create [name] [arguments]\n"
 		"<278>           Create an editor, initialize using the provided arguments.\n"
 		"\n"
 		"<278>         <178>#edit load <variable>\n"
@@ -1397,7 +1397,7 @@ struct help_type help_table[] =
 		"<278>           Suspend editing, similar to pressing enter except that no\n"
 		"<278>           events are triggered.\n"
 		"\n"
-		"<278>         <178>#edit write <filename\n"
+		"<278>         <178>#edit write [filename]\n"
 		"<278>           Write the editor content to file.\n"
 		"\n"
 		"<178>Example<278>: #edit create {bli}{bla}{blo}\n",
@@ -1625,7 +1625,10 @@ struct help_type help_table[] =
 		"<278>         <178>CLASS_LOAD [CLASS]\n"
 		"<278>           %0 class name\n"
 		"\n"
-
+		"<278>         <128>FORMAT EVENTS\n"
+		"\n"
+		"<278>         <178>REFORMAT <MESSAGE>     <278>Use #return to change MESSAGE\n"
+		"\n"
 		"<278>         <128>GAG EVENTS\n"
 		"\n"
 		"<278>         <178>GAG <EVENT>\n"
@@ -1771,8 +1774,6 @@ struct help_type help_table[] =
 		"<278>         <178>UNKNOWN COMMAND        <278>%0 raw text\n"
 		"<278>         <178>SIGUSR                 <278>%0 signal\n"
 		"\n"
-		"<278>         <178>REFORMAT <MESSAGE>     <278>Use #return to change MESSAGE\n"
-		"\n"
 		"<278>         <128>TELNET EVENTS\n"
 		"\n"
 		"<278>         <178>IAC <EVENT>\n"
@@ -2536,6 +2537,9 @@ struct help_type help_table[] =
 		"<278>         <178>#line background <argument>\n"
 		"<278>           Prevent new session activation.\n"
 		"\n"
+		"<278>         <178>#line benchmark <argument>\n"
+		"<278>           Argument is executed and the elapsed time is reported after.\n"
+		"\n"
 		"<278>         <178>#line capture <variable> <argument>\n"
 		"<278>           Argument is executed and output stored in <variable>.\n"
 		"\n"
@@ -2625,8 +2629,8 @@ struct help_type help_table[] =
 		"<278>         #list {var} {tokenize} <string>        Create a character list\n"
 		"\n"
 		"<278>         The index should be between +1 and the list's size. You can also give\n"
-		"<278>         a negative value, in which case -1 equals the last item in the list, -2\n"
-		"<278>         the second last, etc.\n"
+		"<278>         a negative value, in which case -1 equals the last item in the list,\n"
+		"<278>         -2 the second last, etc.\n"
 		"\n"
 		"<278>         When inserting an item a positive index will prepend the item at the\n"
 		"<278>         given index, while a negative index will append the item.\n"
@@ -2644,7 +2648,7 @@ struct help_type help_table[] =
 		"\n"
 		"<278>         The indexate option prepares a table or list table for order, sort,\n"
 		"<278>         filter, refine, and find operations for the given key. It is similar\n"
-		"<278>         to the SELECT option in SQL.\n"
+		"<278>         to the SELECT option in SQL. The table must have a uniform key layout.\n"
 		"\n"
 		"<278>         A size of 0 is returned for an empty or non-existent list. You can\n"
 		"<278>         directly access the size of a list using &var[].\n"
@@ -3814,7 +3818,7 @@ struct help_type help_table[] =
 		"<278>         you need to use \\e]68;2;\\a, and they instead trigger the SECURE LINK\n"
 		"<278>         event.\n"
 		"\n"
-		"<278>         To creae a link that is not undelined, use \\e]4;24m text \\e]24m.\n"
+		"<278>         To create a link that is not underlined, use \\e]4;24m text \\e]24m.\n"
 		"\n"
 		"<178>Example<278>: #sub {%* tells %*} {\\e]68;2;EXEC;#cursor set tell %1 \\a\\e[4;24m%0\\e[24m}\n"
 		"<178>       <278>  #event {PRESSED SECURE LINK EXEC MOUSE BUTTON ONE} {%4}\n"
@@ -4103,6 +4107,7 @@ struct help_type help_table[] =
 		"<178>      \\W <278>Match non-letters, numbers, and underscores    [^A-Za-z0-9_]\n"
 		"<178>      \\x <278>Insert hex character                           \\x\n"
 		"<178>      \\Z <278>Match end of string                            $\n"
+		"<178>      \\\\ <278>Match a backslash                              \\\\\n"
 		"\n"
 		"<278>         \\s matches one space, \\s+ matches one or multiple spaces, the use\n"
 		"<278>         of {\\s+} is required for this sequence to work in tintin, \\s by"

+ 21 - 2
src/list.c

@@ -190,6 +190,25 @@ DO_ARRAY(array_add)
 		list->root = init_list(ses, LIST_VARIABLE, LIST_SIZE);
 	}
 
+	if (list->root->used)
+	{
+		int numerate = atoi(list->root->list[0]->arg1) == 1 && atoi(list->root->list[list->root->used - 1]->arg1) == list->root->used;
+
+		if (numerate == 0)
+		{
+			for (index = 0 ; index < list->root->used ; index++)
+			{
+				if (atoi(list->root->list[index]->arg1) != index + 1)
+				{
+					break;
+				}
+			}
+			show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} ADD: INVALID LIST. INDEX %d IS SET TO {%s}.", var, index + 1, list->root->list[index]->arg1);
+
+			return ses;
+		}
+	}
+
 	index = list->root->used + 1;
 
 	while (*arg)
@@ -599,7 +618,7 @@ DO_ARRAY(array_indexate)
 			}
 			else
 			{
-				show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} INDEXATE: FAILED TO POPULATE INDEX {%s}.", var, list->root->list[cnt]->arg1);
+				show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} INDEXATE: ABORTED DUE TO INVALID INDEX {%s}.", var, list->root->list[cnt]->arg1);
 				break;
 			}
 		}
@@ -625,7 +644,7 @@ DO_ARRAY(array_indexate)
 			}
 			else
 			{
-				show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} INDEXATE: FAILED TO POPULATE INDEX {%s}.", var, list->root->list[cnt]->arg1);
+				show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} INDEXATE: ABORTED DUE TO INVALID INDEX {%s}.", var, list->root->list[cnt]->arg1);
 				break;
 			}
 		}

+ 16 - 8
src/mapper.c

@@ -367,15 +367,23 @@ struct room_data *create_room(struct session *ses, char *format, ...)
 		newroom->weight = 1;
 	}
 
-	if (newroom->vnum > 0 && newroom->vnum < ses->map->size)
+	if (newroom->vnum <= 0)
+	{
+		return newroom;
+	}
+
+	if (newroom->vnum < ses->map->size)
 	{
 		ses->map->room_list[newroom->vnum] = newroom;
 	}
 
-	if (!HAS_BIT(ses->map->flags, MAP_FLAG_READ) && newroom->vnum)
+	if (gtd->level->debug || !HAS_BIT(ses->map->flags, MAP_FLAG_READ))
 	{
 		show_message(ses, LIST_PATH, "#MAP CREATE ROOM %5d {%s}.", newroom->vnum, newroom->name);
+	}
 
+	if (!HAS_BIT(ses->map->flags, MAP_FLAG_READ))
+	{
 		check_all_events(ses, EVENT_FLAG_MAP, 0, 2, "MAP CREATE ROOM", ntos(newroom->vnum), newroom->name);
 	}
 
@@ -6554,9 +6562,9 @@ DO_MAP(map_info)
 
 	if (is_abbrev(arg1, "SAVE"))
 	{
-		set_nest_node_ses(ses, "info[map]", "{DIRECTION}{%d}", ses->map->dir);
-		add_nest_node_ses(ses, "info[map]", "{EXITS}{%d}", exits);
-		add_nest_node_ses(ses, "info[map]", "{FLAGS}{{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}}",
+		set_nest_node_ses(ses, "info[MAP]", "{DIRECTION}{%d}", ses->map->dir);
+		add_nest_node_ses(ses, "info[MAP]", "{EXITS}{%d}", exits);
+		add_nest_node_ses(ses, "info[MAP]", "{FLAGS}{{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}{%s}{%d}}",
 			"ASCIIGRAPHICS", HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS) != 0,
 			"ASCIILENGTH", HAS_BIT(ses->map->flags, MAP_FLAG_ASCIILENGTH) != 0,
 			"ASCIIVNUMS", HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS) != 0,
@@ -6570,9 +6578,9 @@ DO_MAP(map_info)
 			"SYMBOLGRAPHICS", HAS_BIT(ses->map->flags, MAP_FLAG_SYMBOLGRAPHICS) != 0,
 			"TERRAIN", HAS_BIT(ses->map->flags, MAP_FLAG_TERRAIN) != 0,
 			"UNICODEGRAPHICS", HAS_BIT(ses->map->flags, MAP_FLAG_UNICODEGRAPHICS) != 0);
-		add_nest_node_ses(ses, "info[map]", "{LAST_ROOM}{%d}", ses->map->last_room);
-		add_nest_node_ses(ses, "info[map]", "{ROOMS}{%d}", cnt);
-		add_nest_node_ses(ses, "info[map]", "{ROOMS_MAX}{%d}", ses->map->size);
+		add_nest_node_ses(ses, "info[MAP]", "{LAST_ROOM}{%d}", ses->map->last_room);
+		add_nest_node_ses(ses, "info[MAP]", "{ROOMS}{%d}", cnt);
+		add_nest_node_ses(ses, "info[MAP]", "{ROOMS_MAX}{%d}", ses->map->size);
 
 		return;
 	}

+ 13 - 13
src/net.c

@@ -440,7 +440,7 @@ int detect_prompt(struct session *ses, char *original)
 void readmud(struct session *ses)
 {
 	char *line, *next_line/*, *strip*/;
-	char linebuf[BUFFER_SIZE];
+	char linebuf[STRING_SIZE];
 	int len;
 	struct session *cts;
 
@@ -574,7 +574,7 @@ void readmud(struct session *ses)
 		}
 		gtd->mud_output_line = linebuf;
 
-		process_mud_output(ses, linebuf, next_line == NULL);
+		process_one_line(ses, linebuf, next_line == NULL);
 
 		gtd->mud_output_line = gtd->mud_output_buf + gtd->mud_output_len;
 	}
@@ -623,7 +623,7 @@ void process_more_output(struct session *ses, char *append, int prompt)
 	str_cpy(&ses->more_output, "");
 	ses->check_output = 0;
 
-	process_mud_output(ses, line, prompt);
+	process_one_line(ses, line, prompt);
 
 	if (readmud == 0)
 	{
@@ -636,19 +636,19 @@ void process_more_output(struct session *ses, char *append, int prompt)
 	}
 }
 
-void process_mud_output(struct session *ses, char *linebuf, int prompt)
+void process_one_line(struct session *ses, char *linebuf, int prompt)
 {
-	char line[STRING_SIZE], temp[STRING_SIZE];
+	char temp[STRING_SIZE];
 	int str_len, raw_len;
 
-	push_call("process_mud_output(%p,%p,%d)",ses,linebuf,prompt);
+	push_call("process_one_line(%p,%p,%d)",ses,linebuf,prompt);
 
 	raw_len = strlen(linebuf);
-	str_len = strip_vt102_codes(linebuf, line);
+	str_len = strip_vt102_codes(linebuf, temp);
 
-	check_all_events(ses, SUB_SEC|EVENT_FLAG_OUTPUT, 0, 2, "RECEIVED LINE", linebuf, line);
+	check_all_events(ses, SUB_SEC|EVENT_FLAG_OUTPUT, 0, 2, "RECEIVED LINE", linebuf, temp);
 
-	if (check_all_events(ses, SUB_SEC|EVENT_FLAG_CATCH, 0, 2, "CATCH RECEIVED LINE", linebuf, line))
+	if (check_all_events(ses, SUB_SEC|EVENT_FLAG_CATCH, 0, 2, "CATCH RECEIVED LINE", linebuf, temp))
 	{
 		pop_call();
 		return;
@@ -656,9 +656,9 @@ void process_mud_output(struct session *ses, char *linebuf, int prompt)
 
 	if (str_len && prompt)
 	{
-		check_all_events(ses, SUB_SEC|EVENT_FLAG_OUTPUT, 0, 4, "RECEIVED PROMPT", linebuf, line, ntos(raw_len), ntos(str_len));
+		check_all_events(ses, SUB_SEC|EVENT_FLAG_OUTPUT, 0, 4, "RECEIVED PROMPT", linebuf, temp, ntos(raw_len), ntos(str_len));
 
-		if (check_all_events(ses, SUB_SEC|EVENT_FLAG_CATCH, 0, 4, "CATCH RECEIVED PROMPT", linebuf, line, ntos(raw_len), ntos(str_len)))
+		if (check_all_events(ses, SUB_SEC|EVENT_FLAG_CATCH, 0, 4, "CATCH RECEIVED PROMPT", linebuf, temp, ntos(raw_len), ntos(str_len)))
 		{
 			pop_call();
 			return;
@@ -667,11 +667,11 @@ void process_mud_output(struct session *ses, char *linebuf, int prompt)
 
 	if (HAS_BIT(ses->config_flags, CONFIG_FLAG_COLORPATCH))
 	{
-		sprintf(line, "%s%s%s", ses->color_patch, linebuf, "\e[0m");
+		sprintf(temp, "%s%s%s", ses->color_patch, linebuf, "\e[0m");
 
 		get_color_codes(ses->color_patch, linebuf, ses->color_patch, GET_ALL);
 
-		linebuf = line;
+		strcpy(linebuf, temp);
 	}
 
 	check_one_line(ses, linebuf);   /* changes linebuf */

+ 25 - 32
src/regex.c

@@ -252,23 +252,14 @@ int get_regex_range(char *in, char *out, int *var, int *arg)
 	pti = in;
 	ptr = range;
 
-	switch (*pti)
+	if (in[-2] != '!')
 	{
-		case '0':
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-		case '8':
-		case '9':
-			*ptr++ = *pti++;
-			break;
+		*pto++ = '(';
+	}
 
-		default:
-			goto end;
+	if (*pti < '0' || *pti > '9')
+	{
+		goto end;
 	}
 
 	while (*pti)
@@ -302,46 +293,46 @@ int get_regex_range(char *in, char *out, int *var, int *arg)
 				continue;
 
 			case 'a':
-				pto += sprintf(pto, "%s", "([^\\0]");
+				pto += sprintf(pto, "%s", "[^\\0]");
 				break;
 			case 'A':
-				pto += sprintf(pto, "%s", "(\\n");
+				pto += sprintf(pto, "%s", "\\n");
 				break;
 			case 'c':
-				pto += sprintf(pto, "%s", "((?:\\e\\[[0-9;]*m)");
+				pto += sprintf(pto, "%s", "(?:\\e\\[[0-9;]*m)");
 				break;
 			case 'd':
-				pto += sprintf(pto, "%s", "([0-9]");
+				pto += sprintf(pto, "%s", "[0-9]");
 				break;
 			case 'D':
-				pto += sprintf(pto, "%s", "([^0-9]");
+				pto += sprintf(pto, "%s", "[^0-9]");
 				break;
 			case 'p':
-				pto += sprintf(pto, "%s", "([\\x20-\\xfe]");
+				pto += sprintf(pto, "%s", "[\\x20-\\xfe]");
 				break;
 			case 'P':
-				pto += sprintf(pto, "%s", "([^\\x20-\\xfe]");
+				pto += sprintf(pto, "%s", "[^\\x20-\\xfe]");
 				break;
 			case 's':
-				pto += sprintf(pto, "%s", "(\\s");
+				pto += sprintf(pto, "%s", "\\s");
 				break;
 			case 'S':
-				pto += sprintf(pto, "%s", "(\\S");
+				pto += sprintf(pto, "%s", "\\S");
 				break;
 			case 'u':
-				pto += sprintf(pto, "%s", "((?:[\\x00-\\x7F]|[\\xC0-\\xF4][\\x80-\\xC0]{1,3})");
+				pto += sprintf(pto, "%s", "(?:[\\x00-\\x7F]|[\\xC0-\\xF4][\\x80-\\xC0]{1,3})");
 				break;
 			case 'U':
-				pto += sprintf(pto, "%s", "([\\xF5-\\xFF]");
+				pto += sprintf(pto, "%s", "[\\xF5-\\xFF]");
 				break;
 			case 'w':
-				pto += sprintf(pto, "%s", "(\\w");
+				pto += sprintf(pto, "%s", "\\w");
 				break;
 			case 'W':
-				pto += sprintf(pto, "%s", "(\\W");
+				pto += sprintf(pto, "%s", "\\W");
 				break;
 			case '*':
-				pto += sprintf(pto, "%s", "(.");
+				pto += sprintf(pto, "%s", ".");
 				break;
 
 			default:
@@ -350,7 +341,7 @@ int get_regex_range(char *in, char *out, int *var, int *arg)
 		*ptr = 0;
 		pti++;
 
-		pto += sprintf(pto, "{%s}%s", range, *pti ? "?)" : ")");
+		pto += sprintf(pto, "{%s}%s%s", range, *pti ? "?" : "", in[-2] != '!' ? ")" : "");
 
 		return pti - in;
 	}
@@ -360,7 +351,8 @@ int get_regex_range(char *in, char *out, int *var, int *arg)
 	{
 		gtd->args[next_arg(*var)] = next_arg(*arg);
 	}*/
-	strcpy(out, *pti ? "(.+?)" : "(.+)");
+
+	pto += sprintf(pto, "%s%s", *in ? ".+?" : ".+", in[-2] != '!' ? ")" : "");
 
 	return 0;
 }
@@ -789,7 +781,7 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 								break;
 
 							case '+':
-								pti += 3 + get_regex_range(&pti[3], pto, NULL, NULL);
+								pti += 3 + get_regex_range(pti + 3, pto, NULL, NULL);
 								pto += strlen(pto);
 								break;
 
@@ -1138,6 +1130,7 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 
 							case '+':
 								pti += 3 + get_regex_range(&pti[3], pto, NULL, NULL);
+								pto += strlen(pto);
 								break;
 
 							case '.':

+ 1 - 1
src/scan.c

@@ -591,7 +591,7 @@ DO_SCAN(scan_txt)
 		}
 		line[BUFFER_SIZE / 2] = 0;
 
-		process_mud_output(ses, line, FALSE);
+		process_one_line(ses, line, FALSE);
 
 		if (HAS_BIT(ses->flags, SES_FLAG_SCANABORT))
 		{

+ 6 - 6
src/show.c

@@ -157,7 +157,7 @@ void show_message(struct session *ses, int index, char *format, ...)
 
 	display:
 
-	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_SYSTEM, 1, 0, "REFORMAT %s", format))
+	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_REFORMAT, 1, 0, "REFORMAT %s", format))
 	{
 		format = get_variable_def(ses, "result", format);
 	}
@@ -216,7 +216,7 @@ void show_error(struct session *ses, int index, char *format, ...)
 
 	push_call("show_error(%p,%p,%p)",ses,index,format);
 
-	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_SYSTEM, 1, 0, "REFORMAT %s", format))
+	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_REFORMAT, 1, 0, "REFORMAT %s", format))
 	{
 		format = get_variable_def(ses, "result", format);
 	}
@@ -288,7 +288,7 @@ void show_debug(struct session *ses, int index, char *format, ...)
 		return;
 	}
 
-	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_SYSTEM, 1, 0, "REFORMAT %s", format))
+	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_REFORMAT, 1, 0, "REFORMAT %s", format))
 	{
 		format = get_variable_def(ses, "result", format);
 	}
@@ -451,7 +451,7 @@ void tintin_header(struct session *ses, int width, char *format, ...)
 		return;
 	}
 
-	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_SYSTEM, 1, 0, "REFORMAT %s", format))
+	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_REFORMAT, 1, 0, "REFORMAT %s", format))
 	{
 		format = get_variable_def(ses, "result", format);
 	}
@@ -500,7 +500,7 @@ void tintin_printf(struct session *ses, char *format, ...)
 
 	push_call("tintin_printf(%p,%p,...)",ses,format);
 
-	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_SYSTEM, 1, 0, "REFORMAT %s", format))
+	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_REFORMAT, 1, 0, "REFORMAT %s", format))
 	{
 		format = get_variable_def(ses, "result", format);
 	}
@@ -524,7 +524,7 @@ void tintin_printf2(struct session *ses, char *format, ...)
 
 	push_call("tintin_printf2(%p,%p,...)",ses,format);
 
-	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_SYSTEM, 1, 0, "REFORMAT %s", format))
+	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_REFORMAT, 1, 0, "REFORMAT %s", format))
 	{
 		format = get_variable_def(ses, "result", format);
 	}

+ 8 - 1
src/substitute.c

@@ -1621,7 +1621,14 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 						{
 							*pto++ = *pti++;
 						}
-						pti++;
+						if (is_digit(pti[1]))
+						{
+							pti++;
+						}
+						else
+						{
+							*pto++ = *pti++;
+						}
 					}
 					else
 					{

+ 3 - 5
src/system.c

@@ -95,7 +95,7 @@ DO_COMMAND(do_run)
 
 DO_COMMAND(do_script)
 {
-	char *cptr, buf[BUFFER_SIZE], var[BUFFER_SIZE], tmp[BUFFER_SIZE];
+	char *cptr, buf[BUFFER_SIZE], tmp[BUFFER_SIZE];
 	FILE *script;
 	int index;
 
@@ -139,7 +139,7 @@ DO_COMMAND(do_script)
 
 		if (script)
 		{
-			var[0] = 0;
+			set_nest_node_ses(ses, arg1, "");
 
 			while (fgets(buf, BUFFER_SIZE - 1, script))
 			{
@@ -152,11 +152,9 @@ DO_COMMAND(do_script)
 
 				substitute(ses, buf, tmp, SUB_SEC);
 
-				cat_sprintf(var, "{%d}{%s}", index++, tmp);
+				add_nest_node_ses(ses, arg1, "{%d}{%s}", index++, tmp);
 			}
 
-			set_nest_node_ses(ses, arg1, "%s", var);
-
 			pclose(script);
 		}
 		else

+ 1 - 1
src/tintin.h

@@ -2518,7 +2518,7 @@ extern void write_line_mud(struct session *ses, char *line, int size);
 extern int read_buffer_mud(struct session *ses);
 extern void readmud(struct session *ses);
 extern void process_more_output(struct session *ses, char *append, int prompt);
-extern void process_mud_output(struct session *ses, char *linebuf, int prompt);
+extern void process_one_line(struct session *ses, char *linebuf, int prompt);
 
 #endif
 

+ 12 - 7
src/validate

@@ -1,11 +1,11 @@
 #!./tt++ -G
 
-#nop   1: #math
-#nop   2: #line
-#nop   3: #return
-#nop   4: #buffer
-#nop   5: #switch
-#nop   6: #class
+#0   1: #math
+#0   2: #line
+#0   3: #return
+#0   4: #buffer
+#0   5: #switch
+#0   6: #class
 
 
 #line sub arg #var arg {%0}
@@ -510,7 +510,12 @@ sethash blo hello
 
 #regex {blibla} {%10bli%+3..3a} {#if {"&11" !== "bla"} {error 34.1: regex argument indexing (&11)}}
 #regex {blibla} {%.%+%.%*}      {#if {"&4" !== "bla"}  {error 34.2: regex argument indexing (&4)}}
-#regex {blibla} {%99bli%+3..3*}      {#if {"&99" !== "bla"} {error 34.3: regex argument indexing (&99)}}
+#regex {blibla} {%99bli%+3..3*} {#if {"&99" !== "bla"} {error 34.3: regex argument indexing (&99)}}
+#regex {blibla} {bli%!+}        {#if {"&1" !== ""}     {error 34.4: regex argument indexing (&1)}}
+#regex {blibla} {%+2*%+3*}      {#if {"&2" !== "ibl"}  {error 34.5: regex argument indexing (&2)}}
+#regex {blibla} {%+1..2*}       {#if {"&1" !== "bl"}   {error 34.6: regex argument indexing (&1)}}
+#regex {blibla} {%!+5*%*}       {#if {"&1" !== "a"}    {error 34.7: regex argument indexing (&1)}}
+#regex {blibla} {%+%*}          {#if {"&1" !== "b"}    {error 34.8: regex argument indexing (&1)}}
 
 #0 )=-=( ERROR 35 )=-=( 0#