1#!/usr/bin/env perl
2if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
3# DESCRIPTION: Verilator: Verilog Test driver/expect definition
4#
5# Copyright 2003 by Wilson Snyder. This program is free software; you
6# can redistribute it and/or modify it under the terms of either the GNU
7# Lesser General Public License Version 3 or the Perl Artistic License
8# Version 2.0.
9# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
10
11use IO::File;
12
13scenarios(dist => 1);
14
15my $root = "..";
16my $Debug;
17
18if (!-r "$root/.git") {
19    skip("Not in a git repository");
20} else {
21    uint();
22    printfll();
23    cstr();
24    vsnprintf();
25    final();
26}
27
28ok(1);
29
30sub uint {
31    ### Must trim output before and after our file list
32    #my $files = "*/*.c* */*.h test_regress/t/*.c* test_regress/t/*.h";
33    # src isn't clean, and probably doesn't need to be (yet?)
34    my $files = "include/*.c* include/*.h examples/*/*.c* test_regress/t/*.c* test_regress/t/*.h";
35    my $cmd = "cd $root && fgrep -n int $files | sort";
36    print "C $cmd\n";
37    my $grep = `$cmd`;
38    my %names;
39    foreach my $line (split /\n/, $grep) {
40        $line =~ s!//.*$!!;
41        next if $line !~ /uint\d+_t\b/;
42        next if $line =~ /vl[su]int\d+_t/;
43        next if $line =~ /typedef/;
44        next if $line =~ m!include/svdpi.h!;  # Not ours
45        if ($line =~ /^([^:]+)/) {
46            $names{$1} = 1;
47            print "$line\n";
48        }
49    }
50    if (keys %names) {
51        error("Files with uint32*_t instead of vluint32s: ", join(' ', sort keys %names));
52    }
53}
54
55sub printfll {
56    my $files = "src/*.c* src/*.h include/*.c* include/*.h examples/*/*.c* test_regress/t/*.c* test_regress/t/*.h";
57    my $cmd = "cd $root && fgrep -n ll $files | sort";
58    print "C $cmd\n";
59    my $grep = `$cmd`;
60    my %names;
61    foreach my $line (split /\n/, $grep) {
62        next if $line !~ /%[a-z0-9]*ll/;
63        next if $line !~ /\blong\S+long\b/;  # Assume a cast
64        print "$line\n";
65        if ($line =~ /^([^:]+)/) {
66            $names{$1} = 1;
67        } else {
68            $names{UNKNOWN} = 1;
69        }
70    }
71    if (keys %names) {
72        error("Files with %ll instead of VL_PRI64: ", join(' ', sort keys %names));
73    }
74}
75
76sub cstr {
77    my $files = "src/*.c* src/*.h include/*.c* include/*.h examples/*/*.c* test_regress/t/*.c* test_regress/t/*.h";
78    my $cmd = "cd $root && grep -n -P 'c_str|begin|end' $files | sort";
79    print "C $cmd\n";
80    my $grep = `$cmd`;
81    my %names;
82    foreach my $line (split /\n/, $grep) {
83        if ($line =~ /^([^:]+)[^"]*\(\)[a-z0-9_().->]*[.->]+(c_str|r?begin|r?end)\(\)/) {
84            next if $line =~ /lintok-begin-on-ref/;
85            print "$line\n";
86            $names{$1} = 1;
87        }
88    }
89    if (keys %names) {
90        error("Files with potential c_str() lifetime issue: ", join(' ', sort keys %names));
91    }
92}
93
94sub vsnprintf {
95    # Note do not do test_regress, as VPI files need to compile without verilatedos.h
96    my $files = "src/*.c* src/*.h include/*.c* include/*.h examples/*/*.c*";
97    my $cmd = "cd $root && grep -n -P '(snprintf|vsnprintf)' $files | sort";
98    print "C $cmd\n";
99    my $grep = `$cmd`;
100    my %names;
101    foreach my $line (split /\n/, $grep) {
102        if ($line =~ /\b(snprintf|vsnprintf)\b/) {
103            next if $line =~ /# *define\s*VL_V?SNPRINTF/;
104            print "$line\n";
105            $names{$1} = 1;
106        }
107    }
108    if (keys %names) {
109        error("Files with vsnprintf, use VL_VSNPRINTF: ", join(' ', sort keys %names));
110    }
111}
112
113sub final {
114    # Note do not do test_regress, as VPI files need to compile without verilatedos.h
115    my $files = "src/*.c* src/*.h include/*.c* include/*.h";
116    my $cmd = "cd $root && grep -n -P '(class)' $files | sort";
117    print "C $cmd\n";
118    my $grep = `$cmd`;
119    my %names;
120    foreach my $line (split /\n/, $grep) {
121        if ($line =~ /:\s*class /) {
122            next if $line =~ /final|VL_NOT_FINAL/;
123            next if $line =~ /{}/;  # e.g. 'class Foo {};'
124            next if $line =~ /;/;  # e.g. 'class Foo;'
125            print "$line\n";
126            $names{$1} = 1;
127        }
128    }
129    if (keys %names) {
130        error("Files with classes without final/VL_NOT_FINAL: ", join(' ', sort keys %names));
131    }
132}
133
1341;
135