[m-rev.] diff: fix infinite loop in mtags

Zoltan Somogyi zs at cs.mu.OZ.AU
Wed Oct 5 09:50:00 AEST 2005


tools/mtags:
	Fix an infinite loop that occurs in some certain rare circumstances.

	Convert to four-space indentation.

Zoltan.

cvs diff: Diffing .
Index: mtags
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/mtags,v
retrieving revision 1.34
diff -u -b -r1.34 mtags
--- mtags	24 Nov 2003 11:05:18 -0000	1.34
+++ mtags	30 Sep 2005 18:08:22 -0000
@@ -1,4 +1,6 @@
 
+# vim: ts=4 sw=4 et
+#
 # Leave the first line of this file blank!
 # This is a Perl script; the following two lines allow us to avoid
 # embedding the path of the perl interpreter in the script.
@@ -225,7 +227,7 @@
 #---------------------------------------------------------------------------#
 
 sub output_name() {
-	# figure out the part of the body that is the name
+    # Figure out the part of the body that is the name.
 
 	$name =~ s/^[ \t]*//;
 
@@ -242,19 +244,18 @@
 	$match_line =~ s|\\|\\\\|g;   # replace `\' with `\\'
 	$match_line =~ s|/|\\/|g;     # replace `/' with `\/'
 
-	# $src_name holds the name as it was in the original source
+    # $src_name holds the name as it was in the original source.
 	$src_name = $name;
 	$name =~ s|\.|__|g;     # replace `.' module qualifiers with `__'
 
-	# output a tag for the fully-qualified name
+    # Output a tag for the fully-qualified name.
 	if (substr($name, 0, length($module)) ne $module) {
 		$name = "${module}__$name";
 	}
 	output_single_name();
 
-	# strip off the leading module qualifiers one by one,
-	# and output a tag for each partially qualified
-	# or unqualified name
+    # Strip off the leading module qualifiers one by one, and output a tag
+    # for each partially qualified or unqualified name.
 	while ($name =~ /__/) {
 		$name =~ s/[^_]*(_[^_]+)*__//;
 		output_single_name();
@@ -288,12 +289,10 @@
 	    }
 	} else {
 	    if ($emacs) {
-		printf OUT "%s\177%s\001%d,%d\n",
-		    $_, $name, $., $.;
+            printf OUT "%s\177%s\001%d,%d\n", $_, $name, $., $.;
 	    } else {
 	    	# Output basic tag line for vi/vim/elvis.
-	    	printf OUT "%s\t%s\t/^%s\$/",
-		    $name, $file, $match_line;
+            printf OUT "%s\t%s\t/^%s\$/", $name, $file, $match_line;
 
 		# Output commands to alter the search buffer.
 		if ($search_definitions) {
@@ -357,13 +356,13 @@
     }
     
     $module = $file;
-    $module =~ s/.*\///;	# delete the directory name, if any
-    $module =~ s/\.m$//;	# delete the trailing `.m'
-    $module =~ s/\./__/;	# replace `.' module qualifiers with `__'
+    $module =~ s/.*\///;    # Delete the directory name, if any.
+    $module =~ s/\.m$//;    # Delete the trailing `.m'.
+    $module =~ s/\./__/;    # Replace `.' module qualifiers with `__'.
 
     while ($_ = <SRCFILE>)
     {
-	# skip lines which are not declarations
+        # Skip lines which are not declarations.
 	next unless ($_ =~ /^:- /);
 
 	chop;
@@ -387,8 +386,7 @@
 	# typeclass or instance declarations.
 	# Also skip instance declarations if we're producing a normal vi
 	# tags file since vi doesn't allow duplicate tags and the
-	# typeclass tags are probably more important than the instance
-	# tags.
+        # typeclass tags are probably more important than the instance tags.
 	next unless (
 	    $decl eq "pred" ||
 	    $decl eq "func" ||
@@ -399,15 +397,15 @@
 	    ($decl eq "instance" && $keep_dups)
 	);
 
-	# skip declarations which are not definitions
+        # Skip declarations which are not definitions.
 	next unless (
-	    # pred, func, and typeclass declarations are always definitions
+            # Pred, func, and typeclass declarations are always definitions.
 	    $decl eq "pred" ||
 	    $decl eq "func" ||
 	    $decl eq "typeclass" ||
 
-	    # if it doesn't end in a `.' (i.e if it doesn't fit on one line),
-	    # then it's probably a definition
+            # If it doesn't end in a `.' (i.e if it doesn't fit on one line),
+            # then it's probably a definition.
 	    ($body !~ /\.[ \t]*$/ && $body !~ /\.[ \t]*%.*$/) ||
 
 	    # if it contains `--->', `=', or `::', it's probably a
@@ -425,33 +423,33 @@
 	if ($kind eq "instance") { $kind = "tci"; }
 	output_name();
 	
-	# for everything except type, typeclass and instance declarations,
-	# we're done
+        # For everything except type, typeclass and instance declarations,
+        # we're done.
 	next unless ($decl eq "type" || $decl eq "typeclass" || 
 			$decl eq "instance");
 
 	if ($decl eq "type") {
-	    # make sure we're at the line with the `--->'
+            # Make sure we're at the line with the `--->'.
 	    if ($body !~ /--->/) {
 		    next if $_ =~ /\.[ \t]*$/ || $_ =~ /\.[ \t]*%.*$/;
 		    $_ = <SRCFILE>;
 		    chop;
 		    $body = $_;
 	    }
+
 	    next unless ($body =~ /--->/);
 
-	    # replace everything up to the `--->' with `;'
+            # Replace everything up to the `--->' with `;'.
 	    $body =~ s/.*--->/;/;
 
 	    for(;;) {
-		# if the body starts with `;', we assume it must be the
-		# start of a constructor definition
+                # If the body starts with `;', we assume it must be the start
+                # of a constructor definition.
 		if ($body =~ /^[ \t]*;/) {
-
 		    # delete the leading `;'
 		    $body =~ s/[^;]*;[ \t]*//;
 
-		    # skip blank lines and comments
+                    # Skip blank lines and comments.
 		    while ($body =~ /^[ \t]*$/ || $body =~ /^[ \t]*%.*$/) {
 			$_ = <SRCFILE> || last;
 			chop;
@@ -467,26 +465,33 @@
 		    $name = $body;
 		    $name =~ s/[ \t;.%].*//;
 		    $kind = "cons";
+
 		    output_name();
 
 		    # Look for field names on the same line as the
-		    # constructor name
-		    while ($body =~ /([a-z][_a-zA-Z0-9]*)[ \t]*::/) {
+                    # constructor name. Don't allow the line to start with
+                    # a colon, because then the assignment
+                    #
+                    # $body =~ s/^[^:]*:://;
+                    #
+                    # below may leave $body unchanged, leading to an infinite
+                    # loop.
+                    while ($body =~ /^[^:].*([a-z][_a-zA-Z0-9]*)[ \t]*::/) {
 		    	$name = $1;
 			$kind = "fld";
 			output_name();
 			$body =~ s/^[^:]*:://;
 		    }
 
-		    # if there are more constructor definitions on the
-		    # same line, process the next one
+                    # If there are more constructor definitions on the
+                    # same line, process the next one.
 		    if ($body =~ /;/) {
 			    $body =~ s/[^;]*;/;/;
 			    next;
 		    }
 		} else {
-		    # Look for field names that are not on the
-		    # same line as the constructor name
+                    # Look for field names that are not on the same line
+                    # as the constructor name.
 		    while ($body =~ /([a-z][_a-zA-Z0-9]*)[ \t]*::/) {
 			$name = $1;
 			$kind = "fld";
@@ -501,9 +506,7 @@
 		$body = $_;
 	    }
 	} elsif ($decl eq "typeclass") {
-
 	    for(;;) {
-
 		# Assume each method declaration starts on a new line.
 		if ($body =~ /^.*\b(pred|func)[ \t]*/) {
 		    $body =~ s/^.*\b(pred|func)[ \t]*//;
@@ -528,7 +531,6 @@
 	    }
 	} else { # instance declaration
 	    for(;;) {
-
 		# Assume each method declaration starts on a new line.
 		if ($body =~ /^.*\b(pred\(|func\()/) {
 		    $body =~ s/.*\b(pred\(|func\()//;
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list