unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: fabrice nicol <fabrnicol@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 47408@debbugs.gnu.org
Subject: bug#47408: [PATCH] Etags support for Mercury -- fix explicit tags for existentially-quantified procedures
Date: Mon, 14 Jun 2021 20:52:54 +0200	[thread overview]
Message-ID: <c5544bb0-9f8e-e432-d73d-708a29d6a917@gmail.com> (raw)
In-Reply-To: <83eed45omq.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 1518 bytes --]

Agreed. (But you may have more systematically explicit tags because of 
this condition 2.)

The attached patch was tested, builds and runs OK. Replaces the former 
one, is you stick to the option of modifying 's' by reference rather 
than creating a copy.

Note: Prolog has a much simpler naming pattern, so differences are 
normal. No need for explicit tagging in Prolog, see the call to 
'make_tag' in Prolog support.

Fabrice

Le 14/06/2021 à 19:42, Eli Zaretskii a écrit :
>> Cc: 47408@debbugs.gnu.org, pot@gnu.org
>> From: fabrice nicol <fabrnicol@gmail.com>
>> Date: Mon, 14 Jun 2021 19:10:53 +0200
>>
>> If you take a look at other languages that implement explicit tags (like
>> Fortran) you will see that there are buffers coming in to avoid having
>> 'name' and 'linestart' (1st and 4th arguments to 'make_tag') share a
>> same string pointer (here 's').
>>
>> This is explained in the header comment to 'make_tag':
>>
>> " 2. LINESTART contains name as either a rightmost, or rightmost but
>>    *     one character, substring;"
> This is just a condition for generating "implicitly named" tags.
> There's nothing wrong with having explicitly named tags, if there are
> good reasons for that.
>
>> When I applied you suggestion and tested, the TAGS base was as expected
>> accordingly: wrong.
> "Wrong" in what sense?  Can you show an example of such a wrong tag?
> And how does Mercury differ from Prolog in this sense? prolog_pr
> doesn't allocate new strings before calling make_tag.
>
> Thanks.

[-- Attachment #2: 0001-Fix-explicit-tag-issue-with-Mercury-etags-ctags-supp-v2.patch --]
[-- Type: text/x-patch, Size: 7154 bytes --]

From 882ba6a0f51a95893cac798c721e3ccd4ad4e0f6 Mon Sep 17 00:00:00 2001
From: Fabrice Nicol <fabrnicol@gmail.com>
Date: Mon, 14 Jun 2021 14:30:54 +0200
Subject: [PATCH] Fix explicit tag issue with Mercury etags/ctags support

Redesign of prior fix, which did not handle type quantifiers.
Fix omission of single-word declarations like ':- interface.'
* lib-src/etags.c (mercury_pr): Pass the newly corrected NAME
    and NAMELEN arguments to 'make_tag'.
---
 lib-src/etags.c | 110 ++++++++++++++++++++++++++++++------------------
 1 file changed, 69 insertions(+), 41 deletions(-)

diff --git a/lib-src/etags.c b/lib-src/etags.c
index 9f20e44caf..370e825111 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -6081,10 +6081,10 @@ prolog_atom (char *s, size_t pos)
 	      pos++;
 	      if (s[pos] != '\'')
 		break;
-	      pos++;		/* A double quote */
+	      pos++;		/* A double quote  */
 	    }
 	  else if (s[pos] == '\0')
