Page MenuHomeSoftware Heritage

No OneTemporary

diff --git a/Units/verilog-2001.d/expected.tags b/Units/verilog-2001.d/expected.tags
index fba7eed0..2f9222c1 100644
--- a/Units/verilog-2001.d/expected.tags
+++ b/Units/verilog-2001.d/expected.tags
@@ -1,58 +1,64 @@
DEFINE input.v /^`define DEFINE$/;" c
DEF_VALUE input.v /^`define DEF_VALUE 1'd100$/;" c
DEF_WITH_EQ input.v /^`define DEF_WITH_EQ = 1'd100$/;" c
LOCALPARAM input.v /^localparam LOCALPARAM = 2**2;$/;" c module:mod
PARAM1 input.v /^ parameter PARAM1 = 10,$/;" c module:mod
PARAM2 input.v /^ parameter PARAM2 = 2.0$/;" c module:mod
STATE1 input.v /^localparam STATE1 = 4'h0,$/;" c module:mod
STATE2 input.v /^ STATE2 = 4'h1,$/;" c module:mod
STATE3 input.v /^ STATE3 = 4'h2,$/;" c module:mod
STATE4 input.v /^ STATE4 = 4'h5 ,$/;" c module:mod
STATE5 input.v /^ STATE5 = 4'h6 ,$/;" c module:mod
STATE6 input.v /^ STATE6 = 4'h7 ,$/;" c module:mod
STATE7 input.v /^ STATE7 = 4'h8;$/;" c module:mod
a input.v /^ input wire a,$/;" p module:mod
add input.v /^task add ($/;" t module:mod
b input.v /^ b,c,$/;" p module:mod
c input.v /^ b,c,$/;" p module:mod
d input.v /^ d ,$/;" p module:mod
e input.v /^ output wire e ,$/;" p module:mod
f input.v /^ output reg f,$/;" p module:mod
+func_with_range input.v /^function [1:0] func_with_range (k, l);$/;" f module:mod
g input.v /^ inout wire g$/;" p module:mod
+k input.v /^function [1:0] func_with_range (k, l);$/;" p function:mod.func_with_range
k input.v /^real k;$/;" r module:mod
+l input.v /^function [1:0] func_with_range (k, l);$/;" p function:mod.func_with_range
l input.v /^integer l;$/;" r module:mod
mod input.v /^module mod#($/;" m
mod.LOCALPARAM input.v /^localparam LOCALPARAM = 2**2;$/;" c module:mod
mod.PARAM1 input.v /^ parameter PARAM1 = 10,$/;" c module:mod
mod.PARAM2 input.v /^ parameter PARAM2 = 2.0$/;" c module:mod
mod.STATE1 input.v /^localparam STATE1 = 4'h0,$/;" c module:mod
mod.STATE2 input.v /^ STATE2 = 4'h1,$/;" c module:mod
mod.STATE3 input.v /^ STATE3 = 4'h2,$/;" c module:mod
mod.STATE4 input.v /^ STATE4 = 4'h5 ,$/;" c module:mod
mod.STATE5 input.v /^ STATE5 = 4'h6 ,$/;" c module:mod
mod.STATE6 input.v /^ STATE6 = 4'h7 ,$/;" c module:mod
mod.STATE7 input.v /^ STATE7 = 4'h8;$/;" c module:mod
mod.a input.v /^ input wire a,$/;" p module:mod
mod.add input.v /^task add ($/;" t module:mod
mod.add.x input.v /^ input x, y,$/;" p task:mod.add
mod.add.y input.v /^ input x, y,$/;" p task:mod.add
mod.add.z input.v /^ output z$/;" p task:mod.add
mod.b input.v /^ b,c,$/;" p module:mod
mod.c input.v /^ b,c,$/;" p module:mod
mod.d input.v /^ d ,$/;" p module:mod
mod.e input.v /^ output wire e ,$/;" p module:mod
mod.f input.v /^ output reg f,$/;" p module:mod
+mod.func_with_range input.v /^function [1:0] func_with_range (k, l);$/;" f module:mod
+mod.func_with_range.k input.v /^function [1:0] func_with_range (k, l);$/;" p function:mod.func_with_range
+mod.func_with_range.l input.v /^function [1:0] func_with_range (k, l);$/;" p function:mod.func_with_range
mod.g input.v /^ inout wire g$/;" p module:mod
mod.k input.v /^real k;$/;" r module:mod
mod.l input.v /^integer l;$/;" r module:mod
-mod.mult input.v /^function mult ($/;" f module:mod
+mod.mult input.v /^function integer mult ($/;" f module:mod
mod.mult.x input.v /^ input x,$/;" p function:mod.mult
mod.mult.y input.v /^ input y);$/;" p function:mod.mult
mod.scounter input.v /^reg signed [3:0] scounter;$/;" r module:mod
-mult input.v /^function mult ($/;" f module:mod
+mult input.v /^function integer mult ($/;" f module:mod
scounter input.v /^reg signed [3:0] scounter;$/;" r module:mod
x input.v /^ input x, y,$/;" p task:mod.add
x input.v /^ input x,$/;" p function:mod.mult
y input.v /^ input x, y,$/;" p task:mod.add
y input.v /^ input y);$/;" p function:mod.mult
z input.v /^ output z$/;" p task:mod.add
diff --git a/Units/verilog-2001.d/input.v b/Units/verilog-2001.d/input.v
index 4038934b..e61588cf 100644
--- a/Units/verilog-2001.d/input.v
+++ b/Units/verilog-2001.d/input.v
@@ -1,47 +1,51 @@
// Include module declaration in a comment
// module wrong;
// endmodule
`define DEFINE
`define DEF_WITH_EQ = 1'd100
`define DEF_VALUE 1'd100
module mod#(
parameter PARAM1 = 10,
parameter PARAM2 = 2.0
) (
input wire a,
b,c,
d ,
output wire e ,
output reg f,
inout wire g
);
localparam LOCALPARAM = 2**2;
localparam STATE1 = 4'h0,
STATE2 = 4'h1,
STATE3 = 4'h2,
STATE4 = 4'h5 ,
STATE5 = 4'h6 ,
STATE6 = 4'h7 ,
STATE7 = 4'h8;
real k;
integer l;
reg signed [3:0] scounter;
task add (
input x, y,
output z
);
z = x + y;
endtask
-function mult (
+function integer mult (
input x,
input y);
mult = x * y;
endfunction
+function [1:0] func_with_range (k, l);
+ func_with_range = {k, l};
+endfunction
+
endmodule // mod
diff --git a/Units/verilog-nocontext.d/args.ctags b/Units/verilog-nocontext.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-nocontext.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-nocontext.d/expected.tags b/Units/verilog-nocontext.d/expected.tags
new file mode 100644
index 00000000..02d5a26a
--- /dev/null
+++ b/Units/verilog-nocontext.d/expected.tags
@@ -0,0 +1,33 @@
+DEFINE input.v /^`define DEFINE$/;" c
+DEF_VALUE input.v /^`define DEF_VALUE 1'd100$/;" c
+DEF_WITH_EQ input.v /^`define DEF_WITH_EQ = 1'd100$/;" c
+LOCALPARAM input.v /^localparam LOCALPARAM = 2**2;$/;" c
+PARAM input.v /^parameter PARAM = 1;$/;" c
+STATE1 input.v /^localparam STATE1 = 4'h0,$/;" c
+STATE2 input.v /^ STATE2 = 4'h1,$/;" c
+STATE3 input.v /^ STATE3 = 4'h2,$/;" c
+STATE4 input.v /^ STATE4 = 4'h5 ,$/;" c
+STATE5 input.v /^ STATE5 = 4'h6 ,$/;" c
+STATE6 input.v /^ STATE6 = 4'h7 ,$/;" c
+STATE7 input.v /^ STATE7 = 4'h8;$/;" c
+a input.v /^wire a,b,c,d,e;$/;" n
+add input.v /^task add;$/;" t
+add.x input.v /^ input x, y;$/;" p task:add
+add.y input.v /^ input x, y;$/;" p task:add
+add.z input.v /^ output z;$/;" p task:add
+b input.v /^wire a,b,c,d,e;$/;" n
+c input.v /^wire a,b,c,d,e;$/;" n
+d input.v /^wire a,b,c,d,e;$/;" n
+e input.v /^wire a,b,c,d,e;$/;" n
+f input.v /^reg f;$/;" r
+g input.v /^wire g;$/;" n
+k input.v /^real k;$/;" r
+l input.v /^integer l;$/;" r
+mult input.v /^function mult;$/;" f
+mult.x input.v /^ input x;$/;" p function:mult
+mult.y input.v /^ input y;$/;" p function:mult
+x input.v /^ input x, y;$/;" p task:add
+x input.v /^ input x;$/;" p function:mult
+y input.v /^ input x, y;$/;" p task:add
+y input.v /^ input y;$/;" p function:mult
+z input.v /^ output z;$/;" p task:add
diff --git a/Units/verilog-2001.d/input.v b/Units/verilog-nocontext.d/input.v
similarity index 60%
copy from Units/verilog-2001.d/input.v
copy to Units/verilog-nocontext.d/input.v
index 4038934b..18c5275b 100644
--- a/Units/verilog-2001.d/input.v
+++ b/Units/verilog-nocontext.d/input.v
@@ -1,47 +1,45 @@
// Include module declaration in a comment
// module wrong;
// endmodule
`define DEFINE
+
`define DEF_WITH_EQ = 1'd100
`define DEF_VALUE 1'd100
-module mod#(
- parameter PARAM1 = 10,
- parameter PARAM2 = 2.0
-) (
- input wire a,
- b,c,
- d ,
- output wire e ,
- output reg f,
- inout wire g
-);
+parameter PARAM = 1;
localparam LOCALPARAM = 2**2;
localparam STATE1 = 4'h0,
STATE2 = 4'h1,
STATE3 = 4'h2,
STATE4 = 4'h5 ,
STATE5 = 4'h6 ,
STATE6 = 4'h7 ,
STATE7 = 4'h8;
+wire a,b,c,d,e;
+reg f;
+wire g;
real k;
integer l;
-reg signed [3:0] scounter;
-task add (
- input x, y,
- output z
-);
+initial begin
+ add(a, b, f);
+end
+
+task add;
+ input x, y;
+ output z;
+begin
z = x + y;
+end
endtask
-function mult (
- input x,
- input y);
+function mult;
+ input x;
+ input y;
+begin
mult = x * y;
+end
endfunction
-
-endmodule // mod
diff --git a/Units/verilog-sv-assertion.d/args.ctags b/Units/verilog-sv-assertion.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-sv-assertion.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-sv-assertion.d/expected.tags b/Units/verilog-sv-assertion.d/expected.tags
new file mode 100644
index 00000000..c03169c6
--- /dev/null
+++ b/Units/verilog-sv-assertion.d/expected.tags
@@ -0,0 +1,32 @@
+a input.sv /^property prop2 (a, b);$/;" p property:prop2
+b input.sv /^property prop2 (a, b);$/;" p property:prop2
+concurrent_assertion1 input.sv /^concurrent_assertion1 : assert property prop2 (l, m);$/;" A
+deferred_assertion1 input.sv /^ deferred_assertion1 : assert #0 () task();$/;" A block:deferred_immediate_assertions
+deferred_assertion2 input.sv /^ deferred_assertion2 : assert final () task();$/;" A block:deferred_immediate_assertions
+deferred_assume1 input.sv /^ deferred_assume1 : assume #0 () task();$/;" A block:deferred_immediate_assertions
+deferred_assume2 input.sv /^ deferred_assume2 : assume final () task();$/;" A block:deferred_immediate_assertions
+deferred_cover1 input.sv /^ deferred_cover1 : cover #0 () task();$/;" A block:deferred_immediate_assertions
+deferred_cover2 input.sv /^ deferred_cover2 : cover final () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions input.sv /^initial begin : deferred_immediate_assertions$/;" b
+deferred_immediate_assertions.deferred_assertion1 input.sv /^ deferred_assertion1 : assert #0 () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions.deferred_assertion2 input.sv /^ deferred_assertion2 : assert final () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions.deferred_assume1 input.sv /^ deferred_assume1 : assume #0 () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions.deferred_assume2 input.sv /^ deferred_assume2 : assume final () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions.deferred_cover1 input.sv /^ deferred_cover1 : cover #0 () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions.deferred_cover2 input.sv /^ deferred_cover2 : cover final () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions.immediate_assertion input.sv /^ immediate_assertion : assert () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions.immediate_assume input.sv /^ immediate_assume : assume () task();$/;" A block:deferred_immediate_assertions
+deferred_immediate_assertions.immediate_cover input.sv /^ immediate_cover : cover () task();$/;" A block:deferred_immediate_assertions
+immediate_assertion input.sv /^ immediate_assertion : assert () task();$/;" A block:deferred_immediate_assertions
+immediate_assume input.sv /^ immediate_assume : assume () task();$/;" A block:deferred_immediate_assertions
+immediate_cover input.sv /^ immediate_cover : cover () task();$/;" A block:deferred_immediate_assertions
+m input.sv /^ local input int m,$/;" p property:prop1
+n input.sv /^ logic [1:0] n,$/;" p property:prop1
+o input.sv /^ int o$/;" p property:prop1
+prop1 input.sv /^property prop1 ($/;" R
+prop1.m input.sv /^ local input int m,$/;" p property:prop1
+prop1.n input.sv /^ logic [1:0] n,$/;" p property:prop1
+prop1.o input.sv /^ int o$/;" p property:prop1
+prop2 input.sv /^property prop2 (a, b);$/;" R
+prop2.a input.sv /^property prop2 (a, b);$/;" p property:prop2
+prop2.b input.sv /^property prop2 (a, b);$/;" p property:prop2
diff --git a/Units/verilog-sv-assertion.d/input.sv b/Units/verilog-sv-assertion.d/input.sv
new file mode 100644
index 00000000..b74ff4c3
--- /dev/null
+++ b/Units/verilog-sv-assertion.d/input.sv
@@ -0,0 +1,25 @@
+initial begin : deferred_immediate_assertions
+ immediate_assertion : assert () task();
+ immediate_cover : cover () task();
+ immediate_assume : assume () task();
+ deferred_assertion1 : assert #0 () task();
+ deferred_cover1 : cover #0 () task();
+ deferred_assume1 : assume #0 () task();
+ deferred_assertion2 : assert final () task();
+ deferred_cover2 : cover final () task();
+ deferred_assume2 : assume final () task();
+end
+
+property prop1 (
+ local input int m,
+ logic [1:0] n,
+ int o
+);
+
+endproperty :prop1
+
+property prop2 (a, b);
+
+endproperty : prop2
+
+concurrent_assertion1 : assert property prop2 (l, m);
diff --git a/Units/verilog-sv-basic.d/args.ctags b/Units/verilog-sv-basic.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-sv-basic.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-sv-basic.d/expected.tags b/Units/verilog-sv-basic.d/expected.tags
new file mode 100644
index 00000000..26e176dd
--- /dev/null
+++ b/Units/verilog-sv-basic.d/expected.tags
@@ -0,0 +1,75 @@
+DEFINE input.sv /^`define DEFINE$/;" c
+DEF_VALUE input.sv /^`define DEF_VALUE 1'd100$/;" c
+DEF_WITH_EQ input.sv /^`define DEF_WITH_EQ = 1'd100$/;" c
+LOCALPARAM input.sv /^localparam LOCALPARAM = 2**2;$/;" c module:mod
+PARAM1 input.sv /^ parameter PARAM1 = 10,$/;" c module:mod
+PARAM2 input.sv /^ parameter PARAM2 = 2.0$/;" c module:mod
+STATE1 input.sv /^localparam STATE1 = 4'h0,$/;" c module:mod
+STATE2 input.sv /^ STATE2 = 4'h1,$/;" c module:mod
+STATE3 input.sv /^ STATE3 = 4'h2,$/;" c module:mod
+STATE4 input.sv /^ STATE4 = 4'h5 ,$/;" c module:mod
+STATE5 input.sv /^ STATE5 = 4'h6 ,$/;" c module:mod
+STATE6 input.sv /^ STATE6 = 4'h7 ,$/;" c module:mod
+STATE7 input.sv /^ STATE7 = 4'h8;$/;" c module:mod
+a input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p function:test.extern_func
+a input.sv /^ function mult (a, input b = 0);$/;" p function:test.mult
+a input.sv /^ input wire a,$/;" p module:mod
+a input.sv /^ reg a;$/;" r class:test
+add input.sv /^task add ($/;" t module:mod
+b input.sv /^ b,c,$/;" p module:mod
+b input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p function:test.extern_func
+b input.sv /^ function mult (a, input b = 0);$/;" p function:test.mult
+b input.sv /^ logic b;$/;" r class:test
+c input.sv /^ b,c,$/;" p module:mod
+d input.sv /^ d ,$/;" p module:mod
+e input.sv /^ output wire e ,$/;" p module:mod
+extern_func input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" f class:test
+f input.sv /^ output reg f,$/;" p module:mod
+g input.sv /^ inout wire g$/;" p module:mod
+k input.sv /^real k;$/;" r module:mod
+l input.sv /^integer l;$/;" r module:mod
+mod input.sv /^module mod#($/;" m
+mod.LOCALPARAM input.sv /^localparam LOCALPARAM = 2**2;$/;" c module:mod
+mod.PARAM1 input.sv /^ parameter PARAM1 = 10,$/;" c module:mod
+mod.PARAM2 input.sv /^ parameter PARAM2 = 2.0$/;" c module:mod
+mod.STATE1 input.sv /^localparam STATE1 = 4'h0,$/;" c module:mod
+mod.STATE2 input.sv /^ STATE2 = 4'h1,$/;" c module:mod
+mod.STATE3 input.sv /^ STATE3 = 4'h2,$/;" c module:mod
+mod.STATE4 input.sv /^ STATE4 = 4'h5 ,$/;" c module:mod
+mod.STATE5 input.sv /^ STATE5 = 4'h6 ,$/;" c module:mod
+mod.STATE6 input.sv /^ STATE6 = 4'h7 ,$/;" c module:mod
+mod.STATE7 input.sv /^ STATE7 = 4'h8;$/;" c module:mod
+mod.a input.sv /^ input wire a,$/;" p module:mod
+mod.add input.sv /^task add ($/;" t module:mod
+mod.add.x input.sv /^ input x, y,$/;" p task:mod.add
+mod.add.y input.sv /^ input x, y,$/;" p task:mod.add
+mod.add.z input.sv /^ output z$/;" p task:mod.add
+mod.b input.sv /^ b,c,$/;" p module:mod
+mod.c input.sv /^ b,c,$/;" p module:mod
+mod.d input.sv /^ d ,$/;" p module:mod
+mod.e input.sv /^ output wire e ,$/;" p module:mod
+mod.f input.sv /^ output reg f,$/;" p module:mod
+mod.g input.sv /^ inout wire g$/;" p module:mod
+mod.k input.sv /^real k;$/;" r module:mod
+mod.l input.sv /^integer l;$/;" r module:mod
+mod.mult input.sv /^function mult ($/;" f module:mod
+mod.mult.temp input.sv /^ reg temp;$/;" r function:mod.mult
+mod.mult.x input.sv /^ input x,$/;" p function:mod.mult
+mod.mult.y input.sv /^ input y);$/;" p function:mod.mult
+mult input.sv /^ function mult (a, input b = 0);$/;" f class:test
+mult input.sv /^function mult ($/;" f module:mod
+temp input.sv /^ reg temp;$/;" r function:mod.mult
+test input.sv /^class test;$/;" C
+test.a input.sv /^ reg a;$/;" r class:test
+test.b input.sv /^ logic b;$/;" r class:test
+test.extern_func input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" f class:test
+test.extern_func.a input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p function:test.extern_func
+test.extern_func.b input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p function:test.extern_func
+test.mult input.sv /^ function mult (a, input b = 0);$/;" f class:test
+test.mult.a input.sv /^ function mult (a, input b = 0);$/;" p function:test.mult
+test.mult.b input.sv /^ function mult (a, input b = 0);$/;" p function:test.mult
+x input.sv /^ input x, y,$/;" p task:mod.add
+x input.sv /^ input x,$/;" p function:mod.mult
+y input.sv /^ input x, y,$/;" p task:mod.add
+y input.sv /^ input y);$/;" p function:mod.mult
+z input.sv /^ output z$/;" p task:mod.add
diff --git a/Units/verilog-2001.d/input.v b/Units/verilog-sv-basic.d/input.sv
similarity index 72%
copy from Units/verilog-2001.d/input.v
copy to Units/verilog-sv-basic.d/input.sv
index 4038934b..d208b7ad 100644
--- a/Units/verilog-2001.d/input.v
+++ b/Units/verilog-sv-basic.d/input.sv
@@ -1,47 +1,60 @@
// Include module declaration in a comment
// module wrong;
// endmodule
`define DEFINE
`define DEF_WITH_EQ = 1'd100
`define DEF_VALUE 1'd100
+class test;
+ reg a;
+ logic b;
+ function mult (a, input b = 0);
+ return a * b;
+ endfunction : mult
+
+ extern virtual function void extern_func (input bit a, input b);
+
+endclass : test
+
module mod#(
parameter PARAM1 = 10,
parameter PARAM2 = 2.0
) (
input wire a,
b,c,
d ,
output wire e ,
output reg f,
inout wire g
);
localparam LOCALPARAM = 2**2;
localparam STATE1 = 4'h0,
STATE2 = 4'h1,
STATE3 = 4'h2,
STATE4 = 4'h5 ,
STATE5 = 4'h6 ,
STATE6 = 4'h7 ,
STATE7 = 4'h8;
real k;
integer l;
-reg signed [3:0] scounter;
+test t;
task add (
input x, y,
output z
);
z = x + y;
endtask
function mult (
input x,
input y);
- mult = x * y;
+ reg temp;
+ temp = x * y;
+ return temp;
endfunction
endmodule // mod
diff --git a/Units/verilog-sv-covergroup.d/args.ctags b/Units/verilog-sv-covergroup.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-sv-covergroup.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-sv-covergroup.d/expected.tags b/Units/verilog-sv-covergroup.d/expected.tags
new file mode 100644
index 00000000..de45dcfc
--- /dev/null
+++ b/Units/verilog-sv-covergroup.d/expected.tags
@@ -0,0 +1,20 @@
+deferred_assertion1 input.sv /^ deferred_assertion1 : assert #0 () task();$/;" A covergroup:test
+deferred_assertion2 input.sv /^ deferred_assertion2 : assert final () task();$/;" A covergroup:test
+deferred_assume1 input.sv /^ deferred_assume1 : assume #0 () task();$/;" A covergroup:test
+deferred_assume2 input.sv /^ deferred_assume2 : assume final () task();$/;" A covergroup:test
+deferred_cover1 input.sv /^ deferred_cover1 : cover #0 () task();$/;" A covergroup:test
+deferred_cover2 input.sv /^ deferred_cover2 : cover final () task();$/;" A covergroup:test
+immediate_assertion input.sv /^ immediate_assertion : assert () task();$/;" A covergroup:test
+immediate_assume input.sv /^ immediate_assume : assume () task();$/;" A covergroup:test
+immediate_cover input.sv /^ immediate_cover : cover () task();$/;" A covergroup:test
+test input.sv /^covergroup test;$/;" V
+test.deferred_assertion1 input.sv /^ deferred_assertion1 : assert #0 () task();$/;" A covergroup:test
+test.deferred_assertion2 input.sv /^ deferred_assertion2 : assert final () task();$/;" A covergroup:test
+test.deferred_assume1 input.sv /^ deferred_assume1 : assume #0 () task();$/;" A covergroup:test
+test.deferred_assume2 input.sv /^ deferred_assume2 : assume final () task();$/;" A covergroup:test
+test.deferred_cover1 input.sv /^ deferred_cover1 : cover #0 () task();$/;" A covergroup:test
+test.deferred_cover2 input.sv /^ deferred_cover2 : cover final () task();$/;" A covergroup:test
+test.immediate_assertion input.sv /^ immediate_assertion : assert () task();$/;" A covergroup:test
+test.immediate_assume input.sv /^ immediate_assume : assume () task();$/;" A covergroup:test
+test.immediate_cover input.sv /^ immediate_cover : cover () task();$/;" A covergroup:test
+var_to_check_context input.sv /^reg var_to_check_context;$/;" r
diff --git a/Units/verilog-sv-covergroup.d/input.sv b/Units/verilog-sv-covergroup.d/input.sv
new file mode 100644
index 00000000..c4c9d12b
--- /dev/null
+++ b/Units/verilog-sv-covergroup.d/input.sv
@@ -0,0 +1,13 @@
+covergroup test;
+ immediate_assertion : assert () task();
+ immediate_cover : cover () task();
+ immediate_assume : assume () task();
+ deferred_assertion1 : assert #0 () task();
+ deferred_cover1 : cover #0 () task();
+ deferred_assume1 : assume #0 () task();
+ deferred_assertion2 : assert final () task();
+ deferred_cover2 : cover final () task();
+ deferred_assume2 : assume final () task();
+endgroup
+
+reg var_to_check_context;
diff --git a/Units/verilog-sv-interface.d/args.ctags b/Units/verilog-sv-interface.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-sv-interface.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-sv-interface.d/expected.tags b/Units/verilog-sv-interface.d/expected.tags
new file mode 100644
index 00000000..dbf3fbf2
--- /dev/null
+++ b/Units/verilog-sv-interface.d/expected.tags
@@ -0,0 +1,30 @@
+a input.sv /^logic a, b, c, d;$/;" r interface:intf
+b input.sv /^logic a, b, c, d;$/;" r interface:intf
+c input.sv /^logic a, b, c, d;$/;" r interface:intf
+d input.sv /^logic a, b, c, d;$/;" r interface:intf
+e input.sv /^logic [11:0] e;$/;" r interface:intf
+external_interface input.sv /^extern interface external_interface;$/;" I
+in1 input.sv /^ input in1,$/;" p interface:intf
+in2 input.sv /^ input [11:0] in2,$/;" p interface:intf
+intf input.sv /^interface intf ($/;" I
+intf.a input.sv /^logic a, b, c, d;$/;" r interface:intf
+intf.b input.sv /^logic a, b, c, d;$/;" r interface:intf
+intf.c input.sv /^logic a, b, c, d;$/;" r interface:intf
+intf.d input.sv /^logic a, b, c, d;$/;" r interface:intf
+intf.e input.sv /^logic [11:0] e;$/;" r interface:intf
+intf.in1 input.sv /^ input in1,$/;" p interface:intf
+intf.in2 input.sv /^ input [11:0] in2,$/;" p interface:intf
+intf.iout input.sv /^ inout iout$/;" p interface:intf
+intf.master input.sv /^modport master (input a, b, output c, d, e);$/;" M interface:intf
+intf.out input.sv /^ output out,$/;" p interface:intf
+intf.slave input.sv /^modport slave (output a, b, input c, d, e);$/;" M interface:intf
+intf_automatic input.sv /^interface automatic intf_automatic;$/;" I
+intf_automatic.logic_automatic input.sv /^ logic logic_automatic;$/;" r interface:intf_automatic
+intf_static input.sv /^interface static intf_static;$/;" I
+intf_static.logic_static input.sv /^ logic logic_static;$/;" r interface:intf_static
+iout input.sv /^ inout iout$/;" p interface:intf
+logic_automatic input.sv /^ logic logic_automatic;$/;" r interface:intf_automatic
+logic_static input.sv /^ logic logic_static;$/;" r interface:intf_static
+master input.sv /^modport master (input a, b, output c, d, e);$/;" M interface:intf
+out input.sv /^ output out,$/;" p interface:intf
+slave input.sv /^modport slave (output a, b, input c, d, e);$/;" M interface:intf
diff --git a/Units/verilog-sv-interface.d/input.sv b/Units/verilog-sv-interface.d/input.sv
new file mode 100644
index 00000000..efdcea0a
--- /dev/null
+++ b/Units/verilog-sv-interface.d/input.sv
@@ -0,0 +1,24 @@
+interface intf (
+ input in1,
+ input [11:0] in2,
+ output out,
+ inout iout
+);
+
+logic a, b, c, d;
+logic [11:0] e;
+
+modport master (input a, b, output c, d, e);
+modport slave (output a, b, input c, d, e);
+
+endinterface : intf
+
+interface static intf_static;
+ logic logic_static;
+endinterface
+
+interface automatic intf_automatic;
+ logic logic_automatic;
+endinterface
+
+extern interface external_interface;
diff --git a/Units/verilog-sv-nocontext.d/args.ctags b/Units/verilog-sv-nocontext.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-sv-nocontext.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-sv-nocontext.d/expected.tags b/Units/verilog-sv-nocontext.d/expected.tags
new file mode 100644
index 00000000..79eeb96e
--- /dev/null
+++ b/Units/verilog-sv-nocontext.d/expected.tags
@@ -0,0 +1,36 @@
+DEFINE input.sv /^`define DEFINE$/;" c
+DEF_VALUE input.sv /^`define DEF_VALUE 1'd100$/;" c
+DEF_WITH_EQ input.sv /^`define DEF_WITH_EQ = 1'd100$/;" c
+LOCALPARAM input.sv /^localparam LOCALPARAM = 2**2;$/;" c
+PARAM input.sv /^parameter PARAM = 1;$/;" c
+STATE1 input.sv /^localparam STATE1 = 4'h0,$/;" c
+STATE2 input.sv /^ STATE2 = 4'h1,$/;" c
+STATE3 input.sv /^ STATE3 = 4'h2,$/;" c
+STATE4 input.sv /^ STATE4 = 4'h5 ,$/;" c
+STATE5 input.sv /^ STATE5 = 4'h6 ,$/;" c
+STATE6 input.sv /^ STATE6 = 4'h7 ,$/;" c
+STATE7 input.sv /^ STATE7 = 4'h8;$/;" c
+a input.sv /^wire a,b,c,d,e;$/;" n
+add input.sv /^task add ($/;" t
+add.x input.sv /^ input x, y,$/;" p task:add
+add.y input.sv /^ input x, y,$/;" p task:add
+add.z input.sv /^ output z$/;" p task:add
+b input.sv /^wire a,b,c,d,e;$/;" n
+c input.sv /^wire a,b,c,d,e;$/;" n
+d input.sv /^wire a,b,c,d,e;$/;" n
+e input.sv /^wire a,b,c,d,e;$/;" n
+f input.sv /^reg f;$/;" r
+g input.sv /^wire g;$/;" n
+k input.sv /^real k;$/;" r
+l input.sv /^integer l;$/;" r
+m input.sv /^ byte m;$/;" r
+mult input.sv /^function mult ($/;" f
+mult.temp input.sv /^ reg temp;$/;" r function:mult
+mult.x input.sv /^ input x,$/;" p function:mult
+mult.y input.sv /^ input y);$/;" p function:mult
+temp input.sv /^ reg temp;$/;" r function:mult
+x input.sv /^ input x, y,$/;" p task:add
+x input.sv /^ input x,$/;" p function:mult
+y input.sv /^ input x, y,$/;" p task:add
+y input.sv /^ input y);$/;" p function:mult
+z input.sv /^ output z$/;" p task:add
diff --git a/Units/verilog-2001.d/input.v b/Units/verilog-sv-nocontext.d/input.sv
similarity index 64%
copy from Units/verilog-2001.d/input.v
copy to Units/verilog-sv-nocontext.d/input.sv
index 4038934b..f17f1f3d 100644
--- a/Units/verilog-2001.d/input.v
+++ b/Units/verilog-sv-nocontext.d/input.sv
@@ -1,47 +1,44 @@
// Include module declaration in a comment
// module wrong;
// endmodule
`define DEFINE
+
`define DEF_WITH_EQ = 1'd100
`define DEF_VALUE 1'd100
-module mod#(
- parameter PARAM1 = 10,
- parameter PARAM2 = 2.0
-) (
- input wire a,
- b,c,
- d ,
- output wire e ,
- output reg f,
- inout wire g
-);
+parameter PARAM = 1;
localparam LOCALPARAM = 2**2;
localparam STATE1 = 4'h0,
STATE2 = 4'h1,
STATE3 = 4'h2,
STATE4 = 4'h5 ,
STATE5 = 4'h6 ,
STATE6 = 4'h7 ,
STATE7 = 4'h8;
+wire a,b,c,d,e;
+reg f;
+wire g;
real k;
integer l;
-reg signed [3:0] scounter;
+
+initial begin
+ byte m;
+ add(a, b, f);
+end
task add (
input x, y,
output z
);
- z = x + y;
-endtask
+endtask : add
function mult (
input x,
input y);
- mult = x * y;
-endfunction
-
-endmodule // mod
+ reg temp;
+ temp = x * y;
+ return temp;
+endfunction : mult
diff --git a/Units/verilog-sv-package.d/args.ctags b/Units/verilog-sv-package.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-sv-package.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-sv-package.d/expected.tags b/Units/verilog-sv-package.d/expected.tags
new file mode 100644
index 00000000..263385df
--- /dev/null
+++ b/Units/verilog-sv-package.d/expected.tags
@@ -0,0 +1,16 @@
+MyData input.sv /^ } MyData;$/;" T package:MyPackage
+MyPackage input.sv /^package MyPackage;$/;" K
+MyPackage.MyData input.sv /^ } MyData;$/;" T package:MyPackage
+MyPackage.add input.sv /^ function MyData add(MyData x, y);$/;" f package:MyPackage
+MyPackage.add.x input.sv /^ function MyData add(MyData x, y);$/;" p function:MyPackage.add
+MyPackage.add.y input.sv /^ function MyData add(MyData x, y);$/;" p function:MyPackage.add
+MyPackage.mul input.sv /^ function MyData mul(MyData x, y);$/;" f package:MyPackage
+MyPackage.mul.x input.sv /^ function MyData mul(MyData x, y);$/;" p function:MyPackage.mul
+MyPackage.mul.y input.sv /^ function MyData mul(MyData x, y);$/;" p function:MyPackage.mul
+add input.sv /^ function MyData add(MyData x, y);$/;" f package:MyPackage
+mul input.sv /^ function MyData mul(MyData x, y);$/;" f package:MyPackage
+var_to_check_context input.sv /^reg var_to_check_context;$/;" r
+x input.sv /^ function MyData add(MyData x, y);$/;" p function:MyPackage.add
+x input.sv /^ function MyData mul(MyData x, y);$/;" p function:MyPackage.mul
+y input.sv /^ function MyData add(MyData x, y);$/;" p function:MyPackage.add
+y input.sv /^ function MyData mul(MyData x, y);$/;" p function:MyPackage.mul
diff --git a/Units/verilog-sv-package.d/input.sv b/Units/verilog-sv-package.d/input.sv
new file mode 100644
index 00000000..c5a661c8
--- /dev/null
+++ b/Units/verilog-sv-package.d/input.sv
@@ -0,0 +1,14 @@
+package MyPackage;
+ typedef struct {
+ shortreal a;
+ real b;
+ } MyData;
+ function MyData add(MyData x, y);
+ add.a = x.a + y.a;
+ endfunction
+ function MyData mul(MyData x, y);
+ mul.b = x.b * y.b;
+ endfunction
+endpackage : ComplexPkg
+
+reg var_to_check_context;
diff --git a/Units/verilog-sv-program.d/args.ctags b/Units/verilog-sv-program.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-sv-program.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-sv-program.d/expected.tags b/Units/verilog-sv-program.d/expected.tags
new file mode 100644
index 00000000..fa534686
--- /dev/null
+++ b/Units/verilog-sv-program.d/expected.tags
@@ -0,0 +1,35 @@
+count input.sv /^ byte count;$/;" r block:prog.stop
+external_program input.sv /^extern program external_program;$/;" P
+i input.sv /^ longint i;$/;" r block:prog.start
+in1 input.sv /^ input in1,$/;" p program:prog
+in2 input.sv /^ input [11:0] in2,$/;" p program:prog
+iout input.sv /^ inout iout$/;" p program:prog
+logic_automatic input.sv /^ logic logic_automatic;$/;" r program:prog_automatic
+logic_static input.sv /^ logic logic_static;$/;" r program:prog_static
+mod_prog1 input.sv /^program mod_prog1;$/;" P module:topmod
+mod_prog2 input.sv /^program mod_prog2;$/;" P module:topmod
+ok input.sv /^ logic ok;$/;" r block:prog.start
+out input.sv /^ output out,$/;" p program:prog
+prog input.sv /^program prog ($/;" P
+prog.in1 input.sv /^ input in1,$/;" p program:prog
+prog.in2 input.sv /^ input [11:0] in2,$/;" p program:prog
+prog.iout input.sv /^ inout iout$/;" p program:prog
+prog.out input.sv /^ output out,$/;" p program:prog
+prog.start input.sv /^initial begin : start$/;" b program:prog
+prog.start.i input.sv /^ longint i;$/;" r block:prog.start
+prog.start.ok input.sv /^ logic ok;$/;" r block:prog.start
+prog.stop input.sv /^final begin : stop$/;" b program:prog
+prog.stop.count input.sv /^ byte count;$/;" r block:prog.stop
+prog_automatic input.sv /^program automatic prog_automatic;$/;" P
+prog_automatic.logic_automatic input.sv /^ logic logic_automatic;$/;" r program:prog_automatic
+prog_static input.sv /^program static prog_static;$/;" P
+prog_static.logic_static input.sv /^ logic logic_static;$/;" r program:prog_static
+reg_in_anon_prog input.sv /^ reg reg_in_anon_prog;$/;" r
+reg_in_anon_prog2 input.sv /^ reg reg_in_anon_prog2;$/;" r module:topmod_anon
+start input.sv /^initial begin : start$/;" b program:prog
+stop input.sv /^final begin : stop$/;" b program:prog
+topmod input.sv /^module topmod;$/;" m
+topmod.mod_prog1 input.sv /^program mod_prog1;$/;" P module:topmod
+topmod.mod_prog2 input.sv /^program mod_prog2;$/;" P module:topmod
+topmod_anon input.sv /^module topmod_anon;$/;" m
+topmod_anon.reg_in_anon_prog2 input.sv /^ reg reg_in_anon_prog2;$/;" r module:topmod_anon
diff --git a/Units/verilog-sv-program.d/input.sv b/Units/verilog-sv-program.d/input.sv
new file mode 100644
index 00000000..a6b7c916
--- /dev/null
+++ b/Units/verilog-sv-program.d/input.sv
@@ -0,0 +1,51 @@
+program prog (
+ input in1,
+ input [11:0] in2,
+ output out,
+ inout iout
+);
+
+initial begin : start
+ logic ok;
+ longint i;
+end
+
+final begin : stop
+ byte count;
+end
+
+endprogram : prog
+
+
+module topmod;
+
+program mod_prog1;
+endprogram : mod_prog1
+
+program mod_prog2;
+endprogram : mod_prog2
+
+endmodule
+
+
+program;
+ reg reg_in_anon_prog;
+endprogram
+
+module topmod_anon;
+
+program;
+ reg reg_in_anon_prog2;
+endprogram
+
+endmodule
+
+program static prog_static;
+ logic logic_static;
+endprogram
+
+program automatic prog_automatic;
+ logic logic_automatic;
+endprogram
+
+extern program external_program;
diff --git a/Units/verilog-sv-typedef.d/args.ctags b/Units/verilog-sv-typedef.d/args.ctags
new file mode 100644
index 00000000..99a08389
--- /dev/null
+++ b/Units/verilog-sv-typedef.d/args.ctags
@@ -0,0 +1 @@
+--extra=+q
diff --git a/Units/verilog-sv-typedef.d/expected.tags b/Units/verilog-sv-typedef.d/expected.tags
new file mode 100644
index 00000000..18042a27
--- /dev/null
+++ b/Units/verilog-sv-typedef.d/expected.tags
@@ -0,0 +1,8 @@
+myType input.sv /^} myType;$/;" T
+myType2 input.sv /^typedef classname#(paramvalue) myType2;$/;" T
+type_class input.sv /^typedef class type_class;$/;" T
+type_enum input.sv /^typedef enum type_enum;$/;" T
+type_interface_class input.sv /^typedef interface class type_interface_class;$/;" T
+type_struct input.sv /^typedef struct type_struct;$/;" T
+type_union input.sv /^typedef union type_union;$/;" T
+type_unnamed input.sv /^typedef type_unnamed;$/;" T
diff --git a/Units/verilog-sv-typedef.d/input.sv b/Units/verilog-sv-typedef.d/input.sv
new file mode 100644
index 00000000..c451f7d3
--- /dev/null
+++ b/Units/verilog-sv-typedef.d/input.sv
@@ -0,0 +1,15 @@
+typedef enum type_enum;
+typedef struct type_struct;
+typedef union type_union;
+typedef class type_class;
+typedef interface class type_interface_class;
+typedef type_unnamed;
+
+typedef enum bit [1:0] {
+ A = 2'b00,
+ B = 2'b01,
+ C = 2'b10,
+ D = 2'b11
+} myType;
+
+typedef classname#(paramvalue) myType2;
diff --git a/docs/f-news.rst b/docs/f-news.rst
index b415dac7..854cdf8b 100644
--- a/docs/f-news.rst
+++ b/docs/f-news.rst
@@ -1,615 +1,616 @@
Changes in fishman-ctags
======================================================================
:Maintainer: Masatake YAMATO <yamato@redhat.com>
----
Many changes have been introduced in fishman-ctags. Here I (Masatake
YAMATO) enumerate the changes mainly in common part. About changes
not enumerated here especially in language parsers, inquire git-log.
Importing the most of all changes from exuberant-ctags
---------------------------------------------------------------------
See "exuberant-ctags" in "Tracking other projects" about the status of
importing. Some changes in Fedora and Debian are also imported.
New parsers
---------------------------------------------------------------------
Following parsers are added.
* ada
* coffee *xcmd*
* css
* d
* ctags option library *optlib*
* falcon
* go
* json
* mib *optlib*
* rust *optlib*
* windres
+* SystemVerilog
See "Option library" about *optlib*.
See "External parser command" about *xcmd*.
Heavily improved language parsers
---------------------------------------------------------------------
* php
* verilog
New test facility named *Units*
---------------------------------------------------------------------
The existing test facility *Test* checks differences between the
output of older ctags and newer ctags. If a difference is found, it is
recognized as failed. *Test* expects older ctags works fine.
This expectation is not always met. Consider you add a new parser for
a language. You may want to add a sample source code for the language
to *Test*. Older ctags cannot make good tags file for the sample
code. Newer ctags can make it. In this point a difference is found;
and *Test* reports failure.
In other hand *Units* compares the expected output which a test
developer prepares and the output of ./ctags just built. The expected
output doesn't depend on ctags. Many part of changes I made
is covered by *Units*. Fore more detail see "Using *Units*".
Running tests under valgrind
---------------------------------------------------------------------
With the following command line tests can be run under valgrind memory
checker.
::
$ make -f testing.mak VG=1 SHELL=/bin/bash
NOTE: ``/bin/bash`` is needed to report the result.
Semi-fuzz testing
---------------------------------------------------------------------
One of the frustrating thing is that ctags enters infinite loop
against unexpected input. I wanted to decrease this kind of bugs.
In fuzz target of testing.mak I tried to spot them by giving
semi-random(semi-broken) input to parses.
::
$ make -f testing.mak fuzz LANGUAGES=LANG1[,LANG2,...]
With this command line, you can given all test inputs under
*Units/\*/input.\** to parsers specified with ``LANGUAGES`` macro
variable. The output of ctags is just ignored. This target just
checks the exit status. Ctags is run under timeout command
in fuzz target, therefore if ctags enters an infinite loop,
ctags will exits with non-zero status because timeout command
may terminate the ctags process. The timeout will be reported
like this::
[timeout C] Units/test.vhd.t/input.vhd
This means C parser doesn't stop in 1 second when
*Units/test.vhd.t/input.vhd* is given as an input. The default
duration 1 second can be changed with ``TIMEOUT=N`` argument for
*make* command. If no timeout but the exit status is non-zero,
the target reports it as following::
[unexpected-status(N) C] Units/test.vhd.t/input.vhd
You can get the list of parsers which can be used as a value
for ``LANGUAGES`` with following command line
::
$ ./ctags --list-languages
Other than ``LANGUAGES`` and ``TIMEOUT`` fuzz target take following parameters:
``VG=1``
Run ctags under valgrind. If valgrind finds memory
error it is reported like::
[valgrind-error Verilog] Units/array_spec.f90.t/input.f90
The report of valgrind is recorded at
``Units/\*/VALGRIND-${language}.tmp``.
``SHRINK=1``
If exit status is non-zero, run ``units shrink`` to
minimize the bad input. With bisection algorithm,
*misc/units shrink* tries to make the shortest input
which makes ctags exits with non-zero status.
The result is reported to ``Units/\*/SHRINK-${language}.tmp``.
Maybe useful to debug.
Automatic parser selection based on corpora
---------------------------------------------------------------------
For suffix *.m* ctags has two built-in parsers: ``ObjectiveC`` and
``Matlab``. Which parser ctags should use? Here this situation is
called "parser confliction".
Like ``--language-force`` option ctags provides some ways to choose a
parser manually. However, it is nice if ctags choose a proper parser
without manual instruction.
With ``--<LANG>-corpus=spec:corpusFile`` option you can prepare corpus a
file to make ctags learn lexical tendency of a language. Ctags
learns it as typical input of ``LANG``. Based on the learning ctags
tries to solve the parser confliction. See *Data/optlib/mib.ctags*
and *Data/corpora/RFC1213-MIB.txt* as an example of the usage of
``--<LANG>-corpus``.
About ``ObjectiveC`` and ``Matlab`` parser, corpus files are embedded
in the parser implementations. See *objc.c* and *matlab.c*.
More documentation is needed.
Modeline based parser selection
---------------------------------------------------------------------
exuberant-ctags has the ability to choose a proper parser based on shebang
lines (e.g. *#!/bin/sh*). This feature is extended in fishman-ctags.
Editors like vim and emacs recognize special patterns in files, which are
called modelines. The line is inserted by a user of the text editor and can
be used to set the file type (Vim) or mode (emacs).
fishman-ctags also recognizes these modeline and selects a language parser
based on it if ``--guess-language-eagerly`` (or ``-G``) option is given.
ctags recognizes the following patterns used in emacs:
* at the head of input file or at the line next of shebang line::
-*- mode: MODE; -*-
or ::
-*- MODE -*-
* at the end of input file::
Local Variables:
...
mode: MODE
...
End:
ctags recognizes the following patterns used in vim:
* at the end of input file::
vim:set filetype=SYNTAX
or ::
ex:se ft=SYNTAX
NOTE: This feature takes some costs, opening the input file
before parsing, than selecting a parser by the input
file name. So this feature is enabled only if the option
is given. If you like this feature, you can put
``--guess-language-eagerly`` to your .ctags.
Better parser selection for template files
---------------------------------------------------------------------
Consider an input file name *foo.c.in*. Suffix *.in* is popular as a
name for template files. Well-known one is *config.h.in* used in GNU
autotools.
ctags used suffix here *\*.in* for choosing a parser. *.in* shows
nothing about the language used in the input file. When fishman-ctags
finds *.in* as suffix, fishman-ctags checks the next suffix, here *.c*.
Dry running
---------------------------------------------------------------------
With ``--print-language`` option, you can test the parser selector of
ctags. e.g.::
$ ./ctags --print-language main.c
main.c: C
If no parser is selected, ``NONE`` is printed as parser name.
Option library
---------------------------------------------------------------------
exuberant-ctags provides the way to customize ctags with options like
``--langdef=<LANG>`` and ``--regex-<LANG>``. An option file where options are
written can be loaded with ``--options=OPTION_FILE``.
fishman-ctags extends this feature. fishman-ctags treats option files
as libraries. Developers of fishman-ctags maintain some option files
as part of fishman-ctags. They are shipped as part of fishman-ctags
release. With ``make install`` they are also installed as ctags command
is.
fishman-ctags prepares directories where the option files are installed.
Consider you use a GNU/Linux distribution.
Following directories are searched when loading an option file.
#. *~/.ctags.d/optlib*
#. */etc/ctags/optlib*
#. */usr/share/ctags/optlib*
The name of an option file must have .conf or .ctags as suffix.
If ctags is invoked with following command line::
$ ctags --options=mib ...
Following files are searched with following order for finding ``mib``:
#. *~/.ctags.d/optlib/mib.conf*
#. *~/.ctags.d/optlib/mib.ctags*
#. */etc/ctags/optlib/mib.conf*
#. */etc/ctags/optlib/mib.ctags*
#. */usr/share/ctags/optlib/mib.conf*
#. */usr/share/ctags/optlib/mib.ctags*
These are called built-in search path.
If you don't want ctags not to refer above search path, instead you
want to specify directly an option file with ``--options``, start the
parameter of the option with */* (absolute path) or *./* (relative path)
like::
$ ctags --option=/home/user/test/mib.cf
$ ctags --option=./test/mib.cf
Here the restriction about suffix doesn't exist.
On GNU/Linux you can add more directories with environment variable
named ``CTAGS_DATA_PATH``.
::
$ CTAGS_DATA_PATH=A:B ctags --options=mib ...
Following files are searched with following order for finding *mib*:
#. *A/optlib/mib.conf*
#. *A/optlib/mib.ctags*
#. *B/optlib/mib.conf*
#. *B/optlib/mib.ctags*
#. *~/.ctags.d/optlib/mib.conf*
#. ...
Further more you can use ``--data-path=[+]PATH`` for adding more directories
with environment variable::
$ CTAGS_DATA_PATH=A:B ctags --data-path=+C --options=mib ...
In this case following files are searched with following order for
finding *mib*:
#. *C/optlib/mib.conf*
#. *C/optlib/mib.ctags*
#. *A/optlib/mib.conf*
#. *A/optlib/mib.ctags*
#. *B/optlib/mib.conf*
#. *B/optlib/mib.ctags*
#. *~/.ctags.d/optlib/mib.conf*
#. ...
If you omit *+*, instead of adding you can set a directory::
$ CTAGS_DATA_PATH=A:B ctags --data-path=C --options=mib ...
In this case following files are searched with following order for
finding mib:
#. *C/config/mib.conf*
#. *C/config/mib.ctags*
With reserved file name ``NONE``, you can make the directory list empty::
$ CTAGS_DATA_PATH=A:B ctags --data-path=NONE --options=mib ...
In this case ctags tries to load *./mib*.
See also "Loading option recursively".
How a directory is set/added to the search path can be watched with
``--verbose`` option. This is useful for debugging this feature.
fishman-ctags developers wait your pull request of well written
option files.
NOTE: Though ``--data-path`` is highest priority, ``--data-path`` doesn't
affect a stage of automatic option file loading. Following files are
automatically loaded when ctags starts:
#. */ctags.cnf* (on MSDOS, MSWindows only)
#. */etc/ctags.conf*
#. */usr/local/etc/ctags.conf*
#. *$HOME/.ctags*
#. *$HOME /ctags.cnf* (on MSDOS, MSWindows only)
#. *.ctags*
#. *ctags.cnf* (on MSDOS, MSWindows only)
NOTE: This feature is still in experimental. The name of directories,
suffix rules, and other convention will change.
TODO
* Write about MSWindows more(*.cnf*).
* ``accept_only_dot_ctags()`` doesn't check *.cnf*.
See "Contributing an optlib" if you have a good optlib.
Loading option recursively
---------------------------------------------------------------------
The option file loading rules explained in "Option library" is more
complex. If you specify a directory as parameter for ``--option`` instead
of a file, fishman-ctags loads option files under the directory
recursively.
Consider following command line on GNU/Linux distribution::
$ ctags --options=bundle ...
Following directories are searched first:
#. *~/.ctags.d/optlib/bundle.d*
#. */etc/ctags/optlib/bundle.d*
#. */usr/share/ctags/optlib/bundle.d*
If *bundle.d* is found and it is a directory, files (*\*.ctags*
and *\*.conf*), directories (\*.d) are loaded recursively.
NOTE, TODO: If *bundle.d* is not found above list, a file
*bundle.ctags* or *bundle.conf* are searched. This rule is a bit
ugly. Following search rules looks better.
#. *~/.ctags.d/optlib/bundle.d*
#. *~/.ctags.d/optlib/bundle.ctags*
#. *~/.ctags.d/optlib/bundle.conf*
#. */etc/ctags/optlib/bundle.d*
#. */etc/ctags/optlib/bundle.ctags*
#. */etc/ctags/optlib/bundle.conf*
#. */usr/share/ctags/optlib/bundle.d*
#. */usr/share/ctags/optlib/bundle.ctags*
#. */usr/share/ctags/optlib/bundle.conf*
NOTE: This feature requires ``scandir`` library function. This feature may
be disabled on which platform scandir is not available. Check ``option-directory``
in the supported features::
$ ./ctags --list-features
wildcards
regex
option-directory
Directories for preloading
---------------------------------------------------------------------
As written in "Option library", option libraries can be loaded with
``--options`` option. However, you may want to load them without
specifying it explicitly.
Following files can be used for the purpose.
* ~/.ctags
* /ctags.cnf (on MSDOS, MSWindows only)
* /etc/ctags.conf
* /usr/local/etc/ctags.conf
This preloading feature comes from exuberant-ctags. However, I
think two weaknesses in this implementation.
* You have to edit the file when you want to add an
option library to be loaded.
If one wants to add or remove an ``--options=`` in a *ctags.conf*,
currently one may have to use sed or something tool for adding or
removing the line for the entry in */usr/local/etc/ctags.conf* (or
*/etc/ctags.conf*).
I made a discussion about the similar issue in
*http://marc.info/?t=129794755000003&r=1&w=2* about */etc/exports*
of NFS.
* You cannot override the configuration defined in
system administrator.
A user must accept all configuration including ``--options=``
in */etc/ctags.conf* and */usr/local/etc/ctags.conf*.
I prepare another facility. Let's not use older facility like *.ctags*.
I introduced following directories for preloading purpose.
#. *~/.ctags.d/preload*
#. */etc/ctags/preload*
#. */usr/share/ctags/preload*
All files and directories under the directories are loaded recursively,
but two restrictions:
* file/directory name
The same suffix rules written in "Option library" and
"Loading option recursively" are applied in preloading, too.
* overriding
The traversing and loading are done in the order listed above.
Once a file is loaded, another file with the same name is not loaded.
Once a directory is traversed, another directory with the same name is
not traversed.
fishman-ctags prepares */usr/share/ctags/preload/default.ctags*.
If you want ctags not to load it, make an empty file at
*~/.ctags/default.ctags*. If you want to customize
*/usr/share/ctags/preload/default.ctags*, copy the file to
*~/.ctags.d/default.ctags* and edit it as you want.
Assume */usr/share/ctags/preload/something.d* exits.
Some *.ctags* files are in the directory. With making
an empty directory at *~/.ctags.d/something.d*, you
can make ctags not to traverse */usr/share/ctags/preload/something.d*.
As the result *.ctags* files under */usr/share/ctags/preload/something.d*
are not loaded.
If you want to customize one of file under
*/usr/share/ctags/preload/something.d*, you have to copy
*/usr/share/ctags/preload/something.d* to *~/.ctags.d/somethind.d* recursively.
You can also use symbolic links. After copying or symbolic linking, edit
one of the copied file.
This feature is heavily inspired by systemd.
Long regex flag
---------------------------------------------------------------------
I am thinking about making regex parser more useful by adding
more kind of flags to ``--regex-<LANG>`` expression. As explained in
*ctags.1* man page, ``b``, ``e`` and ``i`` are defined as flags in
exuberant-ctags.
Even if I add more flags like ``x``, ``y``, ``z``,..., I guess users
including I myself may not utilize them well. It is difficult for them
to memorize. In addition If many "option libraries" are contributed,
we have to maintain them.
For both users and developers the variety short flags are just
nightmares.
So fishman-ctags prepares API for defining long flags, which can be
used as aliases for short flags. The long flags requires more typing
but more readable.
Here is the mapping between short flag names and long flag names.
=========== ===========
short flag long flag
=========== ===========
b basic
e extend
i icase
=========== ===========
Long flags can be specified with surrounding ``{`` and ``}``.
So the following ``--regex-<LANG>`` expression ::
--m4-regex=/^m4_define\(\[([^]$\(]+).+$/\1/d,definition/x
is the same as ::
--m4-regex=/^m4_define\(\[([^]$\(]+).+$/\1/d,definition/{extend}
The characters ``{`` and ``}`` are not suitable in using command line. My
intent is that using long flags in option libraries.
Exclusive flag in regex
---------------------------------------------------------------------
A line read from input files was matched with **all** regular expressions
defined with ``--regex-<LANG>`` (or ``--<LANG>-regex``). Each regular
expression matched successfully emits a tag.
In some cases another policy, exclusive-matching, is preferable to the
all-matching policy. Exclusive-matching means the rest of regular
expressions are not tried if one of regular expressions is matched
successfully,
For specifying exclusive-matching I introduced a flag ``exclusive``
(long) and ``x`` (short). It is used in *data/optlib/mib.ctags*::
--mib-regex=/^([^ \t]+)[ \t]+DEFINITIONS ::= BEGIN/\1/d,definitions/{exclusive}
--mib-regex=/^([a-zA-Z][^ \t]+)[ \t]+[A-Za-z]/\1/n,name/
passing parameter for long regex flag
---------------------------------------------------------------------
In internal APIs long-flag can take a parameter.
Conceptual example::
--<LANG>-regex=/regexp1/replacement/kind-spec/{transformer=uppercase}
--<LANG>-regex=/regexp2/replacement/kind-spec/{transformer=lowercase}
--<LANG>-regex=/regexp2/replacement/kind-spec/{transformer=capitalize}
This is not used yet any user visible places.
This is implemented for extending ctags in future.
TBW
External parser command
---------------------------------------------------------------------
There are commands generating tags file specialized to a language.
`CoffeeTags <https://github.com/lukaszkorecki/CoffeeTags>`_ is an
example. CoffeeTags deals with scripts of coffee language. It is written in
Ruby. Therefore we cannot merge the parser into ctags
directly(Remember ctags written in C). However, the format of tags
file generated by CoffeeTags conforms `FORMAT
<http://ctags.sourceforge.net/FORMAT>`_ well. This means we can reuse
the output instead of reusing parser source code.
With new ``--<LANG>-xcmd=COMMAND`` option, ctags invokes ``COMMAND``
as an external parser command(xcmd) for input files written in
``LANG``. ctags merges the output of ``COMMAND`` into tags file.
By default following executable are searched with following order for finding
xcmd ``COMMAND``:
#. *~/.ctags.d/drivers/COMMAND*
#. */usr/libexec/ctags/drivers/COMMAND*
These are called built-in search path.
On GNU/Linux you can add more directories with environment variable
named ``CTAGS_LIBEXEC_PATH``. As same as ``CTAGS_DATA_PATH``, you can
set directories with ``:`` separators to ``CTAGS_LIBEXEC_PATH``.
When searching ``COMMAND``, ctags visits the directories before visiting
the built-in search path.
You can add more search paths with ``--libexec-dir=DIR`` option. ctags
visits ``DIR/drivers`` before visiting the directories specified with
``CTAGS_LIBEXEC_PATH`` and built-in search path. If ctags cannot find
``COMMAND``, ctags treats ``COMMAND`` as an executable file, and tries
to run it.
If you want to specify an executable file as ``COMMAND`` explicitly,
use absolute (starting with ``/``) or relative path (starting with
``.``) notations.
Generally you don't want to specify an executable file as ``COMMAND``
because ctags requires very specific behaviors(protocol) to
``COMMAND``. Generally available tags generator like CoffeeTags
doesn't conforms the protocol. Executable under the built-in search
path are expected to fill the gap between generally available tags
generator and fishman-ctags. This is the reason why the name
*drivers* is used as part of built-in search path.
If you want to write a driver for a tags generator, read
"xcmd protocol and writing a driver".
There are some restrictions of utilizing the xcmds.
doesn't work with ``-x``.
ctags cannot generate cross reference file if
``--<LANG>-xcmd=COMMAND`` is specified.
doesn't work with ``-e``.
ctags cannot generate TAGS, etags format output
if ``--<LANG>-xcmd=COMMAND`` is specified.
diff --git a/parsers.h b/parsers.h
index ffe993df..5f125a6e 100644
--- a/parsers.h
+++ b/parsers.h
@@ -1,71 +1,72 @@
/*
* $Id$
*
* Copyright (c) 2000-2003, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License.
*
* External interface to all language parsing modules.
*
* To add a new language parser, you need only modify this single source
* file to add the name of the parser definition function.
*/
#ifndef _PARSERS_H
#define _PARSERS_H
/* Add the name of any new parser definition function here */
#define PARSER_LIST \
AdaParser, \
AntParser, \
AsmParser, \
AspParser, \
AwkParser, \
BasicParser, \
BetaParser, \
CParser, \
CppParser, \
CssParser, \
CsharpParser, \
CobolParser, \
DParser, \
DosBatchParser, \
EiffelParser, \
ErlangParser, \
FalconParser, \
FlexParser, \
FortranParser, \
GoParser, \
HtmlParser, \
JavaParser, \
JavaScriptParser, \
JsonParser, \
LispParser, \
LuaParser, \
MakefileParser, \
MatLabParser, \
ObjcParser, \
OcamlParser, \
PascalParser, \
PerlParser, \
PhpParser, \
PythonParser, \
RexxParser, \
RubyParser, \
SchemeParser, \
ShParser, \
SlangParser, \
SmlParser, \
SqlParser, \
TclParser, \
TexParser, \
VeraParser, \
VerilogParser, \
+ SystemVerilogParser, \
VhdlParser, \
VimParser, \
WindResParser, \
YaccParser
#endif /* _PARSERS_H */
/* vi:set tabstop=4 shiftwidth=4: */
diff --git a/verilog.c b/verilog.c
index 3abc2670..c2f3d71c 100644
--- a/verilog.c
+++ b/verilog.c
@@ -1,596 +1,1015 @@
/*
* $Id$
*
* Copyright (c) 2003, Darren Hiebert
*
* This source code is released for free distribution under the terms of the
* GNU General Public License.
*
* This module contains functions for generating tags for the Verilog HDL
* (Hardware Description Language).
*
* Language definition documents:
* http://www.eg.bucknell.edu/~cs320/verilog/verilog-manual.html
* http://www.sutherland-hdl.com/on-line_ref_guide/vlog_ref_top.html
* http://www.verilog.com/VerilogBNF.html
* http://eesun.free.fr/DOC/VERILOG/verilog_manual1.html
*/
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include <string.h>
#include <setjmp.h>
#include "debug.h"
#include "get.h"
#include "keyword.h"
#include "options.h"
#include "parse.h"
#include "read.h"
#include "routines.h"
+/*
+* MACROS
+*/
+#define NUMBER_LANGUAGES 2 /* Indicates number of defined indexes */
+#define IDX_SYSTEMVERILOG 0
+#define IDX_VERILOG 1
+
/*
* DATA DECLARATIONS
*/
typedef enum {
K_IGNORE = -2,
K_UNDEFINED,
K_CONSTANT,
K_EVENT,
K_FUNCTION,
K_MODULE,
K_NET,
K_PORT,
K_REGISTER,
K_TASK,
- K_BLOCK
+ K_BLOCK,
+ K_ASSERTION,
+ K_CLASS,
+ K_COVERGROUP,
+ K_INTERFACE,
+ K_MODPORT,
+ K_PACKAGE,
+ K_PROGRAM,
+ K_PROPERTY,
+ K_TYPEDEF
} verilogKind;
typedef struct {
const char *keyword;
verilogKind kind;
+ short isValid [NUMBER_LANGUAGES];
} keywordAssoc;
typedef struct sTokenInfo {
verilogKind kind;
vString* name; /* the name of the token */
+ unsigned long lineNumber; /* line number where token was found */
+ fpos_t filePosition; /* file position where token was found */
struct sTokenInfo* scope; /* context of keyword */
int nestLevel; /* Current nest level */
+ verilogKind lastKind; /* Kind of last found tag */
+ vString* blockName; /* Current block name */
+ boolean singleStat; /* Single statement (ends at next semi-colon) */
} tokenInfo;
/*
* DATA DEFINITIONS
*/
static int Ungetc;
static int Lang_verilog;
+static int Lang_systemverilog;
static kindOption VerilogKinds [] = {
{ TRUE, 'c', "constant", "constants (define, parameter, specparam)" },
{ TRUE, 'e', "event", "events" },
{ TRUE, 'f', "function", "functions" },
{ TRUE, 'm', "module", "modules" },
{ TRUE, 'n', "net", "net data types" },
{ TRUE, 'p', "port", "ports" },
{ TRUE, 'r', "register", "register data types" },
{ TRUE, 't', "task", "tasks" },
{ TRUE, 'b', "block", "blocks" }
};
-static keywordAssoc VerilogKeywordTable [] = {
- { "`define", K_CONSTANT },
- { "event", K_EVENT },
- { "function", K_FUNCTION },
- { "inout", K_PORT },
- { "input", K_PORT },
- { "integer", K_REGISTER },
- { "module", K_MODULE },
- { "output", K_PORT },
- { "parameter", K_CONSTANT },
- { "localparam",K_CONSTANT },
- { "real", K_REGISTER },
- { "realtime", K_REGISTER },
- { "reg", K_REGISTER },
- { "specparam", K_CONSTANT },
- { "supply0", K_NET },
- { "supply1", K_NET },
- { "task", K_TASK },
- { "time", K_REGISTER },
- { "tri0", K_NET },
- { "tri1", K_NET },
- { "triand", K_NET },
- { "tri", K_NET },
- { "trior", K_NET },
- { "trireg", K_NET },
- { "wand", K_NET },
- { "wire", K_NET },
- { "wor", K_NET },
- { "begin", K_BLOCK },
- { "end", K_BLOCK },
- { "signed", K_IGNORE }
+static kindOption SystemVerilogKinds [] = {
+ { TRUE, 'c', "constant", "constants (define, parameter, specparam)" },
+ { TRUE, 'e', "event", "events" },
+ { TRUE, 'f', "function", "functions" },
+ { TRUE, 'm', "module", "modules" },
+ { TRUE, 'n', "net", "net data types" },
+ { TRUE, 'p', "port", "ports" },
+ { TRUE, 'r', "register", "register data types" },
+ { TRUE, 't', "task", "tasks" },
+ { TRUE, 'b', "block", "blocks" },
+ { TRUE, 'A', "assert", "assertions" },
+ { TRUE, 'C', "class", "classes" },
+ { TRUE, 'V', "covergroup","covergroups" },
+ { TRUE, 'I', "interface", "interfaces" },
+ { TRUE, 'M', "modport", "modports" },
+ { TRUE, 'K', "package", "packages" },
+ { TRUE, 'P', "program", "programs" },
+ { TRUE, 'R', "property", "properties" },
+ { TRUE, 'T', "typedef", "type declarations" }
+};
+
+static const keywordAssoc KeywordTable [] = {
+ /* SystemVerilog */
+ /* | Verilog */
+ /* keyword keyword ID | | */
+ { "`define", K_CONSTANT, { 1, 1 } },
+ { "event", K_EVENT, { 1, 1 } },
+ { "function", K_FUNCTION, { 1, 1 } },
+ { "inout", K_PORT, { 1, 1 } },
+ { "input", K_PORT, { 1, 1 } },
+ { "integer", K_REGISTER, { 1, 1 } },
+ { "module", K_MODULE, { 1, 1 } },
+ { "output", K_PORT, { 1, 1 } },
+ { "parameter", K_CONSTANT, { 1, 1 } },
+ { "localparam",K_CONSTANT, { 1, 1 } },
+ { "real", K_REGISTER, { 1, 1 } },
+ { "realtime", K_REGISTER, { 1, 1 } },
+ { "reg", K_REGISTER, { 1, 1 } },
+ { "specparam", K_CONSTANT, { 1, 1 } },
+ { "supply0", K_NET, { 1, 1 } },
+ { "supply1", K_NET, { 1, 1 } },
+ { "task", K_TASK, { 1, 1 } },
+ { "time", K_REGISTER, { 1, 1 } },
+ { "tri0", K_NET, { 1, 1 } },
+ { "tri1", K_NET, { 1, 1 } },
+ { "triand", K_NET, { 1, 1 } },
+ { "tri", K_NET, { 1, 1 } },
+ { "trior", K_NET, { 1, 1 } },
+ { "trireg", K_NET, { 1, 1 } },
+ { "uwire", K_NET, { 1, 1 } },
+ { "wand", K_NET, { 1, 1 } },
+ { "wire", K_NET, { 1, 1 } },
+ { "wor", K_NET, { 1, 1 } },
+ { "begin", K_BLOCK, { 1, 1 } },
+ { "end", K_BLOCK, { 1, 1 } },
+ { "signed", K_IGNORE, { 1, 1 } },
+ { "automatic", K_IGNORE, { 1, 0 } },
+ { "assert", K_ASSERTION, { 1, 0 } },
+ { "assume", K_ASSERTION, { 1, 0 } },
+ { "bit", K_REGISTER, { 1, 0 } },
+ { "byte", K_REGISTER, { 1, 0 } },
+ { "class", K_CLASS, { 1, 0 } },
+ { "cover", K_ASSERTION, { 1, 0 } },
+ { "covergroup",K_COVERGROUP,{ 1, 0 } },
+ { "extern", K_IGNORE, { 1, 0 } },
+ { "int", K_REGISTER, { 1, 0 } },
+ { "interface", K_INTERFACE, { 1, 0 } },
+ { "local", K_IGNORE, { 1, 0 } },
+ { "logic", K_REGISTER, { 1, 0 } },
+ { "longint", K_REGISTER, { 1, 0 } },
+ { "modport", K_MODPORT, { 1, 0 } },
+ { "package", K_PACKAGE, { 1, 0 } },
+ { "program", K_PROGRAM, { 1, 0 } },
+ { "property", K_PROPERTY, { 1, 0 } },
+ { "shortint", K_REGISTER, { 1, 0 } },
+ { "shortreal", K_REGISTER, { 1, 0 } },
+ { "static", K_IGNORE, { 1, 0 } },
+ { "string", K_REGISTER, { 1, 0 } },
+ { "typedef", K_TYPEDEF, { 1, 0 } },
+ { "unsigned", K_IGNORE, { 1, 0 } },
+ { "virtual", K_IGNORE, { 1, 0 } },
+ { "void", K_IGNORE, { 1, 0 } }
};
static tokenInfo *currentContext = NULL;
/*
* FUNCTION DEFINITIONS
*/
-static short isContainer (verilogKind kind)
+static short isContainer (tokenInfo const* token)
{
- switch (kind)
+ switch (token->kind)
{
case K_MODULE:
case K_TASK:
case K_FUNCTION:
case K_BLOCK:
+ case K_CLASS:
+ case K_COVERGROUP:
+ case K_INTERFACE:
+ case K_PACKAGE:
+ case K_PROGRAM:
+ case K_PROPERTY:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static short isVariable (tokenInfo const* token)
+{
+ switch (token->kind)
+ {
+ case K_CONSTANT:
+ case K_EVENT:
+ case K_NET:
+ case K_PORT:
+ case K_REGISTER:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static short hasSimplePortList (tokenInfo const* token)
+{
+ switch (token->kind)
+ {
+ case K_TASK:
+ case K_FUNCTION:
+ case K_CLASS:
+ case K_INTERFACE:
+ case K_PROGRAM:
+ case K_PROPERTY:
return TRUE;
default:
return FALSE;
}
}
+static short isSingleStatement (tokenInfo const* token)
+{
+ if (strcmp (vStringValue (token->name), "extern") == 0 )
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
static tokenInfo *newToken (void)
{
tokenInfo *const token = xMalloc (1, tokenInfo);
token->kind = K_UNDEFINED;
token->name = vStringNew ();
+ token->lineNumber = getSourceLineNumber ();
+ token->filePosition = getInputFilePosition ();
token->scope = NULL;
token->nestLevel = 0;
+ token->lastKind = K_UNDEFINED;
+ token->blockName = vStringNew ();
+ token->singleStat = FALSE;
return token;
}
static void deleteToken (tokenInfo * const token)
{
if (token != NULL)
{
vStringDelete (token->name);
+ vStringDelete (token->blockName);
eFree (token);
}
}
static tokenInfo *pushToken (tokenInfo * const token, tokenInfo * const tokenPush)
{
tokenPush->scope = token;
return tokenPush;
}
static tokenInfo *popToken (tokenInfo * const token)
{
tokenInfo *localToken;
if (token != NULL)
{
localToken = token->scope;
deleteToken (token);
return localToken;
}
return NULL;
}
static void pruneTokens (tokenInfo * token)
{
while ((token = popToken (token)));
}
-static void initialize (const langType language)
+static const char *kindName (const verilogKind kind)
+{
+ if (isLanguage (Lang_systemverilog))
+ return SystemVerilogKinds[kind].name;
+ else /* isLanguage (Lang_verilog) */
+ return VerilogKinds[kind].name;
+}
+
+static char kindLetter (const verilogKind kind)
+{
+ if (isLanguage (Lang_systemverilog))
+ return SystemVerilogKinds[kind].letter;
+ else /* isLanguage (Lang_verilog) */
+ return VerilogKinds[kind].letter;
+}
+
+static void buildKeywordHash (const langType language, unsigned int idx)
{
size_t i;
const size_t count =
- sizeof (VerilogKeywordTable) / sizeof (VerilogKeywordTable [0]);
- Lang_verilog = language;
+ sizeof (KeywordTable) / sizeof (KeywordTable [0]);
for (i = 0 ; i < count ; ++i)
{
- const keywordAssoc* const p = &VerilogKeywordTable [i];
- addKeyword (p->keyword, language, (int) p->kind);
+ const keywordAssoc *p = &KeywordTable [i];
+ if (p->isValid [idx])
+ addKeyword (p->keyword, language, (int) p->kind);
}
}
+static void initializeVerilog (const langType language)
+{
+ Lang_verilog = language;
+ buildKeywordHash (language, IDX_VERILOG);
+}
+
+static void initializeSystemVerilog (const langType language)
+{
+ Lang_systemverilog = language;
+ buildKeywordHash (language, IDX_SYSTEMVERILOG);
+}
+
static void vUngetc (int c)
{
Assert (Ungetc == '\0');
Ungetc = c;
}
static int vGetc (void)
{
int c;
if (Ungetc == '\0')
c = fileGetc ();
else
{
c = Ungetc;
Ungetc = '\0';
}
if (c == '/')
{
int c2 = fileGetc ();
if (c2 == EOF)
return EOF;
else if (c2 == '/') /* strip comment until end-of-line */
{
do
c = fileGetc ();
while (c != '\n' && c != EOF);
}
else if (c2 == '*') /* strip block comment */
{
c = skipOverCComment();
}
else
{
fileUngetc (c2);
}
}
else if (c == '"') /* strip string contents */
{
int c2;
do
c2 = fileGetc ();
while (c2 != '"' && c2 != EOF);
c = '@';
}
return c;
}
static boolean isIdentifierCharacter (const int c)
{
return (boolean)(isalnum (c) || c == '_' || c == '`');
}
static int skipWhite (int c)
{
while (isspace (c))
c = vGetc ();
return c;
}
static int skipPastMatch (const char *const pair)
{
const int begin = pair [0], end = pair [1];
int matchLevel = 1;
int c;
do
{
c = vGetc ();
if (c == begin)
++matchLevel;
else if (c == end)
--matchLevel;
}
while (c != EOF && matchLevel > 0);
return vGetc ();
}
static void skipToEOL (void)
{
int c;
do
{
c = vGetc ();
} while (c != EOF && c != '\n');
}
static void skipComments (int c)
{
int p;
if (c == '/')
{
c = vGetc ();
if (c == '/')
{
skipToEOL ();
}
else if (c == '*')
{
do
{
p = c;
c = vGetc ();
} while (c != EOF && p != '*' && c != '/');
}
else
{
vUngetc (c);
}
}
}
-static boolean readIdentifier (vString *const name, int c)
+static void skipToSemiColon (void)
+{
+ int c;
+ do
+ {
+ c = vGetc ();
+ } while (c != EOF && c != ';');
+}
+
+static boolean readIdentifier (tokenInfo *const token, int c)
{
- vStringClear (name);
+ vStringClear (token->name);
if (isIdentifierCharacter (c))
{
while (isIdentifierCharacter (c))
{
- vStringPut (name, c);
+ vStringPut (token->name, c);
c = vGetc ();
}
vUngetc (c);
- vStringTerminate (name);
+ vStringTerminate (token->name);
+ token->lineNumber = getSourceLineNumber ();
+ token->filePosition = getInputFilePosition ();
}
- return (boolean)(vStringLength (name) > 0);
+ return (boolean)(vStringLength (token->name) > 0);
+}
+
+static verilogKind getKind (tokenInfo *const token)
+{
+ return (verilogKind) lookupKeyword (vStringValue (token->name), getSourceLanguage () );
+}
+
+static void updateKind (tokenInfo *const token)
+{
+ token->kind = getKind (token);
}
static void createContext (tokenInfo *const scope)
{
if (scope)
{
vString *contextName = vStringNew ();
verbose ("Creating new context %s\n", vStringValue (scope->name));
/* Determine full context name */
- if (currentContext)
+ if (currentContext->kind != K_UNDEFINED)
{
vStringCopy (contextName, currentContext->name);
vStringCatS (contextName, ".");
}
vStringCat (contextName, scope->name);
/* Create context */
currentContext = pushToken (currentContext, scope);
vStringCopy (currentContext->name, contextName);
vStringDelete (contextName);
}
}
-static void createTag (const verilogKind kind, vString *name)
+static void dropContext (tokenInfo *const token)
+{
+ verbose ("current context %s; context kind %0d; nest level %0d\n", vStringValue (currentContext->name), currentContext->kind, currentContext->nestLevel);
+ vString *endTokenName = vStringNewInit("end");
+ if ((currentContext->kind == K_COVERGROUP && strcmp (vStringValue (token->name), "endgroup") == 0) ||
+ (currentContext->kind == K_BLOCK && currentContext->nestLevel == 0 && strcmp (vStringValue (token->name), vStringValue (endTokenName)) == 0)
+ )
+ {
+ verbose ("Dropping context %s\n", vStringValue (currentContext->name));
+ currentContext = popToken (currentContext);
+ }
+ else
+ {
+ vStringCatS (endTokenName, kindName (currentContext->kind));
+ if (strcmp (vStringValue (token->name), vStringValue (endTokenName)) == 0)
+ {
+ verbose ("Dropping context %s\n", vStringValue (currentContext->name));
+ currentContext = popToken (currentContext);
+ }
+ }
+ vStringDelete(endTokenName);
+}
+
+
+static void createTag (tokenInfo *const token)
{
tagEntryInfo tag;
- initTagEntry (&tag, vStringValue (name));
- tag.kindName = VerilogKinds[kind].name;
- tag.kind = VerilogKinds[kind].letter;
- verbose ("Adding tag %s", vStringValue (name));
- if (currentContext)
+ /* Do nothing it tag name is empty */
+ if (vStringLength (token->name) == 0)
+ {
+ return;
+ }
+
+ /* Create tag */
+ initTagEntryFull(
+ &tag,
+ vStringValue (token->name),
+ token->lineNumber,
+ getSourceLanguageName (),
+ token->filePosition,
+ getSourceFileTagPath ()
+ );
+ tag.kindName = kindName (token->kind);
+ tag.kind = kindLetter (token->kind);
+ verbose ("Adding tag %s (kind %d)", vStringValue (token->name), token->kind);
+ if (currentContext->kind != K_UNDEFINED)
{
verbose (" to context %s\n", vStringValue (currentContext->name));
- tag.extensionFields.scope [0] = VerilogKinds[currentContext->kind].name;
+ currentContext->lastKind = token->kind;
+ tag.extensionFields.scope [0] = kindName (currentContext->kind);
tag.extensionFields.scope [1] = vStringValue (currentContext->name);
}
verbose ("\n");
makeTagEntry (&tag);
- if (Option.include.qualifiedTags && currentContext)
+ if (Option.include.qualifiedTags && currentContext->kind != K_UNDEFINED)
{
vString *const scopedName = vStringNew ();
vStringCopy (scopedName, currentContext->name);
vStringCatS (scopedName, ".");
- vStringCatS (scopedName, vStringValue (name));
+ vStringCatS (scopedName, vStringValue (token->name));
tag.name = vStringValue (scopedName);
makeTagEntry (&tag);
vStringDelete (scopedName);
}
- if (isContainer (kind))
+ if (isContainer (token))
{
tokenInfo *newScope = newToken ();
- vStringCopy (newScope->name, name);
- newScope->kind = kind;
+ vStringCopy (newScope->name, token->name);
+ newScope->kind = token->kind;
createContext (newScope);
}
}
-static boolean findBlockName (vString *const name)
+static boolean findBlockName (tokenInfo *const token)
{
int c;
c = skipWhite (vGetc ());
if (c == ':')
{
c = skipWhite (vGetc ());
- readIdentifier (name, c);
- return (boolean) (vStringLength (name) > 0);
+ readIdentifier (token, c);
+ return (boolean) (vStringLength (token->name) > 0);
}
else
vUngetc (c);
return FALSE;
}
-static void processBlock (vString *const name, const verilogKind kind)
+static void processBlock (tokenInfo *const token)
{
boolean blockStart = FALSE;
boolean blockEnd = FALSE;
- if (currentContext)
+ if (strcmp (vStringValue (token->name), "begin") == 0)
{
- if (strcmp (vStringValue (name), "begin") == 0)
- {
- currentContext->nestLevel++;
- blockStart = TRUE;
- }
- if (strcmp (vStringValue (name), "end") == 0)
- {
- currentContext->nestLevel--;
- blockEnd = TRUE;
- }
+ currentContext->nestLevel++;
+ blockStart = TRUE;
+ }
+ else if (strcmp (vStringValue (token->name), "end") == 0)
+ {
+ currentContext->nestLevel--;
+ blockEnd = TRUE;
}
- if (findBlockName (name))
+ if (findBlockName (token))
{
- verbose ("Found block: %s\n", vStringValue (name));
+ verbose ("Found block: %s\n", vStringValue (token->name));
if (blockStart)
{
- createTag (kind, name);
+ createTag (token);
verbose ("Current context %s\n", vStringValue (currentContext->name));
}
if (blockEnd && currentContext->kind == K_BLOCK && currentContext->nestLevel <= 1)
{
verbose ("Dropping context %s\n", vStringValue (currentContext->name));
currentContext = popToken (currentContext);
}
}
}
-static void tagNameList (const verilogKind kind, int c)
+static void processPortList (int c)
{
- vString *name = vStringNew ();
- verilogKind localKind, nameKind;
+ if ((c = skipWhite (c)) == '(')
+ {
+ tokenInfo *token = newToken ();
+
+ /* Get next non-whitespace character after ( */
+ c = skipWhite (vGetc ());
+
+ while (c != ';' && c != EOF)
+ {
+ if (c == '[')
+ {
+ c = skipPastMatch ("[]");
+ }
+ else if (c == '(')
+ {
+ c = skipPastMatch ("()");
+ }
+ else if (c == '{')
+ {
+ c = skipPastMatch ("{}");
+ }
+ else if (c == '=')
+ {
+ /* Search for next port or end of port declaration */
+ while (c != ',' && c != ')' && c != EOF)
+ {
+ c = skipWhite (vGetc ());
+ }
+ }
+ else if (isIdentifierCharacter (c))
+ {
+ readIdentifier (token, c);
+ updateKind (token);
+ if (token->kind == K_UNDEFINED)
+ {
+ /* Only add port name if it is the last keyword.
+ * First keyword can be a dynamic type, like a class name */
+ c = skipWhite (vGetc ());
+ if (! isIdentifierCharacter (c))
+ {
+ verbose ("Found port: %s\n", vStringValue (token->name));
+ token->kind = K_PORT;
+ createTag (token);
+ }
+ }
+ else
+ {
+ c = skipWhite (vGetc ());
+ }
+ }
+ else
+ {
+ c = skipWhite (vGetc ());
+ }
+ }
+
+ if (! isIdentifierCharacter (c)) vUngetc (c);
+
+ deleteToken (token);
+ }
+}
+
+static void processFunction (tokenInfo *const token)
+{
+ int c;
+
+ /* Search for function name
+ * Last identifier found before a '(' or a ';' is the function name */
+ c = skipWhite (vGetc ());
+ do
+ {
+ readIdentifier (token, c);
+ c = skipWhite (vGetc ());
+ } while (c != '(' && c != ';' && c != EOF);
+
+ if ( vStringLength (token->name) > 0 )
+ {
+ verbose ("Found function: %s\n", vStringValue (token->name));
+
+ /* Creat tag */
+ createTag (token);
+
+ /* Get port list from function */
+ processPortList (c);
+ }
+}
+
+static void processTypedef (tokenInfo *const token)
+{
+ /*Note: At the moment, only identifies typedef name and not its contents */
+ int c;
+
+ /* Get identifiers */
+ c = skipWhite (vGetc ());
+ while (isIdentifierCharacter (c))
+ {
+ readIdentifier (token, c);
+ c = skipWhite (vGetc ());
+ }
+
+ /* Skip bus width definition */
+ if (c == '[')
+ {
+ skipPastMatch ("[]");
+ c = skipWhite (vGetc ());
+ }
+
+ /* Skip typedef contents */
+ if (c == '{')
+ {
+ skipPastMatch ("{}");
+ c = skipWhite (vGetc ());
+ }
+
+ /* Skip past class parameter override */
+ if (c == '#')
+ {
+ c = skipWhite (vGetc ());
+ if (c == '(')
+ {
+ skipPastMatch ("()");
+ }
+ c = skipWhite (vGetc ());
+ }
+
+ /* Read new typedef identifier */
+ if (isIdentifierCharacter (c))
+ {
+ readIdentifier (token, c);
+ }
+
+ /* Use last identifier to create tag */
+ createTag (token);
+}
+
+static void tagNameList (tokenInfo* token, int c)
+{
+ verilogKind localKind;
boolean repeat;
+
+ /* Many keywords can have bit width.
+ * reg [3:0] net_name;
+ * inout [(`DBUSWIDTH-1):0] databus;
+ */
+ if (c == '(')
+ c = skipPastMatch ("()");
+ c = skipWhite (c);
+ if (c == '[')
+ c = skipPastMatch ("[]");
+ c = skipWhite (c);
+ if (c == '#')
+ {
+ c = vGetc ();
+ if (c == '(')
+ c = skipPastMatch ("()");
+ }
+ c = skipWhite (c);
+
Assert (isIdentifierCharacter (c));
- localKind = kind;
do
{
repeat = FALSE;
+
if (isIdentifierCharacter (c))
{
- readIdentifier (name, c);
- /* Check if "name" is in fact a keyword */
- nameKind = (verilogKind) lookupKeyword (vStringValue (name), getSourceLanguage () );
+ readIdentifier (token, c);
+ localKind = getKind (token);
/* Create tag in case name is not a known kind ... */
- if (nameKind == K_UNDEFINED)
+ if (localKind == K_UNDEFINED)
{
- createTag (localKind, name);
+ createTag (token);
}
/* ... or else continue searching for names */
else
{
- /* Update local kind unless it's a port or an ignored keyword */
- if (localKind != K_PORT && nameKind != K_IGNORE)
+ /* Update kind unless it's a port or an ignored keyword */
+ if (token->kind != K_PORT && localKind != K_IGNORE)
{
- localKind = nameKind;
+ token->kind = localKind;
}
repeat = TRUE;
}
}
else
break;
c = skipWhite (vGetc ());
+
if (c == '[')
c = skipPastMatch ("[]");
c = skipWhite (c);
if (c == '=')
{
c = skipWhite (vGetc ());
if (c == '{')
skipPastMatch ("{}");
else
{
/* Skip until end of current name, kind or parameter list definition */
do
c = vGetc ();
while (c != EOF && c != ',' && c != ';' && c != ')');
}
}
if (c == ',')
{
c = skipWhite (vGetc ());
repeat = TRUE;
}
} while (repeat);
- vStringDelete (name);
vUngetc (c);
}
-static void findTag (vString *const name)
+static void findTag (tokenInfo *const token)
{
- const verilogKind kind = (verilogKind) lookupKeyword (vStringValue (name), Lang_verilog);
-
- /* Search for end of current context to drop respective context */
- if (currentContext)
+ if (currentContext->kind != K_UNDEFINED)
{
- vString *endTokenName = vStringNewInit("end");
- if (currentContext->kind == K_BLOCK && currentContext->nestLevel == 0 && strcmp (vStringValue (name), vStringValue (endTokenName)) == 0)
- {
- verbose ("Dropping context %s\n", vStringValue (currentContext->name));
- currentContext = popToken (currentContext);
- }
- else
- {
- vStringCatS (endTokenName, VerilogKinds[currentContext->kind].name);
- if (strcmp (vStringValue (name), vStringValue (endTokenName)) == 0)
- {
- verbose ("Dropping context %s\n", vStringValue (currentContext->name));
- currentContext = popToken (currentContext);
- }
- }
- vStringDelete(endTokenName);
+ /* Drop context, but only if an end token is found */
+ dropContext (token);
}
- if (kind == K_CONSTANT && vStringItem (name, 0) == '`')
+ if (token->kind == K_CONSTANT && vStringItem (token->name, 0) == '`')
{
/* Bug #961001: Verilog compiler directives are line-based. */
int c = skipWhite (vGetc ());
- readIdentifier (name, c);
- createTag (kind, name);
+ readIdentifier (token, c);
+ createTag (token);
/* Skip the rest of the line. */
do {
c = vGetc();
} while (c != EOF && c != '\n');
vUngetc (c);
}
- else if (kind == K_BLOCK)
+ else if (token->kind == K_BLOCK)
{
/* Process begin..end blocks */
- processBlock (name, kind);
+ processBlock (token);
+ }
+ else if (token->kind == K_FUNCTION || token->kind == K_TASK)
+ {
+ /* Functions are treated differently because they may also include the
+ * type of the return value.
+ * Tasks are treated in the same way, although not having a return
+ * value.*/
+ processFunction (token);
+ }
+ else if (token->kind == K_ASSERTION)
+ {
+ if (vStringLength (currentContext->blockName) > 0)
+ {
+ vStringCopy (token->name, currentContext->blockName);
+ createTag (token);
+ skipToSemiColon ();
+ }
}
- else if (kind != K_UNDEFINED)
+ else if (token->kind == K_TYPEDEF)
+ {
+ processTypedef (token);
+ }
+ else if (token->kind == K_IGNORE && isSingleStatement (token))
+ {
+ currentContext->singleStat = TRUE;
+ }
+ else if (isVariable (token))
{
int c = skipWhite (vGetc ());
- /* Many keywords can have bit width.
- * reg [3:0] net_name;
- * inout [(`DBUSWIDTH-1):0] databus;
- */
- if (c == '(')
- c = skipPastMatch ("()");
- c = skipWhite (c);
- if (c == '[')
- c = skipPastMatch ("[]");
- c = skipWhite (c);
- if (c == '#')
+ tagNameList (token, c);
+ }
+ else if (token->kind != K_UNDEFINED && token->kind != K_IGNORE)
+ {
+ int c = skipWhite (vGetc ());
+
+ if (isIdentifierCharacter (c))
{
- c = vGetc ();
- if (c == '(')
- c = skipPastMatch ("()");
+ readIdentifier (token, c);
+ while (getKind (token) == K_IGNORE)
+ {
+ c = skipWhite (vGetc ());
+ readIdentifier (token, c);
+ }
+ createTag (token);
+
+ /* Get port list if required */
+ c = skipWhite (vGetc ());
+ if (c == '(' && hasSimplePortList (token))
+ {
+ processPortList (c);
+ }
+ else
+ {
+ vUngetc (c);
+ }
}
- c = skipWhite (c);
- if (isIdentifierCharacter (c))
- tagNameList (kind, c);
}
}
static void findVerilogTags (void)
{
- vString *const name = vStringNew ();
+ tokenInfo *const token = newToken ();
int c = '\0';
+ currentContext = newToken ();
while (c != EOF)
{
c = vGetc ();
+ c = skipWhite (c);
switch (c)
{
case '/':
skipComments (c);
break;
+ /* Store current block name whenever a : is found
+ * This is used later by any tag type that requires this information
+ * */
+ case ':':
+ vStringCopy (currentContext->blockName, token->name);
+ break;
+ /* Skip interface modport port declarations */
+ case '(':
+ if (currentContext && currentContext->lastKind == K_MODPORT)
+ {
+ skipPastMatch ("()");
+ }
+ break;
+ /* Drop context on single statements, which don't have an end
+ * statement */
+ case ';':
+ if (currentContext->scope && currentContext->scope->singleStat)
+ {
+ verbose ("Dropping context %s\n", vStringValue (currentContext->name));
+ currentContext = popToken (currentContext);
+ currentContext->singleStat = FALSE;
+ }
+ break;
default :
- c = skipWhite (c);
if (isIdentifierCharacter (c))
{
- readIdentifier (name, c);
- findTag (name);
+ readIdentifier (token, c);
+ updateKind (token);
+ findTag (token);
}
}
}
- vStringDelete (name);
+ deleteToken (token);
pruneTokens (currentContext);
currentContext = NULL;
}
extern parserDefinition* VerilogParser (void)
{
static const char *const extensions [] = { "v", NULL };
parserDefinition* def = parserNew ("Verilog");
def->kinds = VerilogKinds;
def->kindCount = KIND_COUNT (VerilogKinds);
def->extensions = extensions;
def->parser = findVerilogTags;
- def->initialize = initialize;
+ def->initialize = initializeVerilog;
+ return def;
+}
+
+extern parserDefinition* SystemVerilogParser (void)
+{
+ static const char *const extensions [] = { "sv", "svh", "svi", NULL };
+ parserDefinition* def = parserNew ("SystemVerilog");
+ def->kinds = SystemVerilogKinds;
+ def->kindCount = KIND_COUNT (SystemVerilogKinds);
+ def->extensions = extensions;
+ def->parser = findVerilogTags;
+ def->initialize = initializeSystemVerilog;
return def;
}
/* vi:set tabstop=4 shiftwidth=4: */

File Metadata

Mime Type
text/x-diff
Expires
Jul 4 2025, 6:04 PM (4 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3452643

Event Timeline