aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorFabrice Nicol2021-06-17 19:59:52 +0200
committerEli Zaretskii2021-06-18 14:18:34 +0300
commit0ffcf7479c49ad5e0f9f675124c7cf741197aedd (patch)
tree4a630b074ae5485677a23fe764f613fb16c582f3 /lib-src
parentbc44763b8342ee9e1bf43ffb202c73fee5ba0bf6 (diff)
downloademacs-0ffcf7479c49ad5e0f9f675124c7cf741197aedd.tar.gz
emacs-0ffcf7479c49ad5e0f9f675124c7cf741197aedd.zip
Fix Mercury support, notably qualified procedures.
Correct the previous fix (did not correctly handle qualified types). Also fix the following issues: - remove module name (+ dot) from tags, as prefixing module name is often inconsistent in code and may cause tags to be too specific. - now tag 0-arity predicates and functions (':- func foo_14.') - now tag one-word declarations (':- interface.') * lib-src/etags.c (mercury_pr): Pass the correct NAME and NAMELEN arguments to 'make_tag'. (mercury_decl): Return more information about the declaration or definition it finds. This allows mercury_pr to be smarter. (Bug#47408)
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c126
1 files changed, 83 insertions, 43 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 9f20e44caf4..bd57ede2f37 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -6081,10 +6081,10 @@ prolog_atom (char *s, size_t pos)
6081 pos++; 6081 pos++;
6082 if (s[pos] != '\'') 6082 if (s[pos] != '\'')
6083 break; 6083 break;
6084 pos++; /* A double quote */ 6084 pos++; /* A double quote */
6085 } 6085 }
6086 else if (s[pos] == '\0') 6086 else if (s[pos] == '\0')
6087 /* Multiline quoted atoms are ignored. */ 6087 /* Multiline quoted atoms are ignored. */
6088 return 0; 6088 return 0;
6089 else if (s[pos] == '\\') 6089 else if (s[pos] == '\\')
6090 { 6090 {
@@ -6119,6 +6119,13 @@ static void mercury_skip_comment (linebuffer *, FILE *);
6119static bool is_mercury_type = false; 6119static bool is_mercury_type = false;
6120static bool is_mercury_quantifier = false; 6120static bool is_mercury_quantifier = false;
6121static bool is_mercury_declaration = false; 6121static bool is_mercury_declaration = false;
6122typedef struct
6123{
6124 size_t pos; /* Position reached in parsing tag name. */
6125 size_t namelength; /* Length of tag name */
6126 size_t totlength; /* Total length of parsed tag: this field is currently
6127 reserved for control and debugging. */
6128} mercury_pos_t;
6122 6129
6123/* 6130/*
6124 * Objective-C and Mercury have identical file extension .m. 6131 * Objective-C and Mercury have identical file extension .m.
@@ -6374,10 +6381,12 @@ static const char *Mercury_decl_tags[] = {"type", "solver type", "pred",
6374 "initialise", "finalise", "mutable", "module", "interface", "implementation", 6381 "initialise", "finalise", "mutable", "module", "interface", "implementation",
6375 "import_module", "use_module", "include_module", "end_module", "some", "all"}; 6382 "import_module", "use_module", "include_module", "end_module", "some", "all"};
6376 6383
6377static size_t 6384static mercury_pos_t
6378mercury_decl (char *s, size_t pos) 6385mercury_decl (char *s, size_t pos)
6379{ 6386{
6380 if (s == NULL) return 0; 6387 mercury_pos_t null_pos = {0, 0, 0};
6388
6389 if (s == NULL) return null_pos;
6381 6390
6382 size_t origpos; 6391 size_t origpos;
6383 origpos = pos; 6392 origpos = pos;
@@ -6398,7 +6407,8 @@ mercury_decl (char *s, size_t pos)
6398 if (is_mercury_quantifier) 6407 if (is_mercury_quantifier)
6399 { 6408 {
6400 if (strcmp (buf, "pred") != 0 && strcmp (buf, "func") != 0) /* Bad syntax. */ 6409 if (strcmp (buf, "pred") != 0 && strcmp (buf, "func") != 0) /* Bad syntax. */
6401 return 0; 6410 return null_pos;
6411
6402 is_mercury_quantifier = false; /* Reset to base value. */ 6412 is_mercury_quantifier = false; /* Reset to base value. */
6403 found_decl_tag = true; 6413 found_decl_tag = true;
6404 } 6414 }
@@ -6418,7 +6428,7 @@ mercury_decl (char *s, size_t pos)
6418 is_mercury_quantifier = true; 6428 is_mercury_quantifier = true;
6419 } 6429 }
6420 6430
6421 break; /* Found declaration tag of rank j. */ 6431 break; /* Found declaration tag of rank j. */
6422 } 6432 }
6423 else 6433 else
6424 /* 'solver type' has a blank in the middle, 6434 /* 'solver type' has a blank in the middle,
@@ -6461,24 +6471,36 @@ mercury_decl (char *s, size_t pos)
6461 if (found_decl_tag) 6471 if (found_decl_tag)
6462 pos = skip_spaces (s + pos) - s; /* Skip len blanks again. */ 6472 pos = skip_spaces (s + pos) - s; /* Skip len blanks again. */
6463 else 6473 else
6464 return 0; 6474 return null_pos;
6465 } 6475 }
6466 6476
6467 /* From now on it is the same as for Prolog except for module dots. */ 6477 /* From now on it is the same as for Prolog except for module dots. */
6468 6478
6479 size_t start_of_name = pos;
6480
6469 if (c_islower (s[pos]) || s[pos] == '_' ) 6481 if (c_islower (s[pos]) || s[pos] == '_' )
6470 { 6482 {
6471 /* The name is unquoted. 6483 /* The name is unquoted.
6472 Do not confuse module dots with end-of-declaration dots. */ 6484 Do not confuse module dots with end-of-declaration dots. */
6485 int module_dot_pos = 0;
6473 6486
6474 while (c_isalnum (s[pos]) 6487 while (c_isalnum (s[pos])
6475 || s[pos] == '_' 6488 || s[pos] == '_'
6476 || (s[pos] == '.' /* A module dot. */ 6489 || (s[pos] == '.' /* A module dot. */
6477 && s + pos + 1 != NULL 6490 && s + pos + 1 != NULL
6478 && (c_isalnum (s[pos + 1]) || s[pos + 1] == '_'))) 6491 && (c_isalnum (s[pos + 1]) || s[pos + 1] == '_')
6492 && (module_dot_pos = pos))) /* Record module dot position.
6493 Erase module from name. */
6479 ++pos; 6494 ++pos;
6480 6495
6481 return pos - origpos; 6496 if (module_dot_pos)
6497 {
6498 start_of_name = module_dot_pos + 2;
6499 ++pos;
6500 }
6501
6502 mercury_pos_t position = {pos, pos - start_of_name + 1, pos - origpos};
6503 return position;
6482 } 6504 }
6483 else if (s[pos] == '\'') 6505 else if (s[pos] == '\'')
6484 { 6506 {
@@ -6493,28 +6515,37 @@ mercury_decl (char *s, size_t pos)
6493 ++pos; /* A double quote. */ 6515 ++pos; /* A double quote. */
6494 } 6516 }
6495 else if (s[pos] == '\0') /* Multiline quoted atoms are ignored. */ 6517 else if (s[pos] == '\0') /* Multiline quoted atoms are ignored. */
6496 return 0; 6518 return null_pos;
6497 else if (s[pos] == '\\') 6519 else if (s[pos] == '\\')
6498 { 6520 {
6499 if (s[pos+1] == '\0') 6521 if (s[pos+1] == '\0')
6500 return 0; 6522 return null_pos;
6501 pos += 2; 6523 pos += 2;
6502 } 6524 }
6503 else 6525 else
6504 ++pos; 6526 ++pos;
6505 } 6527 }
6506 return pos - origpos; 6528
6529 mercury_pos_t position = {pos, pos - start_of_name + 1, pos - origpos};
6530 return position;
6507 } 6531 }
6508 else if (is_mercury_quantifier && s[pos] == '[') /* :- some [T] pred/func. */ 6532 else if (is_mercury_quantifier && s[pos] == '[') /* :- some [T] pred/func. */
6509 { 6533 {
6510 for (++pos; s + pos != NULL && s[pos] != ']'; ++pos) {} 6534 for (++pos; s + pos != NULL && s[pos] != ']'; ++pos) {}
6511 if (s + pos == NULL) return 0; 6535 if (s + pos == NULL) return null_pos;
6512 ++pos; 6536 ++pos;
6513 pos = skip_spaces (s + pos) - s; 6537 pos = skip_spaces (s + pos) - s;
6514 return mercury_decl (s, pos) + pos - origpos; 6538 mercury_pos_t position = mercury_decl (s, pos);
6539 position.totlength += pos - origpos;
6540 return position;
6541 }
6542 else if (s[pos] == '.') /* as in ':- interface.' */
6543 {
6544 mercury_pos_t position = {pos, pos - origpos + 1, pos - origpos};
6545 return position;
6515 } 6546 }
6516 else 6547 else
6517 return 0; 6548 return null_pos;
6518} 6549}
6519 6550
6520static ptrdiff_t 6551static ptrdiff_t
@@ -6523,6 +6554,7 @@ mercury_pr (char *s, char *last, ptrdiff_t lastlen)
6523 size_t len0 = 0; 6554 size_t len0 = 0;
6524 is_mercury_type = false; 6555 is_mercury_type = false;
6525 is_mercury_quantifier = false; 6556 is_mercury_quantifier = false;
6557 bool stop_at_rule = false;
6526 6558
6527 if (is_mercury_declaration) 6559 if (is_mercury_declaration)
6528 { 6560 {
@@ -6530,38 +6562,46 @@ mercury_pr (char *s, char *last, ptrdiff_t lastlen)
6530 len0 = skip_spaces (s + 2) - s; 6562 len0 = skip_spaces (s + 2) - s;
6531 } 6563 }
6532 6564
6533 size_t len = mercury_decl (s, len0); 6565 mercury_pos_t position = mercury_decl (s, len0);
6534 if (len == 0) return 0; 6566 size_t pos = position.pos;
6535 len += len0; 6567 int offset = 0; /* may be < 0 */
6536 6568 if (pos == 0) return 0;
6537 if (( (s[len] == '.' /* This is a statement dot, not a module dot. */ 6569
6538 || (s[len] == '(' && (len += 1)) 6570 /* Skip white space for:
6539 || (s[len] == ':' /* Stopping in case of a rule. */ 6571 a. rules in definitions before :-
6540 && s[len + 1] == '-' 6572 b. 0-arity predicates with inlined modes.
6541 && (len += 2))) 6573 c. possibly multiline type definitions */
6542 && (lastlen != len || memcmp (s, last, len) != 0) 6574
6575 while (c_isspace (s[pos])) { ++pos; ++offset; }
6576
6577 if (( ((s[pos] == '.' && (pos += 1)) /* case 1
6578 This is a statement dot,
6579 not a module dot. */
6580 || c_isalnum(s[pos]) /* 0-arity procedures */
6581 || (s[pos] == '(' && (pos += 1)) /* case 2: arity > 0 */
6582 || ((s[pos] == ':') /* case 3: rules */
6583 && s[pos + 1] == '-' && (stop_at_rule = true)))
6584 && (lastlen != pos || memcmp (s, last, pos) != 0)
6543 ) 6585 )
6544 /* Types are often declared on several lines so keeping just 6586 /* Types are often declared on several lines so keeping just
6545 the first line. */ 6587 the first line. */
6546 || is_mercury_type) 6588
6589 || is_mercury_type) /* When types are implemented. */
6547 { 6590 {
6548 char *name = skip_non_spaces (s + len0); 6591 size_t namelength = position.namelength;
6549 size_t namelen; 6592 if (stop_at_rule && offset) --offset;
6550 if (name >= s + len) 6593
6551 { 6594 /* Left-trim type definitions. */
6552 name = s; 6595
6553 namelen = len; 6596 while (pos > namelength + offset
6554 } 6597 && c_isspace (s[pos - namelength - offset]))
6555 else 6598 --offset;
6556 { 6599
6557 name = skip_spaces (name); 6600 /* There is no need to correct namelength or call notinname. */
6558 namelen = len - (name - s); 6601
6559 } 6602 make_tag (s + pos - namelength - offset, namelength - 1, true,
6560 /* Remove trailing non-name characters. */ 6603 s, pos - offset - 1, lineno, linecharno);
6561 while (namelen > 0 && notinname (name[namelen - 1])) 6604 return pos;
6562 namelen--;
6563 make_tag (name, namelen, true, s, len, lineno, linecharno);
6564 return len;
6565 } 6605 }
6566 6606
6567 return 0; 6607 return 0;