-	    /* Multiline quoted atoms are ignored. */
+	    /* Multiline quoted atoms are ignored.  */
 	    return 0;
 	  else if (s[pos] == '\\')
 	    {
@@ -6119,6 +6119,13 @@ prolog_atom (char *s, size_t pos)
 static bool is_mercury_type = false;
 static bool is_mercury_quantifier = false;
 static bool is_mercury_declaration = false;
+typedef struct
+{
+  size_t pos;          /* Position reached in parsing tag name.  */
+  size_t namelength;   /* Length of tag name  */
+  size_t totlength;    /* Total length of parsed tag: this field is currently
+			  reserved for control and debugging.   */
+} mercury_pos_t;
 
 /*
  * Objective-C and Mercury have identical file extension .m.
@@ -6374,10 +6381,12 @@ mercury_skip_comment (linebuffer *plb, FILE *inf)
   "initialise", "finalise", "mutable", "module", "interface", "implementation",
   "import_module", "use_module", "include_module", "end_module", "some", "all"};
 
-static size_t
+static mercury_pos_t
 mercury_decl (char *s, size_t pos)
 {
-  if (s == NULL) return 0;
+  mercury_pos_t null_pos = {0, 0, 0};
+
+  if (s == NULL) return null_pos;
 
   size_t origpos;
   origpos = pos;
@@ -6398,7 +6407,8 @@ mercury_decl (char *s, size_t pos)
   if (is_mercury_quantifier)
     {
       if (strcmp (buf, "pred") != 0 && strcmp (buf, "func") != 0) /* Bad syntax.  */
-	return 0;
+	return null_pos;
+
       is_mercury_quantifier = false; /* Reset to base value.  */
       found_decl_tag = true;
     }
@@ -6418,7 +6428,7 @@ mercury_decl (char *s, size_t pos)
 		  is_mercury_quantifier = true;
 		}
 
-	      break;  /* Found declaration tag of rank j. */
+	      break;  /* Found declaration tag of rank j.  */
 	    }
 	  else
 	    /* 'solver type' has a blank in the middle,
@@ -6461,11 +6471,13 @@ mercury_decl (char *s, size_t pos)
       if (found_decl_tag)
 	pos = skip_spaces (s + pos) - s; /* Skip len blanks again.  */
       else
-	return 0;
+	return null_pos;
     }
 
   /* From now on it is the same as for Prolog except for module dots.  */
 
+  size_t start_of_name = pos;
+
   if (c_islower (s[pos]) || s[pos] == '_' )
     {
       /* The name is unquoted.
@@ -6478,7 +6490,8 @@ mercury_decl (char *s, size_t pos)
                  && (c_isalnum (s[pos + 1]) || s[pos + 1] == '_')))
 	++pos;
 
-      return pos - origpos;
+      mercury_pos_t position = {pos, pos - start_of_name + 1, pos - origpos};
+      return position;
     }
   else if (s[pos] == '\'')
     {
@@ -6493,28 +6506,37 @@ mercury_decl (char *s, size_t pos)
 	      ++pos; /* A double quote.  */
 	    }
 	  else if (s[pos] == '\0')  /* Multiline quoted atoms are ignored.  */
-	    return 0;
+	    return null_pos;
 	  else if (s[pos] == '\\')
 	    {
 	      if (s[pos+1] == '\0')
-		return 0;
+		return null_pos;
 	      pos += 2;
 	    }
 	  else
 	    ++pos;
 	}
-      return pos - origpos;
+
+      mercury_pos_t position = {pos, pos - start_of_name + 1, pos - origpos};
+      return position;
     }
   else if (is_mercury_quantifier && s[pos] == '[')   /* :- some [T] pred/func.  */
     {
       for (++pos; s + pos != NULL && s[pos] != ']'; ++pos) {}
-      if (s + pos == NULL) return 0;
+      if (s + pos == NULL) return null_pos;
       ++pos;
       pos = skip_spaces (s + pos) - s;
-      return mercury_decl (s, pos) + pos - origpos;
+      mercury_pos_t position = mercury_decl (s, pos);
+      position.totlength += pos - origpos;
+      return position;
+    }
+  else if (s[pos] == '.')  /* as in ':- interface.'  */
+    {
+      mercury_pos_t position = {pos, pos - origpos + 1, pos - origpos};
+      return position;
     }
   else
-    return 0;
+    return null_pos;
 }
 
 static ptrdiff_t
@@ -6523,6 +6545,7 @@ mercury_pr (char *s, char *last, ptrdiff_t lastlen)
   size_t len0 = 0;
   is_mercury_type = false;
   is_mercury_quantifier = false;
