2012-01-16 16:34:32 +01:00
#!/usr/bin/perl
2017-03-05 22:33:31 +01:00
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
2012-01-16 16:34:32 +01:00
use warnings ;
use strict ;
my $ debug = 0 ;
# for paragraphs
my $ USER_SPECIFIED = 1 ;
my $ RESULTS_SPECIFIED = 2 ;
my $ search = join ' ' , @ ARGV ;
2019-05-28 18:19:42 +02:00
if ( not length $ search ) {
2013-02-25 03:27:24 +01:00
print "Usage: c11std [-list] [-n#] [-section <section>] [search text] -- 'section' must be in the form of X.YpZ where X and Y are section/chapter and, optionally, pZ is paragraph. If both 'section' and 'search text' are specified, then the search space will be within the specified section. You may use -n # to skip to the #th match. To list only the section numbers containing 'search text', add -list.\n" ;
2012-01-16 16:34:32 +01:00
exit 0 ;
}
my ( $ section , $ paragraph , $ section_specified , $ paragraph_specified , $ match , $ list_only , $ list_titles ) ;
$ section_specified = 0 ;
$ paragraph_specified = 0 ;
2019-05-28 18:19:42 +02:00
if ( $ search =~ s/-section\s*([A-Z0-9\.p]+)//i or $ search =~ s/\b([A-Z0-9]+\.[0-9\.p]+)//i ) {
2012-01-16 16:34:32 +01:00
$ section = $ 1 ;
2019-05-28 18:19:42 +02:00
if ( $ section =~ s/p(\d+)//i ) {
2012-01-16 16:34:32 +01:00
$ paragraph = $ 1 ;
$ paragraph_specified = $ USER_SPECIFIED ;
} else {
$ paragraph = 1 ;
}
2015-01-07 00:35:40 +01:00
$ section = "$section." if $ section =~ m/^[A-Z0-9]+$/i ;
2012-01-16 16:34:32 +01:00
$ section_specified = 1 ;
}
2019-05-28 18:19:42 +02:00
if ( $ search =~ s/-n\s*(\d+)// ) {
2012-01-16 16:34:32 +01:00
$ match = $ 1 ;
} else {
$ match = 1 ;
}
2019-05-28 18:19:42 +02:00
if ( $ search =~ s/-list//i ) {
2012-01-16 16:34:32 +01:00
$ list_only = 1 ;
$ list_titles = 1 ; # Added here instead of removing -titles option
}
2019-05-28 18:19:42 +02:00
if ( $ search =~ s/-titles//i ) {
2012-01-16 16:34:32 +01:00
$ list_only = 1 ;
$ list_titles = 1 ;
}
$ search =~ s/^\s+// ;
$ search =~ s/\s+$// ;
2019-05-28 18:19:42 +02:00
if ( not defined $ section ) {
2012-01-16 16:34:32 +01:00
$ section = "1." ;
$ paragraph = 1 ;
}
2019-05-28 18:19:42 +02:00
if ( $ list_only and not length $ search ) {
2012-01-16 16:34:32 +01:00
print "You must specify some search text to use with -list.\n" ;
exit 0 ;
}
2012-01-23 23:24:51 +01:00
open FH , "<n1570.out" or die "Could not open n1570: $!" ;
2012-01-16 16:34:32 +01:00
my @ contents = <FH> ;
close FH ;
my $ text = join '' , @ contents ;
$ text =~ s/\r//g ;
my $ result ;
my $ found_section = "" ;
my $ found_section_title = "" ;
my $ section_title ;
my $ found_paragraph ;
my $ found = 0 ;
my $ matches = 0 ;
my $ this_section ;
my $ comma = "" ;
2019-05-28 18:19:42 +02:00
if ( $ list_only ) {
2012-01-16 16:34:32 +01:00
$ result = "Sections containing '$search':\n " ;
}
2014-12-30 08:24:54 +01:00
my $ qsearch = quotemeta $ search ;
$ qsearch =~ s/\\ / /g ;
$ qsearch =~ s/\s+/\\s+/g ;
2012-01-16 16:34:32 +01:00
2019-05-28 18:19:42 +02:00
while ( $ text =~ m/^\s{0,4}([0-9A-Z]+\.[0-9\.]*)/msg ) {
2012-01-16 16:34:32 +01:00
$ this_section = $ 1 ;
print "----------------------------------\n" if $ debug >= 2 ;
print "Processing section [$this_section]\n" if $ debug ;
2012-01-23 23:24:51 +01:00
2019-05-28 18:19:42 +02:00
if ( $ section_specified and $ this_section !~ m/^$section/i ) {
2012-01-23 23:24:51 +01:00
print "No section match, skipping.\n" if $ debug >= 4 ;
next ;
}
2012-01-16 16:34:32 +01:00
my $ section_text ;
2019-05-28 18:19:42 +02:00
if ( $ text =~ m/(.*?)^(?=\s{0,4}(?!FOOTNOTE)[0-9A-Z]+\.)/msg ) {
2012-01-16 16:34:32 +01:00
$ section_text = $ 1 ;
} else {
print "No section text, end of file marker found.\n" if $ debug >= 4 ;
last ;
}
2019-05-28 18:19:42 +02:00
if ( $ section =~ /FOOTNOTE/i ) {
2012-01-23 23:24:51 +01:00
$ section_text =~ s/^\s{4}//ms ;
2015-01-07 00:35:40 +01:00
$ section_text =~ s/^\s{4}FOOTNOTE.*//msi ;
2012-01-23 23:24:51 +01:00
$ section_text =~ s/^\d.*//ms ;
2012-07-22 21:22:30 +02:00
} elsif ( $ section_text =~ m/(.*?)$/msg ) {
2012-01-16 16:34:32 +01:00
$ section_title = $ 1 if length $ 1 ;
$ section_title =~ s/^\s+// ;
$ section_title =~ s/\s+$// ;
}
print "$this_section [$section_title]\n" if $ debug >= 2 ;
2019-05-28 18:19:42 +02:00
while ( $ section_text =~ m/^(\d+)\s(.*?)^(?=\d)/msgic or $ section_text =~ m/^(\d+)\s(.*)/msgi ) {
2012-01-16 16:34:32 +01:00
my $ p = $ 1 ;
my $ t = $ 2 ;
print "paragraph $p: [$t]\n" if $ debug >= 3 ;
2019-05-28 18:19:42 +02:00
if ( $ paragraph_specified == $ USER_SPECIFIED and not length $ search and $ p == $ paragraph ) {
2012-01-16 16:34:32 +01:00
$ result = $ t if not $ found ;
$ found_paragraph = $ p ;
$ found_section = $ this_section ;
$ found_section_title = $ section_title ;
$ found = 1 ;
last ;
}
2019-05-28 18:19:42 +02:00
if ( length $ search ) {
2012-01-16 16:34:32 +01:00
eval {
2019-05-28 18:19:42 +02:00
if ( $ t =~ m/\b$qsearch\b/mis or $ section_title =~ m/\b$qsearch\b/mis ) {
2012-01-16 16:34:32 +01:00
$ matches + + ;
2019-05-28 18:19:42 +02:00
if ( $ matches >= $ match ) {
if ( $ list_only ) {
2012-01-16 16:34:32 +01:00
$ result . = sprintf ( "%s%-15s" , $ comma , $ this_section . "p" . $ p ) ;
$ result . = " $section_title" if $ list_titles ;
$ comma = ",\n " ;
} else {
2019-05-28 18:19:42 +02:00
if ( not $ found ) {
2012-01-16 16:34:32 +01:00
$ result = $ t ;
$ found_section = $ this_section ;
$ found_section_title = $ section_title ;
$ found_paragraph = $ p ;
$ paragraph_specified = $ RESULTS_SPECIFIED ;
}
$ found = 1 ;
}
}
}
} ;
2019-05-28 18:19:42 +02:00
if ( $@ ) {
2012-01-16 16:34:32 +01:00
print "Error in search regex; you may need to escape characters such as *, ?, ., etc.\n" ;
exit 0 ;
}
}
}
last if $ found && $ paragraph_specified == $ USER_SPECIFIED ;
2019-06-26 18:34:19 +02:00
2019-05-28 18:19:42 +02:00
if ( $ paragraph_specified == $ USER_SPECIFIED ) {
if ( length $ search ) {
2014-02-22 03:42:25 +01:00
print "No such text '$search' in paragraph $paragraph of section $section of n1570.\n" ;
} else {
print "No such paragraph $paragraph in section $section of n1570.\n" ;
}
2012-01-16 16:34:32 +01:00
exit 0 ;
}
2019-05-28 18:19:42 +02:00
if ( defined $ section_specified and not length $ search ) {
2012-01-16 16:34:32 +01:00
$ found = 1 ;
$ found_section = $ this_section ;
$ found_section_title = $ section_title ;
$ found_paragraph = $ paragraph ;
$ result = $ section_text ;
last ;
}
}
2019-05-28 18:19:42 +02:00
if ( not $ found and $ comma eq "" ) {
2012-01-16 16:34:32 +01:00
$ search =~ s/\\s\+/ /g ;
2019-05-28 18:19:42 +02:00
if ( $ section_specified ) {
2012-01-16 16:34:32 +01:00
print "No such text '$search' found within section '$section' in C11 Draft Standard (n1570).\n" if length $ search ;
print "No such section '$section' in C11 Draft Standard (n1570).\n" if not length $ search ;
exit 0 ;
}
print "No such section '$section' in C11 Draft Standard (n1570).\n" if not length $ search ;
print "No such text '$search' found in C11 Draft Standard (n1570).\n" if length $ search ;
exit 0 ;
}
$ result =~ s/$found_section_title// if length $ found_section_title ;
$ result =~ s/^\s+// ;
$ result =~ s/\s+$// ;
= cut
$ result =~ s/\s+/ /g ;
$ result =~ s/[\n\r]/ /g ;
= cut
2019-05-28 18:19:42 +02:00
if ( $ matches > 1 and not $ list_only ) {
2012-07-22 21:22:30 +02:00
print "Displaying $match of $matches matches: " ;
2012-01-16 16:34:32 +01:00
}
2019-05-28 18:19:42 +02:00
if ( $ comma eq "" ) {
2012-01-16 16:34:32 +01:00
= cut
print $ found_section ;
print "p" . $ found_paragraph if $ paragraph_specified ;
= cut
2012-07-22 21:22:30 +02:00
# print "\nhttp://blackshell.com/~msmud/n1570.html\#$found_section";
2019-05-28 18:19:42 +02:00
print "http://www.iso-9899.info/n1570.html\#$found_section" ;
2012-01-16 16:34:32 +01:00
print "p" . $ found_paragraph if $ paragraph_specified ;
print "\n\n" ;
print "[" , $ found_section_title , "]\n\n" if length $ found_section_title ;
}
2012-11-02 23:08:20 +01:00
$ result =~ s/\s*Constraints\s*$// ;
$ result =~ s/\s*Semantics\s*$// ;
$ result =~ s/\s*Description\s*$// ;
$ result =~ s/\s*Returns\s*$// ;
$ result =~ s/\s*Runtime-constraints\s*$// ;
$ result =~ s/\s*Recommended practice\s*$// ;
2012-01-16 16:34:32 +01:00
print "$result\n" ;