+  bool stop_at_rule = false;
 
   if (is_mercury_declaration)
     {
@@ -6530,38 +6553,43 @@ mercury_pr (char *s, char *last, ptrdiff_t lastlen)
       len0 = skip_spaces (s + 2) - s;
     }
 
-  size_t len = mercury_decl (s, len0);
-  if (len == 0) return 0;
-  len += len0;
+  mercury_pos_t position = mercury_decl (s, len0);
+  size_t pos = position.pos;
+  int offset = 0;  /* may be < 0  */
+  if (pos == 0) return 0;
 
-  if (( (s[len] == '.'  /* This is a statement dot, not a module dot.  */
-	 || (s[len] == '(' && (len += 1))
-         || (s[len] == ':'  /* Stopping in case of a rule.  */
-	     && s[len + 1] == '-'
-	     && (len += 2)))
-	&& (lastlen != len || memcmp (s, last, len) != 0)
+  /* Skip white space for rules in definitions before :-
+     and possibly multiline type definitions  */
+
+  while (c_isspace (s[pos])) { ++pos; ++offset; }
+
+  if (( ((s[pos] == '.' && (pos += 1))     /* case 1
+                                              This is a statement dot,
+                                              not a module dot.  */
+	 || (s[pos] == '(' && (pos += 1))  /* case 2  */
+	 || ((s[pos] == ':')               /* case 3  */
+	     && s[pos + 1] == '-' && (stop_at_rule = true)))
+	     && (lastlen != pos || memcmp (s, last, pos) != 0)
 	)
       /* Types are often declared on several lines so keeping just
 	 the first line.  */
-      || is_mercury_type)
+
+      || is_mercury_type)  /* When types are implemented.  */
     {
-      char *name = skip_non_spaces (s + len0);
-      size_t namelen;
-      if (name >= s + len)
-	{
-	  name = s;
-	  namelen = len;
-	}
-      else
-	{
-	  name = skip_spaces (name);
-	  namelen = len - (name - s);
-	}
-      /* Remove trailing non-name characters.  */
-      while (namelen > 0 && notinname (name[namelen - 1]))
-	namelen--;
-      make_tag (name, namelen, true, s, len, lineno, linecharno);
-      return len;
+      size_t namelength = position.namelength;
+      if (stop_at_rule && offset) --offset;
+
+      /* Left-trim type definitions.  */
+
+      while (pos > namelength + offset
+	     && c_isspace (s[pos - namelength - offset]))
+	--offset;
+
+      /* There is no need to correct namelength or call notinname.  */
+      s[pos - offset - 1] = '\0';
+
+      make_tag (s + pos - namelength - offset, namelength, true, s, pos, lineno, linecharno);
+      return pos;
     }
 
   return 0;
-- 
2.31.1


  reply	other threads:[~2021-06-14 18:52 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <mailman.12421.1623412982.2554.bug-gnu-emacs@gnu.org>
2021-06-14 15:10 ` bug#47408: [PATCH] Etags support for Mercury -- fix explicit tags for existentially-quantified procedures fabrice nicol
2021-06-14 16:04   ` Eli Zaretskii
2021-06-14 17:10     ` fabrice nicol
2021-06-14 17:42       ` Eli Zaretskii
2021-06-14 18:52         ` fabrice nicol [this message]
2021-06-17 10:50           ` Eli Zaretskii
2021-06-17 11:19             ` Fabrice Nicol
2021-06-17 11:42               ` Eli Zaretskii
2021-06-17 18:36                 ` fabrice nicol
2021-06-18 11:29                   ` Eli Zaretskii
2021-06-18 11:54                     ` Francesco Potortì
2021-06-18 12:33                       ` Eli Zaretskii
2021-06-18 13:53                         ` fabrice nicol

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c5544bb0-9f8e-e432-d73d-708a29d6a917@gmail.com \
    --to=fabrnicol@gmail.com \
    --cc=47408@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).