From 080ab7ca7a9fccc57e0265fdbdcc27925b62c8f1 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Wed, 23 Oct 2024 11:18:27 -0500 Subject: [PATCH 1/8] fix: applied gawk prettyprint to awk --- idnits | 6197 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 3065 insertions(+), 3132 deletions(-) diff --git a/idnits b/idnits index 4e4e2c6..717a71d 100755 --- a/idnits +++ b/idnits @@ -248,3338 +248,3271 @@ checknits() { cat << 'EOF' > $program BEGIN { - option_verbose = 0; - option_warn = 1; - option_nonascii = 0; - - split(ENVIRON["CHECKNITS"], argv); - - columns = ENVIRON["COLUMNS"]; - if (! columns ) columns = 78; - if (columns > 80) columns = 80; - if (columns < 16) columns = 16; - if (columns < 73) bpcols = columns; else bpcols = 73; - - indentation = 8; - errmark = "**"; - flawmark = "~~" - warnmark = "=="; - infomark = "--"; - notemark = " "; - - for (i in argv) { - # Deprecated - if (argv[i] == "--rfc3667") { - printf "\nOption %s does nothing any more\n", argv[i]; - argv[i] = ""; - } - if (argv[i] == "--no3667") { - printf "\nOption %s does nothing any more\n", argv[i]; - argv[i] = ""; - } - if (argv[i] == "--rfc2026") { - printf "\nOption %s does nothing any more\n", argv[i]; - argv[i] = ""; - } - if (argv[i] == "--nowarn") { - option_warn = 0; - argv[i] = ""; - } - if (argv[i] == "--filename") { - option_filename = argv[i+1]; - argv[i] = ""; - argv[i+1] = ""; - } - if (argv[i] == "--debug") { - option_debug = 1; - argv[i] = ""; - } - if (argv[i] == "--nitcount") { - option_nitcount = 1; - argv[i] = ""; - } - if (argv[i] == "--pass1") { - option_pass1 = 1; - argv[i] = ""; - } - if (argv[i] == "--verbose") { - option_verbose++; - argv[i] = ""; - } - if (argv[i] == "--list-matches") { - option_list_matches = 1; - argv[i] = ""; - } - if (argv[i] == "--year") { - option_year = argv[i+1]; - argv[i] = ""; - argv[i+1] = ""; - } - if (argv[i] == "--checklistwarn") { - option_checklistwarn++; - argv[i] = ""; - } - if (argv[i] == "--submitcheck") { - option_submitcheck++; - argv[i] = ""; - } - if (argv[i] == "--status") { - option_status = argv[i+1]; - argv[i] = ""; - argv[i+1] = ""; - } - if (argv[i] == "--nonascii") { - option_nonascii = 1; - argv[i] = ""; - } - if (argv[i] == "--ascii") { - option_nonascii = 0; - argv[i] = ""; - } - if (argv[i] == "--") { - argv[i] = ""; - } - if (argv[i] ~ "^-.+") { - printf "\nUnknown option: %s\n\n", argv[i]; - usage(); - exit 1; - } - if (argv[i] ~ "^--.+") { - printf "\nUnknown option: %s\n\n", argv[i]; - usage(); - exit 1; - } - } - option_pass2 = ! option_pass1; - - split("SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US", controlchar) - for (i in controlchar) { - controlchar[sprintf("%c",i+0)] = controlchar[i]; - delete controlchar[i]; - } - - split("January February March April May June July August September October November December", monthnames); - for (i in monthnames) { - mn = monthnames[i]; - month[mn] = i; - month[substr(mn, 1, 3)] = i; - } - doc_date = 0; - - # Extract a list of hyphenated words from the document, and build an array of valid fragments - if ( length(option_filename) ) { - cmd = sprintf("cat %s | sed 's/[^A-Za-z0-9_-]/\\n/g' | sort | uniq | egrep -- '-' | egrep -v -- '-$' | egrep '^[A-Za-z0-9]'", option_filename ) - while ( cmd | getline > 0 ) { - word = $0 - frag = "" - for (;;) { - if ( length(word) == 0 ) break - - pos = index(word, "-") - if ( pos == 0 ) break - - frag = frag substr(word, 1, pos ) - hyphenfrags[frag] - has_hyphenlist = 1 - word = substr(word, pos+1) - } - } - } - - # get current year - if ( option_year > 1990 ) { - year = option_year; - } else if ( "date +'%Y'" | getline year <= 0 ) { - year = "[0-9]+" - } - - # establish the format we expect references to have, for later use - has_refs = 0; - one_ref_format = "(([0-9A-Z-]|I-?D.)[0-9A-Za-z-]*( [0-9A-Z-]+)?|(IEEE|ieee)[A-Za-z0-9.-]+|(ITU ?|ITU-T ?|G\\.)[A-Za-z0-9.-]+)"; - reference_format = "\\[" one_ref_format "(, ?" one_ref_format ")*\\]"; - abnf_rule_format = "^ +([A-Za-z0-9-]+ *=|;).*"; - imap_rule_format = "^ *S: (\\*|[A-Za-z0-9]+) (OK|NO|BAD|PREAUTH|BYE) \\[[-A-Za-z]+\\]"; - code_start_format = "()"; - code_end_format = "()"; - inline_code_format = "(/\\*|\\*/|^ *#)" - - # read obsoleted RFC information from file - if (obslist) { - while ( getline < obslist > 0 ) { - oldrfc = $1; $1 = ""; - obsoleted[oldrfc] = $0; - } - } else { - obsoleted[""] = ""; - } - - # read the rfc status information from file - if (statusfile) { - while ( getline < statusfile > 0 ) { - rfcstatus = rfcstatus $0; - } - } else { - rfcstatus = ""; - } - - # read exception RFC information from file - if (exclist) { - while ( getline < exclist > 0 ) { - exception[$1] = $1; - } - } else { - exception[""] = ""; - } - - status2code["bcp"] = "B"; - status2code["best current"] = "B"; - status2code["best current practice"] = "B"; - status2code["experimental"] = "E"; - status2code["experimental track"] = "E"; - status2code["informational"] = "I"; - status2code["ps"] = "P"; - status2code["proposed standard"] = "P"; - status2code["proposed standards"] = "P"; - status2code["standards track"] = "P"; - status2code["standard track"] = "P"; - status2code["ds"] = "D"; - status2code["draft standard"] = "D"; - status2code["standard"] = "S"; - status2code["full standard"] = "S"; - status2code["historic"] = "H"; - status2code["not issued"] = "N"; - - code2status["O"] = "Obsolete"; - code2status["U"] = "Unknown state"; - code2status["E"] = "Experimental"; - code2status["I"] = "Informational"; - code2status["B"] = "Best Current Practice"; - code2status["P"] = "Proposed Standard"; - code2status["D"] = "Draft Standard"; - code2status["S"] = "Full Standard"; - code2status["H"] = "Historic"; - code2status["N"] = "Not Issued"; - - warncodes["H"] = "N"; - warncodes["E"] = "N O"; - warncodes["I"] = "N O"; - warncodes["B"] = "N E I O U H"; - warncodes["P"] = "N E I O U H"; - warncodes["D"] = "N E I O U H P"; - warncodes["S"] = "N E I P U H P D"; - - split("B P D S", ietfstreamcodes) - - has[""]; # make sure this exists as a global variable here - seen_ref[""]; - miss_ref[""]; - - # ------------------------------------------------------------------ - # 3978 and 3979 section texts - # - - bp["any_text"] = ".*" - - bp["rfc3667_3_claim"] = "This document is an Internet-Draft and is subject to all provisions " \ - "of (S|s)ection 3 of( | \\])RFC( |.?)(3667|3667\\])\\.$"; - - bp["rfc3667_5_1"] = "By submitting this Internet-Draft, (I|we) certify that any applicable " \ - "patent or other IPR claims of which (I am|we are) aware have been disclosed,( or " \ - "will be disclosed,)? and any of which (I|we) become aware will be disclosed, " \ - "in accordance with RFC 3668.$"; - - bp["rfc3978_5_1"] = "By submitting this Internet-Draft, each author represents that any " \ - "applicable patent or other IPR claims of which he or she is aware " \ - "have been or will be disclosed, and any of which he or she becomes " \ - "aware will be disclosed, in accordance with Section 6 of BCP 79.$"; - - bp["rfc3978_5_1_a"] = "By submitting this Internet-Draft, (each|the) author represents that any " \ - "applicable patent or other IPR claims of which (he or she|he|she) is aware " \ - "have been or will be disclosed, and any of which (he or she|he|she) becomes? " \ - "aware will be disclosed, in accordance with( (S|s)ection 6 of)? (BCP 79|RFC 3979|RFC 3668).$"; - - bp["rfc3978_5_2a"] = "This document may not be modified, and derivative works of it may " \ - "not be created, except to publish it as an RFC and to translate it " \ - "into languages other than English\\.$"; - - bp["rfc3978_5_2ax"] = "This document may not be modified, and derivative works of it may " \ - "not be created, except to publish it as an RFC and to translate it " \ - "into languages other than English other than to extract section " \ - "[0-9.]+ as-is for separate use\\.$"; - - bp["rfc3978_5_2b"] = "This document may not be modified, and derivative works of it may " \ - "not be created\\.$"; - - bp["rfc3978_5_2bx"] = "This document may not be modified, and derivative works of it may " \ - "not be created other than to extract section [0-9.]+ as-is for separate use.$"; - - bp["rfc3978_5_3"] = "This document may only be posted in an Internet-Draft.$"; - - bp["rfc3978_5_4_p1"] = "Copyright \\(C\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?.$" - - bp["rfc3978_5_4_p1_u4748"] = "Copyright \\(C\\) The IETF Trust \\(?[0-9][0-9][0-9][0-9]\\)?.$" - - bp["rfc3978_5_4_p1_e"] = ".+Copyright \\(C\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?\\..+" - - bp["rfc3978_5_4_p1_u4748_e"] = ".+Copyright \\(C\\) The IETF Trust \\(?[0-9][0-9][0-9][0-9]\\)?\\..+" - - bp["rfc3978_5_4_p1_now"] = sprintf("Copyright \\(C\\) The Internet Society \\(?%s\\)?", year); - - bp["rfc3978_5_4_p1_u4748_now"] = sprintf("Copyright \\(C\\) The IETF Trust \\(?%s\\)?", year); - - bp["trust-16-oct-2008_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " \ - "the persons identified as the document authors", year); - - bp["trust-12-feb-2009_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " \ - "the persons identified as the document authors", year); - - bp["trust-12-sep-2009_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " \ - "the persons identified as the document authors.", year); - - bp["trust-28-dec-2009_6_b_i_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " \ - "the persons identified as the document authors.", year); - -# ---------------------------------------------------------------------------------------------- - - bp["rfc3978_5_4_p2"] = "This document is subject to the rights, licenses and restrictions contained in BCP " \ - "78, and except as set forth therein, the authors retain all their rights.$"; - - bp["rfc3978_5_5"] = "This document and the information contained herein are provided " \ - "on an \"AS IS\" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE " \ - "REPRESENTS OR IS SPONSORED BY \\(IF ANY\\), THE INTERNET SOCIETY AND " \ - "THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, " \ - "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT " \ - "THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR " \ - "ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " \ - "PARTICULAR PURPOSE.$"; - - bp["rfc3978_5_5_u4748"] = "This document and the information contained herein are provided " \ - "on an \"AS IS\" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE " \ - "REPRESENTS OR IS SPONSORED BY \\(IF ANY\\), THE INTERNET SOCIETY, THE IETF TRUST AND " \ - "THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, " \ - "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT " \ - "THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR " \ - "ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " \ - "PARTICULAR PURPOSE.$"; - - bp["rfc3979_5_p1"] = "The IETF takes no position regarding the validity or scope of any " \ - "Intellectual Property Rights or other rights that might be claimed " \ - "to pertain to the implementation or use of the technology " \ - "described in this document or the extent to which any license " \ - "under such rights might or might not be available; nor does it " \ - "represent that it has made any independent effort to identify any " \ - "such rights. Information on the procedures with respect to rights " \ - "in RFC documents can be found in BCP 78 and BCP 79.$"; - - bp["rfc3979_5_p2"] = "Copies of IPR disclosures made to the IETF Secretariat and any " \ - "assurances of licenses to be made available, or the result of an " \ - "attempt made to obtain a general license or permission for the use " \ - "of such proprietary rights by implementers or users of this " \ - "specification can be obtained from the IETF on-line IPR repository " \ - "at https?://www.ietf.org/ipr.$"; - - bp["rfc3979_5_p3"] = "The IETF invites any interested party to bring to its attention " \ - "any copyrights, patents or patent applications, or other " \ - "proprietary rights that may cover technology that may be required " \ - "to implement this standard. Please address the information to the " \ - "IETF at ietf-ipr@ietf.org.$"; - -# ---------------------------------------------------------------------------------------------- - - bp["trust-16-oct-2008_6_a"] = "This Internet-Draft is submitted to IETF in full " \ - "conformance with the provisions of BCP 78 and BCP 79\\.$"; - - bp["trust-16-oct-2008_6_b_p2"] = "Copyright \\(c\\) [0-9][0-9][0-9][0-9] IETF Trust and " \ - "the persons identified as the document authors\\. All rights reserved\\.$"; - - bp["trust-16-oct-2008_6_b_p3"] = "This document is subject to BCP 78 and the " \ - "IETF Trust's Legal Provisions Relating to IETF Documents " \ - "\\(http://trustee.ietf.org/license-inf(o|o/)\\) " \ - "in effect on the date of publication of this document. " \ - "Please review these documents " \ - "carefully, as they describe your rights and restrictions with respect to " \ - "this document\\.$"; - - bp["trust-16-oct-2008_6_c_i"] = "This document may not be modified, and derivative " \ - "works of it may not be created, except to format it for publication " \ - "as an RFC and to translate it into languages other than English\\.$"; - -# ---------------------------------------------------------------------------------------------- - - bp["trust-12-feb-2009_6_a"] = bp["trust-16-oct-2008_6_a"] - bp["trust-12-feb-2009_6_b_p2"] = bp["trust-16-oct-2008_6_b_p2"] - - bp["trust-12-feb-2009_6_b_p3"] = \ - "This document is subject to BCP 78 and the IETF Trust's Legal " \ - "Provisions Relating to IETF Documents in effect on the date of " \ - "publication of this document \\(http://trustee.ietf.org/license-inf(o|o/)\\)\\. " \ - "Please review these documents carefully, as they describe your " \ - "rights and restrictions with respect to this document\\.$" - - bp["trust-12-feb-2009_6_c_i"] = "This document may not be modified, and derivative " \ - "works of it may not be created, except to format it for publication " \ - "as an RFC or to translate it into languages other than English\\.$"; - - bp["trust-12-feb-2009_6_c_ii"] = "This document may not be modified, and " \ - "derivative works of it may not be created, and it may not be published " \ - "except as an Internet-Draft\\.$" - - bp["trust-12-feb-2009_6_c_iii"] = \ - "This document may contain material from IETF Documents or IETF " \ - "Contributions published or made publicly available before November " \ - "10, 2008\\. The person\\(s\\) controlling the copyright in some of this " \ - "material may not have granted the IETF Trust the right to allow " \ - "modifications of such material outside the IETF Standards Process\\. " \ - "Without obtaining an adequate license from the person\\(s\\) " \ - "controlling the copyright in such materials, this document may not " \ - "be modified outside the IETF Standards Process, and derivative " \ - "works of it may not be created outside the IETF Standards Process, " \ - "except to format it for publication as an RFC or to translate it " \ - "into languages other than English\\.$" - -# ---------------------------------------------------------------------------------------------- - - bp["trust-12-sep-2009_6_a"] = bp["trust-12-feb-2009_6_a"] - bp["trust-12-sep-2009_6_b_p2"] = bp["trust-12-feb-2009_6_b_p2"] - bp["trust-12-sep-2009_6_c_i"] = bp["trust-12-feb-2009_6_c_i"] - bp["trust-12-sep-2009_6_c_ii"] = bp["trust-12-feb-2009_6_c_ii"] - bp["trust-12-sep-2009_6_c_iii"] = bp["trust-12-feb-2009_6_c_iii"] - - bp["trust-12-sep-2009_6_b_p3"] = \ - "This document is subject to BCP 78 and the IETF Trust's Legal " \ - "Provisions Relating to IETF Documents \\(https?://trustee.ietf.org/license-inf(o|o/)\\) " \ - "in effect on the date of publication of this document\\. " \ - "Please review these documents carefully, as they describe your " \ - "rights and restrictions with respect to this document\\. " \ - "Code Components extracted from this document must include " \ - "(Simplified|Revised) BSD License text as described in Section 4.e of the " \ - "Trust Legal Provisions and are provided without warranty as described " \ - "in the BSD License\\.$" - - -# ---------------------------------------------------------------------------------------------- - - bp["trust-28-dec-2009_6_b_i_p2"] = bp["trust-12-sep-2009_6_b_p2"] - bp["trust-28-dec-2009_6_c_i"] = bp["trust-12-sep-2009_6_c_i"] - bp["trust-28-dec-2009_6_c_ii"] = bp["trust-12-sep-2009_6_c_ii"] - bp["trust-28-dec-2009_6_c_iii"] = bp["trust-12-sep-2009_6_c_iii"] - - bp["trust-28-dec-2009_6_a"] = "This Internet-Draft is submitted in full " \ - "conformance with the provisions of BCP 78 and BCP 79\\.$"; - - # This applies to the IETF stream - bp["trust-28-dec-2009_6_b_i_p3"] = \ - "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " \ - "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " \ - "in effect on the date of publication of this document\\. " \ - "Please review these documents carefully, as they describe your " \ - "rights and restrictions with respect to this document\\. " \ - "Code Components extracted from this document must include " \ - "(Simplified|Revised) BSD License text as described in Section 4.e of the " \ - "Trust Legal Provisions and are provided without warranty as described " \ - "in the (Simplified|Revised) BSD License\\.$" - - # This applies to non-IETF streams - bp["trust-28-dec-2009_6_b_ii_p3"] = \ - "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " \ - "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " \ - "in effect on the date of publication of this document\\. " \ - "Please review these documents carefully, as they describe your " \ - "rights and restrictions with respect to this document\\.$" - -# ---------------------------------------------------------------------------------------------- - - bp["rfc2026_10_4A"] = "The IETF takes no position regarding the validity or scope of " \ - "any intellectual property or other rights that might be claimed " \ - "to pertain to the implementation or use of the technology " \ - "described in this document or the extent to which any license " \ - "under such rights might or might not be available; neither does " \ - "it represent that it has made any effort to identify any such " \ - "rights. Information on the IETF\047s procedures with respect to " \ - "rights in standards-track and standards-related documentation " \ - "can be found in BCP-11. Copies of claims of rights made " \ - "available for publication and any assurances of licenses to " \ - "be made available, or the result of an attempt made " \ - "to obtain a general license or permission for the use of such " \ - "proprietary rights by implement[oe]rs or users of this " \ - "specification can be obtained from the IETF Secretariat.$"; - - bp["rfc2026_10_4B"] = "The IETF invites any interested party to bring to its " \ - "attention any copyrights, patents or patent applications, or " \ - "other proprietary rights which may cover technology that may be " \ - "required to practice this standard. Please address the " \ - "information to the IETF Executive Director.$"; - - bp["rfc2026_10_4C_p1"] = "Copyright \\([Cc]\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?. All Rights " \ - "Reserved.$"; - - bp["rfc2026_10_4C_p2"] = "This document and translations of it may be copied and " \ - "furnished to others, and derivative works that comment on or " \ - "otherwise explain it or assist in its implementation may be " \ - "prepared, copied, published and distributed, in whole or in " \ - "part, without restriction of any kind, provided that the above " \ - "copyright notice and this paragraph are included on all such " \ - "copies and derivative works. However, this document itself may " \ - "not be modified in any way, such as by removing the copyright " \ - "notice or references to the Internet Society or other Internet " \ - "organizations, except as needed for the purpose of developing " \ - "Internet standards in which case the procedures for copyrights " \ - "defined in the Internet Standards process must be followed, or " \ - "as required to translate it into languages other than English.$"; - - bp["rfc2026_10_4C_p3"] = "The limited permissions granted above are perpetual and will " \ - "not be revoked by the Internet Society or its successors or " \ - "assign(ee)?s.$"; - - bp["rfc2026_10_4C_p4"] = "This document and the information contained herein is provided " \ - "on an \"AS IS\" basis and THE INTERNET SOCIETY AND THE INTERNET " \ - "ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR " \ - "IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE " \ - "OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY " \ - "IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " \ - "PARTICULAR PURPOSE.$"; - - bp["rfc2026_10_4D"] = "The IETF has been notified of intellectual property rights " \ - "claimed in regard to some or all of the specification contained " \ - "in this document. For more information consult the online list " \ - "of claimed rights.$"; - - bp["rfc2026_claim"] = "This document is an Internet-Draft and is in full conformance " \ - "with all provisions of Section 10 of( | \\])RFC( |.?)(2026|2026\\])\\."; - - bp["rfc2026_lax_claim"] = "This document is an Internet-Draft and is in full conformance " \ - "with all provisions of Section 10 of( | \\])RFC( |.?)(2026|2026\\])( ?\\[[0-9]+\\].*)?."; - - bp["rfc2026b_claim"] = "This document is an Internet-Draft and is subject to all provisions " \ - "of Section 10 of( | \\])RFC( |.?)(2026|2026\\])\\."; - - bp["rfc2026b_lax_claim"] = "This document is an Internet-Draft and is subject to all provisions " \ - "of Section 10 of( | \\])RFC( |.?)(2026|2026\\])( ?\\[[0-9]+\\].*)?."; - - bp["rfc3978_3_claim"] = "This document is an Internet-Draft and is subject to all provisions " \ - "of (S|s)ection 3 of( | \\])RFC( |.?)(3978|3978\\])\\.$"; - - bp["rfc2119_p2"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", " \ - "\"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\",( | \"NOT RECOMMENDED\", )\"MAY\", " \ - "and \"OPTIONAL\" in this document are to be interpreted as described in" \ - "( | \\[| BCP 14, | BCP 14, \\[)RFC( |.?)2119(\\.|.*\\.|\\].*\\.)$"; - - bp["rfc2119_p2a"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", " \ - "\"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\",( | \"NOT RECOMMENDED\", )\"MAY\", " \ - "and \"OPTIONAL\" in this document are to be interpreted as described in " \ - "(['\"]?Key words for use in RFCs to Indicate Requirement Levels['\"]? )?" \ - "\\[[0-9A-Z-][0-9A-Za-z-]* ?[0-9A-Z-]*\\].*\\.$"; - - # This is from RFC 8174 which updates 2119: - bp["rfc8174_p11"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL " \ - "NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"NOT RECOMMENDED\", " \ - "\"MAY\", and \"OPTIONAL\" in this document are to be interpreted as " \ - "described in BCP 14 \\[RFC2119\\] ?\\[RFC8174\\] when, and only when, they " \ - "appear in all capitals, as shown here."; - - bp["1id_guidelines_p1"] = "Internet-Drafts are working documents of the Internet Engineering " \ - "Task Force \\(IETF\\), its areas, and its working groups. Note that other " \ - "groups may also distribute working documents as Internet-Drafts.$"; - - bp["1id_guidelines_p1a"] = "Internet-Drafts are working documents of the Internet Engineering " \ - "Task Force \\(IETF\\). Note that other groups may also distribute " \ - "working documents as Internet-Drafts. The list of current "\ - "Internet-Drafts is at https?://datatracker.ietf.org/drafts/current/? ?\\.$"; - - bp["1id_guidelines_p2"] = "Internet-Drafts are draft documents valid for a maximum of six months " \ - "and may be updated, replaced, or obsoleted by other documents at any " \ - "time. It is inappropriate to use Internet-Drafts as reference " \ - "material or to cite them other than as \"?work in progress(\\.\"|\"?\\.)$"; - - bp["1id_guidelines_p2a"] = "Internet-Drafts are draft documents valid for a maximum of six months " \ - "and may be updated, replaced, or obsoleted by other documents at any " \ - "time. It is inappropriate to use Internet-Drafts as reference " \ - "material or to cite them other than as \"?work in progress(\\.\"|\"?\\.)$"; - - bp["1id_guidelines_p3"] = "The list of current Internet-Drafts can be accessed at " \ - "https?://www.ietf.org/1id-abstracts.html$"; - - bp["1id_guidelines_p3a"] = "The list of current Internet-Drafts can be accessed at:? " \ - "https?:// *www.ietf.org/ *(ietf/)?1id-abstracts.(txt|html) ?\\.?$"; - - bp["1id_guidelines_p4"] = "The list of Internet-Draft Shadow Directories can be accessed at " \ - "https?://www.ietf.org/shadow.html$"; - - bp["1id_guidelines_p4a"] = "The list of Internet-Draft Shadow Directories can be accessed at:? " \ - "https?:// *www.ietf.org/ *shadow.html ?\\.?$"; + option_verbose = 0 + option_warn = 1 + option_nonascii = 0 + split(ENVIRON["CHECKNITS"], argv, FS) + columns = ENVIRON["COLUMNS"] + if (! columns) { + columns = 78 + } + if (columns > 80) { + columns = 80 + } + if (columns < 16) { + columns = 16 + } + if (columns < 73) { + bpcols = columns + } else { + bpcols = 73 + } + indentation = 8 + errmark = "**" + flawmark = "~~" + warnmark = "==" + infomark = "--" + notemark = " " + for (i in argv) { + # Deprecated + if (argv[i] == "--rfc3667") { + printf "\nOption %s does nothing any more\n", argv[i] + argv[i] = "" + } + if (argv[i] == "--no3667") { + printf "\nOption %s does nothing any more\n", argv[i] + argv[i] = "" + } + if (argv[i] == "--rfc2026") { + printf "\nOption %s does nothing any more\n", argv[i] + argv[i] = "" + } + if (argv[i] == "--nowarn") { + option_warn = 0 + argv[i] = "" + } + if (argv[i] == "--filename") { + option_filename = argv[i + 1] + argv[i] = "" + argv[i + 1] = "" + } + if (argv[i] == "--debug") { + option_debug = 1 + argv[i] = "" + } + if (argv[i] == "--nitcount") { + option_nitcount = 1 + argv[i] = "" + } + if (argv[i] == "--pass1") { + option_pass1 = 1 + argv[i] = "" + } + if (argv[i] == "--verbose") { + option_verbose++ + argv[i] = "" + } + if (argv[i] == "--list-matches") { + option_list_matches = 1 + argv[i] = "" + } + if (argv[i] == "--year") { + option_year = argv[i + 1] + argv[i] = "" + argv[i + 1] = "" + } + if (argv[i] == "--checklistwarn") { + option_checklistwarn++ + argv[i] = "" + } + if (argv[i] == "--submitcheck") { + option_submitcheck++ + argv[i] = "" + } + if (argv[i] == "--status") { + option_status = argv[i + 1] + argv[i] = "" + argv[i + 1] = "" + } + if (argv[i] == "--nonascii") { + option_nonascii = 1 + argv[i] = "" + } + if (argv[i] == "--ascii") { + option_nonascii = 0 + argv[i] = "" + } + if (argv[i] == "--") { + argv[i] = "" + } + if (argv[i] ~ "^-.+") { + printf "\nUnknown option: %s\n\n", argv[i] + usage() + exit 1 + } + if (argv[i] ~ "^--.+") { + printf "\nUnknown option: %s\n\n", argv[i] + usage() + exit 1 + } + } + option_pass2 = ! option_pass1 + split("SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US", controlchar, FS) + for (i in controlchar) { + controlchar[sprintf("%c", i + 0)] = controlchar[i] + delete controlchar[i] + } + split("January February March April May June July August September October November December", monthnames, FS) + for (i in monthnames) { + mn = monthnames[i] + month[mn] = i + month[substr(mn, 1, 3)] = i + } + doc_date = 0 + # Extract a list of hyphenated words from the document, and build an array of valid fragments + if (length(option_filename)) { + cmd = sprintf("cat %s | sed 's/[^A-Za-z0-9_-]/\\n/g' | sort | uniq | egrep -- '-' | egrep -v -- '-$' | egrep '^[A-Za-z0-9]'", option_filename) + while ((cmd | getline) > 0) { + word = $0 + frag = "" + for (;;) { + if (length(word) == 0) { + break + } + pos = index(word, "-") + if (pos == 0) { + break + } + frag = frag substr(word, 1, pos) + hyphenfrags[frag] + has_hyphenlist = 1 + word = substr(word, pos + 1) + } + } + } + # get current year + if (option_year > 1990) { + year = option_year + } else if (("date +'%Y'" | getline year) <= 0) { + year = "[0-9]+" + } + # establish the format we expect references to have, for later use + has_refs = 0 + one_ref_format = "(([0-9A-Z-]|I-?D.)[0-9A-Za-z-]*( [0-9A-Z-]+)?|(IEEE|ieee)[A-Za-z0-9.-]+|(ITU ?|ITU-T ?|G\\.)[A-Za-z0-9.-]+)" + reference_format = "\\[" one_ref_format "(, ?" one_ref_format ")*\\]" + abnf_rule_format = "^ +([A-Za-z0-9-]+ *=|;).*" + imap_rule_format = "^ *S: (\\*|[A-Za-z0-9]+) (OK|NO|BAD|PREAUTH|BYE) \\[[-A-Za-z]+\\]" + code_start_format = "()" + code_end_format = "()" + inline_code_format = "(/\\*|\\*/|^ *#)" + # read obsoleted RFC information from file + if (obslist) { + while ((getline < obslist) > 0) { + oldrfc = $1 + $1 = "" + obsoleted[oldrfc] = $0 + } + } else { + obsoleted[""] = "" + } + # read the rfc status information from file + if (statusfile) { + while ((getline < statusfile) > 0) { + rfcstatus = rfcstatus $0 + } + } else { + rfcstatus = "" + } + # read exception RFC information from file + if (exclist) { + while ((getline < exclist) > 0) { + exception[$1] = $1 + } + } else { + exception[""] = "" + } + status2code["bcp"] = "B" + status2code["best current"] = "B" + status2code["best current practice"] = "B" + status2code["experimental"] = "E" + status2code["experimental track"] = "E" + status2code["informational"] = "I" + status2code["ps"] = "P" + status2code["proposed standard"] = "P" + status2code["proposed standards"] = "P" + status2code["standards track"] = "P" + status2code["standard track"] = "P" + status2code["ds"] = "D" + status2code["draft standard"] = "D" + status2code["standard"] = "S" + status2code["full standard"] = "S" + status2code["historic"] = "H" + status2code["not issued"] = "N" + code2status["O"] = "Obsolete" + code2status["U"] = "Unknown state" + code2status["E"] = "Experimental" + code2status["I"] = "Informational" + code2status["B"] = "Best Current Practice" + code2status["P"] = "Proposed Standard" + code2status["D"] = "Draft Standard" + code2status["S"] = "Full Standard" + code2status["H"] = "Historic" + code2status["N"] = "Not Issued" + warncodes["H"] = "N" + warncodes["E"] = "N O" + warncodes["I"] = "N O" + warncodes["B"] = "N E I O U H" + warncodes["P"] = "N E I O U H" + warncodes["D"] = "N E I O U H P" + warncodes["S"] = "N E I P U H P D" + split("B P D S", ietfstreamcodes, FS) + has[""] # make sure this exists as a global variable here + seen_ref[""] + miss_ref[""] + # ------------------------------------------------------------------ + # 3978 and 3979 section texts + # + bp["any_text"] = ".*" + bp["rfc3667_3_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of (S|s)ection 3 of( | \\])RFC( |.?)(3667|3667\\])\\.$" + bp["rfc3667_5_1"] = "By submitting this Internet-Draft, (I|we) certify that any applicable " "patent or other IPR claims of which (I am|we are) aware have been disclosed,( or " "will be disclosed,)? and any of which (I|we) become aware will be disclosed, " "in accordance with RFC 3668.$" + bp["rfc3978_5_1"] = "By submitting this Internet-Draft, each author represents that any " "applicable patent or other IPR claims of which he or she is aware " "have been or will be disclosed, and any of which he or she becomes " "aware will be disclosed, in accordance with Section 6 of BCP 79.$" + bp["rfc3978_5_1_a"] = "By submitting this Internet-Draft, (each|the) author represents that any " "applicable patent or other IPR claims of which (he or she|he|she) is aware " "have been or will be disclosed, and any of which (he or she|he|she) becomes? " "aware will be disclosed, in accordance with( (S|s)ection 6 of)? (BCP 79|RFC 3979|RFC 3668).$" + bp["rfc3978_5_2a"] = "This document may not be modified, and derivative works of it may " "not be created, except to publish it as an RFC and to translate it " "into languages other than English\\.$" + bp["rfc3978_5_2ax"] = "This document may not be modified, and derivative works of it may " "not be created, except to publish it as an RFC and to translate it " "into languages other than English other than to extract section " "[0-9.]+ as-is for separate use\\.$" + bp["rfc3978_5_2b"] = "This document may not be modified, and derivative works of it may " "not be created\\.$" + bp["rfc3978_5_2bx"] = "This document may not be modified, and derivative works of it may " "not be created other than to extract section [0-9.]+ as-is for separate use.$" + bp["rfc3978_5_3"] = "This document may only be posted in an Internet-Draft.$" + bp["rfc3978_5_4_p1"] = "Copyright \\(C\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?.$" + bp["rfc3978_5_4_p1_u4748"] = "Copyright \\(C\\) The IETF Trust \\(?[0-9][0-9][0-9][0-9]\\)?.$" + bp["rfc3978_5_4_p1_e"] = ".+Copyright \\(C\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?\\..+" + bp["rfc3978_5_4_p1_u4748_e"] = ".+Copyright \\(C\\) The IETF Trust \\(?[0-9][0-9][0-9][0-9]\\)?\\..+" + bp["rfc3978_5_4_p1_now"] = sprintf("Copyright \\(C\\) The Internet Society \\(?%s\\)?", year) + bp["rfc3978_5_4_p1_u4748_now"] = sprintf("Copyright \\(C\\) The IETF Trust \\(?%s\\)?", year) + bp["trust-16-oct-2008_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors", year) + bp["trust-12-feb-2009_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors", year) + bp["trust-12-sep-2009_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors.", year) + bp["trust-28-dec-2009_6_b_i_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors.", year) + # ---------------------------------------------------------------------------------------------- + bp["rfc3978_5_4_p2"] = "This document is subject to the rights, licenses and restrictions contained in BCP " "78, and except as set forth therein, the authors retain all their rights.$" + bp["rfc3978_5_5"] = "This document and the information contained herein are provided " "on an \"AS IS\" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE " "REPRESENTS OR IS SPONSORED BY \\(IF ANY\\), THE INTERNET SOCIETY AND " "THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, " "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT " "THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR " "ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" + bp["rfc3978_5_5_u4748"] = "This document and the information contained herein are provided " "on an \"AS IS\" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE " "REPRESENTS OR IS SPONSORED BY \\(IF ANY\\), THE INTERNET SOCIETY, THE IETF TRUST AND " "THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, " "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT " "THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR " "ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" + bp["rfc3979_5_p1"] = "The IETF takes no position regarding the validity or scope of any " "Intellectual Property Rights or other rights that might be claimed " "to pertain to the implementation or use of the technology " "described in this document or the extent to which any license " "under such rights might or might not be available; nor does it " "represent that it has made any independent effort to identify any " "such rights. Information on the procedures with respect to rights " "in RFC documents can be found in BCP 78 and BCP 79.$" + bp["rfc3979_5_p2"] = "Copies of IPR disclosures made to the IETF Secretariat and any " "assurances of licenses to be made available, or the result of an " "attempt made to obtain a general license or permission for the use " "of such proprietary rights by implementers or users of this " "specification can be obtained from the IETF on-line IPR repository " "at https?://www.ietf.org/ipr.$" + bp["rfc3979_5_p3"] = "The IETF invites any interested party to bring to its attention " "any copyrights, patents or patent applications, or other " "proprietary rights that may cover technology that may be required " "to implement this standard. Please address the information to the " "IETF at ietf-ipr@ietf.org.$" + # ---------------------------------------------------------------------------------------------- + bp["trust-16-oct-2008_6_a"] = "This Internet-Draft is submitted to IETF in full " "conformance with the provisions of BCP 78 and BCP 79\\.$" + bp["trust-16-oct-2008_6_b_p2"] = "Copyright \\(c\\) [0-9][0-9][0-9][0-9] IETF Trust and " "the persons identified as the document authors\\. All rights reserved\\.$" + bp["trust-16-oct-2008_6_b_p3"] = "This document is subject to BCP 78 and the " "IETF Trust's Legal Provisions Relating to IETF Documents " "\\(http://trustee.ietf.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document. " "Please review these documents " "carefully, as they describe your rights and restrictions with respect to " "this document\\.$" + bp["trust-16-oct-2008_6_c_i"] = "This document may not be modified, and derivative " "works of it may not be created, except to format it for publication " "as an RFC and to translate it into languages other than English\\.$" + # ---------------------------------------------------------------------------------------------- + bp["trust-12-feb-2009_6_a"] = bp["trust-16-oct-2008_6_a"] + bp["trust-12-feb-2009_6_b_p2"] = bp["trust-16-oct-2008_6_b_p2"] + bp["trust-12-feb-2009_6_b_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal " "Provisions Relating to IETF Documents in effect on the date of " "publication of this document \\(http://trustee.ietf.org/license-inf(o|o/)\\)\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" + bp["trust-12-feb-2009_6_c_i"] = "This document may not be modified, and derivative " "works of it may not be created, except to format it for publication " "as an RFC or to translate it into languages other than English\\.$" + bp["trust-12-feb-2009_6_c_ii"] = "This document may not be modified, and " "derivative works of it may not be created, and it may not be published " "except as an Internet-Draft\\.$" + bp["trust-12-feb-2009_6_c_iii"] = "This document may contain material from IETF Documents or IETF " "Contributions published or made publicly available before November " "10, 2008\\. The person\\(s\\) controlling the copyright in some of this " "material may not have granted the IETF Trust the right to allow " "modifications of such material outside the IETF Standards Process\\. " "Without obtaining an adequate license from the person\\(s\\) " "controlling the copyright in such materials, this document may not " "be modified outside the IETF Standards Process, and derivative " "works of it may not be created outside the IETF Standards Process, " "except to format it for publication as an RFC or to translate it " "into languages other than English\\.$" + # ---------------------------------------------------------------------------------------------- + bp["trust-12-sep-2009_6_a"] = bp["trust-12-feb-2009_6_a"] + bp["trust-12-sep-2009_6_b_p2"] = bp["trust-12-feb-2009_6_b_p2"] + bp["trust-12-sep-2009_6_c_i"] = bp["trust-12-feb-2009_6_c_i"] + bp["trust-12-sep-2009_6_c_ii"] = bp["trust-12-feb-2009_6_c_ii"] + bp["trust-12-sep-2009_6_c_iii"] = bp["trust-12-feb-2009_6_c_iii"] + bp["trust-12-sep-2009_6_b_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal " "Provisions Relating to IETF Documents \\(https?://trustee.ietf.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "(Simplified|Revised) BSD License text as described in Section 4.e of the " "Trust Legal Provisions and are provided without warranty as described " "in the BSD License\\.$" + # ---------------------------------------------------------------------------------------------- + bp["trust-28-dec-2009_6_b_i_p2"] = bp["trust-12-sep-2009_6_b_p2"] + bp["trust-28-dec-2009_6_c_i"] = bp["trust-12-sep-2009_6_c_i"] + bp["trust-28-dec-2009_6_c_ii"] = bp["trust-12-sep-2009_6_c_ii"] + bp["trust-28-dec-2009_6_c_iii"] = bp["trust-12-sep-2009_6_c_iii"] + bp["trust-28-dec-2009_6_a"] = "This Internet-Draft is submitted in full " "conformance with the provisions of BCP 78 and BCP 79\\.$" + # This applies to the IETF stream + bp["trust-28-dec-2009_6_b_i_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "(Simplified|Revised) BSD License text as described in Section 4.e of the " "Trust Legal Provisions and are provided without warranty as described " "in the (Simplified|Revised) BSD License\\.$" + # This applies to non-IETF streams + bp["trust-28-dec-2009_6_b_ii_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" + # ---------------------------------------------------------------------------------------------- + bp["rfc2026_10_4A"] = "The IETF takes no position regarding the validity or scope of " "any intellectual property or other rights that might be claimed " "to pertain to the implementation or use of the technology " "described in this document or the extent to which any license " "under such rights might or might not be available; neither does " "it represent that it has made any effort to identify any such " "rights. Information on the IETF's procedures with respect to " "rights in standards-track and standards-related documentation " "can be found in BCP-11. Copies of claims of rights made " "available for publication and any assurances of licenses to " "be made available, or the result of an attempt made " "to obtain a general license or permission for the use of such " "proprietary rights by implement[oe]rs or users of this " "specification can be obtained from the IETF Secretariat.$" + bp["rfc2026_10_4B"] = "The IETF invites any interested party to bring to its " "attention any copyrights, patents or patent applications, or " "other proprietary rights which may cover technology that may be " "required to practice this standard. Please address the " "information to the IETF Executive Director.$" + bp["rfc2026_10_4C_p1"] = "Copyright \\([Cc]\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?. All Rights " "Reserved.$" + bp["rfc2026_10_4C_p2"] = "This document and translations of it may be copied and " "furnished to others, and derivative works that comment on or " "otherwise explain it or assist in its implementation may be " "prepared, copied, published and distributed, in whole or in " "part, without restriction of any kind, provided that the above " "copyright notice and this paragraph are included on all such " "copies and derivative works. However, this document itself may " "not be modified in any way, such as by removing the copyright " "notice or references to the Internet Society or other Internet " "organizations, except as needed for the purpose of developing " "Internet standards in which case the procedures for copyrights " "defined in the Internet Standards process must be followed, or " "as required to translate it into languages other than English.$" + bp["rfc2026_10_4C_p3"] = "The limited permissions granted above are perpetual and will " "not be revoked by the Internet Society or its successors or " "assign(ee)?s.$" + bp["rfc2026_10_4C_p4"] = "This document and the information contained herein is provided " "on an \"AS IS\" basis and THE INTERNET SOCIETY AND THE INTERNET " "ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR " "IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE " "OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY " "IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" + bp["rfc2026_10_4D"] = "The IETF has been notified of intellectual property rights " "claimed in regard to some or all of the specification contained " "in this document. For more information consult the online list " "of claimed rights.$" + bp["rfc2026_claim"] = "This document is an Internet-Draft and is in full conformance " "with all provisions of Section 10 of( | \\])RFC( |.?)(2026|2026\\])\\." + bp["rfc2026_lax_claim"] = "This document is an Internet-Draft and is in full conformance " "with all provisions of Section 10 of( | \\])RFC( |.?)(2026|2026\\])( ?\\[[0-9]+\\].*)?." + bp["rfc2026b_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of Section 10 of( | \\])RFC( |.?)(2026|2026\\])\\." + bp["rfc2026b_lax_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of Section 10 of( | \\])RFC( |.?)(2026|2026\\])( ?\\[[0-9]+\\].*)?." + bp["rfc3978_3_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of (S|s)ection 3 of( | \\])RFC( |.?)(3978|3978\\])\\.$" + bp["rfc2119_p2"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", " "\"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\",( | \"NOT RECOMMENDED\", )\"MAY\", " "and \"OPTIONAL\" in this document are to be interpreted as described in" "( | \\[| BCP 14, | BCP 14, \\[)RFC( |.?)2119(\\.|.*\\.|\\].*\\.)$" + bp["rfc2119_p2a"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", " "\"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\",( | \"NOT RECOMMENDED\", )\"MAY\", " "and \"OPTIONAL\" in this document are to be interpreted as described in " "(['\"]?Key words for use in RFCs to Indicate Requirement Levels['\"]? )?" "\\[[0-9A-Z-][0-9A-Za-z-]* ?[0-9A-Z-]*\\].*\\.$" + # This is from RFC 8174 which updates 2119: + bp["rfc8174_p11"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL " "NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"NOT RECOMMENDED\", " "\"MAY\", and \"OPTIONAL\" in this document are to be interpreted as " "described in BCP 14 \\[RFC2119\\] ?\\[RFC8174\\] when, and only when, they " "appear in all capitals, as shown here." + bp["1id_guidelines_p1"] = "Internet-Drafts are working documents of the Internet Engineering " "Task Force \\(IETF\\), its areas, and its working groups. Note that other " "groups may also distribute working documents as Internet-Drafts.$" + bp["1id_guidelines_p1a"] = "Internet-Drafts are working documents of the Internet Engineering " "Task Force \\(IETF\\). Note that other groups may also distribute " "working documents as Internet-Drafts. The list of current " "Internet-Drafts is at https?://datatracker.ietf.org/drafts/current/? ?\\.$" + bp["1id_guidelines_p2"] = "Internet-Drafts are draft documents valid for a maximum of six months " "and may be updated, replaced, or obsoleted by other documents at any " "time. It is inappropriate to use Internet-Drafts as reference " "material or to cite them other than as \"?work in progress(\\.\"|\"?\\.)$" + bp["1id_guidelines_p2a"] = "Internet-Drafts are draft documents valid for a maximum of six months " "and may be updated, replaced, or obsoleted by other documents at any " "time. It is inappropriate to use Internet-Drafts as reference " "material or to cite them other than as \"?work in progress(\\.\"|\"?\\.)$" + bp["1id_guidelines_p3"] = "The list of current Internet-Drafts can be accessed at " "https?://www.ietf.org/1id-abstracts.html$" + bp["1id_guidelines_p3a"] = "The list of current Internet-Drafts can be accessed at:? " "https?:// *www.ietf.org/ *(ietf/)?1id-abstracts.(txt|html) ?\\.?$" + bp["1id_guidelines_p4"] = "The list of Internet-Draft Shadow Directories can be accessed at " "https?://www.ietf.org/shadow.html$" + bp["1id_guidelines_p4a"] = "The list of Internet-Draft Shadow Directories can be accessed at:? " "https?:// *www.ietf.org/ *shadow.html ?\\.?$" + bad["MUST not"] = "Using lowercase 'not' together with uppercase 'MUST', " "'SHALL', 'SHOULD', or 'RECOMMENDED' is not an " "accepted usage according to RFC 2119. Please use uppercase 'NOT' " "together with RFC 2119 keywords (if that is what you mean)." + bad["SHALL not"] = bad["MUST not"] + bad["SHOULD not"] = bad["MUST not"] + bad["not RECOMMENDED"] = bad["MUST not"] + bad["MAY NOT"] = "The expression 'MAY NOT', while looking like RFC 2119 requirements " "text, is not defined in RFC 2119, and should not be used. Consider " "using 'MUST NOT' instead (if that is what you mean)." +} +# ---------------------------------------------------------------------- +# Pattern / actions: +# +/^This Internet-Draft(, draft-.*)? has been deleted./ { + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 +} - bad["MUST not"] = "Using lowercase 'not' together with uppercase 'MUST', "\ - "'SHALL', 'SHOULD', or 'RECOMMENDED' is not an " \ - "accepted usage according to RFC 2119. Please use uppercase 'NOT' " \ - "together with RFC 2119 keywords (if that is what you mean)." - - bad["SHALL not"] = bad["MUST not"] - bad["SHOULD not"] = bad["MUST not"] - bad["not RECOMMENDED"] = bad["MUST not"] +/^This +document has been replaced by/ { + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 +} - bad["MAY NOT"] = "The expression 'MAY NOT', while looking like RFC 2119 requirements " \ - "text, is not defined in RFC 2119, and should not be used. Consider " \ - "using 'MUST NOT' instead (if that is what you mean)." +/^This Internet-Draft(, draft-.*)? was published as/ { + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 +} +/^A new Request for Comments is now available/ { + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 } +/^RFC [0-9]+ was never issued./ { + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 +} -# ---------------------------------------------------------------------- -# usage() -# +/.*/ { + check_line() +} -function usage() { - print "" \ -"Usage: idnits [options] filename\n" \ -"\n" \ -" Options:\n" \ -" --version Print the version and exit\n" \ -" --help Print this text and exit\n" \ -" --nowarn Don't issue warnings, only ID-Checklist violations\n" \ -" --verbose Show more information about offending lines\n" \ -" --nitcount Show a count of nits\n" \ -" --debug Debug output, especially of boilerplate matching\n" \ -" --year NNNN Expect the given year in the boilerplate\n" \ -" --checklistwarn Only warn (no errors) for ID-Checklist violations\n" \ -" --nonascii Disable warnings for non-ascii characters\n" \ -" --submitcheck Only output errors and warnings related to 1id-guidelines\n" \ -" --status doctype Assume the given intended document type\n" \ -"" +# Pagecount +/-\+- Pagecount: [0-9]+ -\+-/ { + pagecount = $3 + 0 + next } +/-\+- Firstpagelength: [0-9]+ -\+-/ { + firstpagelength = $3 + 0 + next +} -# ---------------------------------------------------------------------- -# strip() -# -function strip(str) { - sub(/^[ \t\f\r]+/, "", str); - sub(/[ \t\f\r]+$/, "", str); - return str; +/-\+- Maxpagelength: [0-9]+ -\+-/ { + maxpagelength = $3 + 0 + next } -# ---------------------------------------------------------------------- -# list() -function list(str, lst) { - split(str, lst) - for (i in lst) { - lst[lst[i]] = i - delete lst[i]; - } +/-\+- Longestpage: [0-9]+ -\+-/ { + longestpage = $3 + 0 + next } -# ---------------------------------------------------------------------- -# findall() -# -function findall(str, re, array, i) { - array[0] = str - while (match(str, re) > 0) { - i += 1 - array[i] = substr(str, RSTART, RLENGTH) - str = substr(str, RSTART+RLENGTH) - } - delete array[0] +/-\+- Longpagecount: [0-9]+ -\+-/ { + longpagecount = $3 + 0 + next } -# ---------------------------------------------------------------------- -# get_para() -# -function get_para() { - para = strip($0); - while ((getline > 0) && (text = strip($0)) != "") { - check_line() - if (para ~ /-$/) { - para = para text; - } else if (para ~ /[A-Za-z0-9]\/$/ && text ~ /^[a-z0-9_-]+([)\/]|\.[a-z])/) { - para = para text; - } else if (para ~ /[A-Za-z0-9]$/ && text ~ /^\/[a-z0-9_-]+([)\/]|\.[a-z])/) { - para = para text; - } else if (para ~ /[0-9A-Fa-f]:$/ && text ~ /^[0-9A-Fa-f]+:/) { - para = para text; - } else { - para = para " " text; - } - } - return para; +/-\+- Formfeedcount: [0-9]+ -\+-/ { + formfeedcount = $3 + 0 + next } -# ---------------------------------------------------------------------- -# match_para() -# -function match_para(para, name1, name2, name3, name4) { - name[1] = name1; name[2] = name2; name[3] = name3; name[4] = name4; - for (i=1; i <= 4; i++) { - pat[i] = bp[name[i]]; - } - orig = para; - gsub(/ +/, " ", para); - pattern = ""; - for (i=1; i <= 4; i++) { - if (!pat[i]) { - almost_boilerplate[name[1]] = orig; - if (option_debug && option_pass2) { - print "** End of patterns **" - } - return 0; - } - - gsub(/. /,". ?", pat[i]); - pattern = pattern pat[i]; - - if (option_debug && option_pass2) { - print "\n----",name[i],"----" - print "line", FNR, "\n" - print "" - print "'"para"'" - print "" - print "'"pattern"'" - print "" - if (para ~ pattern) { - print "** Matches **" - } else { - print "** No Match **" - } - } - if (para ~ pattern) { - for (j=1; j<= i; j++) has[name[j]] = FNR-1; - if (option_debug && option_pass2) { - print "** Exit **" - } - return 1; - } - sub(/ *\$?$/," +", pattern); - if (para ~ pattern) { - if (option_debug && option_pass2) { - print "** Match with trailing text **" - } - for (j=1; j<= i; j++) has[name[j]] = FNR-1; - if (!pat[i+1]) { - if (option_debug && option_pass2) { - print "** Exit: end of patterns **" - } - return 1; - } - } else { - if (option_debug && option_pass2) { - print "** Exit: No prefix match **" - } - for (k=1; k < i; k++) { - pref = pat[k]; - sub(/ *\$?$/," +", pref); - sub(pref, "", orig); - } - stripped_orig = strip(orig) - if (index(substr(bp[name[i]], 1, 48), substr(stripped_orig, 1, 32))) { - almost_boilerplate[name[i]] = orig; - } - return 0; - } - } - - almost_boilerplate[name[1]] = orig; - return 0 +/-\+- Expiration: [0-9]+ -\+-/ { + has_expiration = $3 + 0 + next } -# ---------------------------------------------------------------------- -# rindex(str, find) -# -function rindex(str, find, start, pos, incr, i) { - start = 0; - pos = 0; - incr = length(find); +/-\+- NoNroffPostproc: [0-9]+ -\+-/ { + missing_nroff_postprocessing = $3 + 0 + next +} - while (1) { - i = index(str, find); - if ( i == 0 ) return pos; - pos = start + i; - str = substr(str, i+incr); - start = start+i+incr-1; - } +# If the draft begins with 'PK' it some software will think it's a zip file. Mention this. +/^PK/ && FNR == 1 { + has_pk_mark = 1 } -# ---------------------------------------------------------------------- -# fold(str) -# -# This could have been done by piping through fold, too, but we'd have -# to postprocess to add indentation anyway, and this should be a lot -# quicker for short texts. -# -function fold(str, indent, cols, width, pos, lpos, npos) { - pos = 1; - - #print "str: ", str; - #print "indent: ", indent; - #print "cols: ", cols; - - insert = "\n" indent; - width = cols; - while (pos+width-1 < length(str)) { - frag = substr(str, pos, width); - lpos = rindex(frag, " "); - npos = index(frag, "\n"); - if (npos && npos < lpos) lpos = npos; - if (!lpos) { - frag = substr(str, pos+width); - lpos = index(frag, " "); - if (lpos) lpos += width; - } - if (lpos) { - #print "** before break :", "..." substr(str, pos+lpos-9, 8) - #print "** after break :", substr(str, pos+lpos, 8) "..." - - str = substr(str, 1, pos+lpos-2) insert substr(str, pos+lpos); - pos = pos + lpos + length(insert); - } else { - return str; - } - width = cols - length(indent); - } - return str; +/^BM/ && FNR == 1 { + has_bm_mark = 1 } -# ---------------------------------------------------------------------- -# markiff(p1, p2) -# -function markdiff(p1, p2, prefixlen, para2, suffix, leading, point, temp) { - prefixlen = 0; - para2 = p2; - gsub(/\. +/, ". ", p1); - gsub(/\. +/, ". ", p2); - do { - if (substr(p1,1,1) == substr(p2,1,1)) { - p1 = substr(p1,2); - p2 = substr(p2,2); - } else { - break; - } - prefixlen++; - } while (length(p1) && length(p2)); - - prefix = substr(para2,1,prefixlen); - suffix = substr(para2,prefixlen+1); - leading = length(prefix) - rindex(prefix, "\n"); - - temp = substr(prefix, length(prefix) - leading) - spacefix = gsub(/\. +/, ". ", temp); - - point = index(suffix, "\n"); - marker = substr("........................................................................", 1, leading+spacefix) "^\n"; - return prefix substr(suffix, 1, point) marker substr(suffix, point+1) +# Check for required sections +# Nawk doesn't understand IGNORECASE = 0, so we have to explicitly convert. +# Also normalise the indentation +/\. ?\. ?\. ?\. ?\. *[0-9]+$/ { + if (! has_intro) { + has_toc = 1 + in_toc = 1 + } + next } -# ---------------------------------------------------------------------- -# expandname(name) -# -function expandname(name) { - sub(/_u/, ", updated by RFC " , name); - sub(/_p/, ", paragraph " , name); - sub(/_e/, " embedded", name); - if (name ~ /^rfc/ || name ~ /^trust-/) { - sub("_", ", Section ", name); - split("x ix viii vii vi v iv iii ii i", roman) - for (i in roman) { - r = roman[i]; - sub("_" r, "(" r ")", name); - } - gsub("_", ".", name); - sub("rfc", "RFC ", name) - sub("trust-", "IETF Trust Legal Provisions of ", name) - } - return name +{ + normalized = tolower($0) + if (indentation) { + normalized = substr(normalized, indentation) + #if (option_verbose > 2 && option_pass1) printf " normalized: '%s'\n", normalized; + } } -# ---------------------------------------------------------------------- -# showalmost(name) -# -function showalmost(name, orig) { - p2 = almost_boilerplate[name]; - p2 = fold(p2, " ", bpcols); - p2 = sprintf (" %s\n\n", p2) - if (orig) p2 = markdiff(orig, p2); - printf(p2) +/::= +BEGIN *$/ { + in_mib = 1 } -# ---------------------------------------------------------------------- -# showsection(name) -# -function showsection(name, suppress, initial, final) { - p = bp[name]; - "date +'%Y'" | getline year - # Get rid of regexp stuff in the boilerplate text we show the user: - # - mark metacharacters with mark character "!" - gsub(/[()|?+*^$]/, "!&", p); - # - get rid of mark preceeded by escape char... - gsub(/\\!/, "", p); - # - get rid of alternates, keeping the first only - gsub(/!\|[^)]*!\)/, "", p); - # - and we can get rid of metacharacters not preceeded by escape char - gsub(/![\(\)?+*^$]/, "", p); - # and also of escape chars themselves - gsub(/\\/, "", p); - # - also say "year" instead of "[0-9]" - ##gsub(/\[0-9\]/, "", p); - gsub(/\[0-9\]\[0-9\]\[0-9\]\[0-9\]/, year, p); - if (suppress < 2) note( initial expandname(name) final ":"); - p1 = fold(p, " ", bpcols); - p1 = sprintf(" %s", p1); - printf(p1) +/^ +END *$/ { + in_mib = 0 +} - if (name in almost_boilerplate && suppress == 0) { - note( "\n\n ... text found in draft:"); - showalmost(name, p1) - print "" +normalized ~ /^internet[ -]draft/ { + if (FNR < 15) { + has_id_indication = 1 } else { - print "\n"; + has_late_id_indication = 1 } } -# ---------------------------------------------------------------------- -# checkmultibp(name) -# -function checkmultibp(name) { - if ( has[name] && almost_boilerplate[name]) { - warn(sprintf("In addition to %s boilerplate, a section with a similar start was also found:\n", expandname(name))) - showalmost(name) - } +normalized ~ /^expires:?.*20[0-9][0-9]/ { + has_expiration = FNR } -# ---------------------------------------------------------------------- -# sectionerr(name, str) -# -function sectionerr(name, str, wflag) { - if (! name in has) { - print "?? internal error, expected a table match on %s", name; - exit; - } - if (str ~ /^the /) { - str = "The document seems to lack " str; - } else if (str ~ /^[aeiouyAEIOUYRH]/) { - str = "The document seems to lack an " str; - } else { - str = "The document seems to lack a " str; - } - if (name in almost_boilerplate) { - str = str " -- however, there\047s a paragraph with a matching beginning. Boilerplate error?"; - } else { - if ( str !~ /(\.|\.\))$/ ) str = str ". "; - } - if (wflag == 3) { - comment(str); - } else if (wflag == 2) { - warn(str); - } else if (wflag == 1) { - flaw(str); - } else { - err(str); - } - if ((option_verbose || option_submitcheck) && option_pass2) { - showsection(name) - } -} - -function sectioncomment(name, str) { - sectionerr(name, str, 3); -} -function sectionwarn(name, str) { - sectionerr(name, str, 2); -} -function sectionflaw(name, str) { - sectionerr(name, str, 1); +normalized ~ /[12][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/ { + match($0, /[12][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/) + datestr = substr($0, RSTART, RLENGTH) + if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { + split(datestr, part, /-/) + m = part[2] + d = part[3] + y = part[1] + isodate = sprintf("%s-%s-%s", y, m, d) + new_date = jdn(isodate) + if (new_date > doc_date) { + doc_date = new_date + date_lit = datestr + iso_date = isodate + date_skew = 3 + } + } } -# ---------------------------------------------------------------------- -# oldandnewerr(old, new) -# -function oldandnewerr(old, new) { - if (! new in has) { - print "?? internal error, expected a table match on %s", new; - exit; - } - newname = expandname(new) - oldname = expandname(old) - str = sprintf("Found boilerplate matching %s (on line %s), which is fine, but *also* found old %s text on line %s.", newname, has[new], oldname, has[old]); - err(str); - if (option_verbose && option_pass2) { - showsection(old, 1) - showsection(new, 1) - } +normalized ~ /[adfjmnos][a-z]+ [0-9]+, [12][0-9][0-9][0-9]$/ { + match($0, /[ADFJMNOS][a-z]+ [0-9]+, [12][0-9][0-9][0-9]$/) + datestr = substr($0, RSTART, RLENGTH) + if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { + split(datestr, part, /[ ,]+/) + m = month[part[1]] + d = part[2] + y = part[3] + isodate = sprintf("%s-%s-%s", y, m, d) + new_date = jdn(isodate) + if (new_date > doc_date) { + doc_date = new_date + date_lit = datestr + iso_date = isodate + date_skew = 3 + } + } } +normalized ~ /([0-9]+ )?[adfjmnos][a-z]+ [12][0-9][0-9][0-9]$/ { + is_docdate = 0 + if (match($0, /[0-9]+ [ADFJMNOS][a-z]+ [12][0-9][0-9][0-9]$/)) { + datestr = substr($0, RSTART, RLENGTH) + if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { + is_docdate = 1 + split(datestr, part, /[ ,]+/) + m = month[part[2]] + d = part[1] + y = part[3] + date_skew = 3 + } + } else { + match($0, /[ADFJMNOS][a-z]+ [12][0-9][0-9][0-9]$/) + datestr = substr($0, RSTART, RLENGTH) + if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { + is_docdate = 1 + split(datestr, part, /[ ,]+/) + m = month[part[1]] + d = 15 + y = part[2] + date_skew = 16 + } + } + if (is_docdate) { + isodate = sprintf("%s-%s-%s", y, m, d) + new_date = jdn(isodate) + if (new_date > doc_date) { + doc_date = new_date + date_lit = datestr + iso_date = isodate + } + } +} -# ---------------------------------------------------------------------- -# newandolderr(old, new) -# -function newandolderr(old, new) { - newname = expandname(new) - oldname = expandname(old) - str = sprintf("Found new %s boilerplate, which is fine, but *also* found old boilerplate from %s on line %s.", newname, oldname, has[old]); - err(str); - if (option_verbose && option_pass2) { - showsection(old, 1) - } +normalized ~ /^([0123.]+ +)?table of contents:?( *\(.+\))?$/ { + has_toc = 1 + in_toc = 1 } +normalized ~ /^[ \t]*contents$/ { + if (! has_intro) { + has_toc = 1 + in_toc = 1 + } +} -# ---------------------------------------------------------------------- -# olderr(old, new) -# -function olderr(old) { - oldname = expandname(old) - str = sprintf("Found old boilerplate from %s on line %s.", oldname, has[old]); - comment(str); - if (option_verbose && option_pass2) { - showsection(old, 1, "The obsolete ", " text") - } +normalized ~ /^([0123.]+ )? ? ? ? ? ?introduction[ \t]*.*/ { + has_intro = 1 } +normalized ~ /^ +([0123.]+ )? ? ? ? ? ?introduction[ \t]*.*/ { + indented_intro = $0 +} -# ---------------------------------------------------------------------- -# update_references(line, pos) -# +normalized ~ /^([0123.]+ )? ? ? ? ? ?overview[ \t]*.*/ { + has_intro = 1 +} -function update_references(this, pos) { - if (!match(this, /\[Page/)) { - nnnote( sprintf("update_references( %s)\n", this)) - if ( match(this, "(^|[\\]A-Za-z0-9 \t.()])" reference_format "\\)?([) \t,;:.?[]|$)") ) { - - line[pos] = this - if (in_refs && this ~ "^ *([0-9.]+ *)?" reference_format) { - # Reference definitions - match(this, reference_format) - reftag = substr(this, RSTART+1, RLENGTH-2) - numrefs = split(reftag, reftags, /, +/) - for (i=1; i<= numrefs; i++) { - reftag = reftags[i] - ref_def[reftag] = pos - if ( ! (reftag in ref_def_seen) ) { - ref_def_seen[reftag]; ref_def_list[++ref_def_count] = reftag - } - - if ( reftag ~ /^[0-9]+$/ ) { - has_numeric_refs = 1 - } else { - has_symbolic_refs = 1 - } - - if (option_pass2) nnnote(sprintf(" ref_def[%s] at %s: %s\n", reftag, pos, this)); - ref_text[reftag] = this; - if (in_normref) { - ref_norm[reftag]; - } - } - } else { - # Reference usage - while ( match(this, reference_format )) { - reftag = substr(this, RSTART+1, RLENGTH-2) - numrefs = split(reftag, reftags, /, +/) - for (i=1; i<= numrefs; i++) { - tags = substr(this, RSTART+1, RLENGTH-2) - split(tags, reftags, /(,|, )/) - for (i in reftags) { - reftag = reftags[i] - ref_use[reftag] = pos - if ( ! (reftag in ref_use_seen) ) { - ref_use_seen[reftag]; ref_use_list[++ref_use_count] = reftag; - } - if (option_verbose > 2 && option_pass2) printf " ref_use[%s] = %s\n", reftag, pos - } - this = substr(this, RSTART+RLENGTH) - } - } - } - } else if (option_verbose && option_pass1) { - match(this, /\[[0-9A-Z-]+\]/) - printf("%s(%d): Unexpected reference format: '...%s...'\n", FILENAME, pos, substr(this,RSTART-5, RLENGTH+10)); - if (option_verbose > 1) { - printf(" --> %s\n", this); - printf(" %*s\n", RSTART, "^"); - } - } - } +normalized ~ /^ +([0123.]+ )? ? ? ? ? ?overview[ \t]*.*/ { + indented_intro = $0 } -# ---------------------------------------------------------------------- -# announce() -# +normalized ~ /^([0123.]+ )? ? ? ? ? ?rationale[ \t]*.*/ { + has_intro = 1 +} -function announce(str) { -### print "" - print "" - print fold(" " str, " ", columns); - print " " substr("----------------------------------------------------------------------------", 1, columns-2); - print "" +normalized ~ /^ +([0123.]+ )? ? ? ? ? ?rationale[ \t]*.*/ { + indented_intro = $0 } +normalized ~ /^([0123.]+ )? ? ? ? ? ?scope[ \t]*.*/ { + has_intro = 1 +} -# ---------------------------------------------------------------------- -# note() -# +normalized ~ /^ +([0123.]+ )? ? ? ? ? ?scope[ \t]*.*/ { + indented_intro = $0 +} -function note(str) { - if (option_pass1) { - printf("%s(%d): %s.\n", FILENAME, FNR, str); - } else { - print fold(" " notemark " " str, " ", columns); - } +normalized ~ /^([0123.]+ )? ? ? ? ? ?(historical )?background[ \t]*.*/ { + has_intro = 1 } -function nnote(str) { - if (option_verbose) { - if (option_pass1) { - printf("%s(%d): %s.\n", FILENAME, FNR, str); - } - } +normalized ~ /^ +([0123.]+ )? ? ? ? ? ?(historical )?background[ \t]*.*/ { + indented_intro = $0 } -function nnnote(str) { - if (option_verbose >= 2) { - if (option_pass1) { - printf("%s(%d): %s.\n", FILENAME, FNR, str); - } else { - print fold(" " notemark " " str, " ", columns); - } - } +normalized ~ /^([0-9.]+ )? ? ? ? ? ?security considerations?[ \t]*.*/ { + has_security = 1 } -# ---------------------------------------------------------------------- -# comment() -# +normalized ~ /^ +([0-9.]+ )? ? ? ? ? ?security considerations?[ \t]*.*/ { + indented_security = $0 +} -function comment(str, indented) { - if (option_warn) { - print fold(" " infomark " " str, " ", columns); - if (indented) { - print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns); - print fold(" '" indented "' )", " ", columns); - } - print ""; - comments++; - } +normalized ~ /^([0-9.]+ )? ? ? ? ? ?security$/ { + has_security = 1 } +normalized ~ /^ +([0-9.]+ )? ? ? ? ? ?security$/ { + indented_security = $0 +} -# ---------------------------------------------------------------------- -# warn() -# +normalized ~ /^(appendix )?([0-9a-z.]+ )? ? ? ? ? ?iana considerations?[ \t]*.*/ { + has_iana = 1 +} -function warn(str, indented) { - if (option_warn) { - print fold(" " warnmark " " str, " ", columns); - if (indented) { - print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns); - print fold(" '" indented "' )", " ", columns); - } - print ""; - warnings++; - } +normalized ~ /^ +([0-9a-z.]+ )? ? ? ? ? ?iana considerations?[ \t]*.*/ { + indented_iana = $0 } +# New section. If we were in a reference section, we've now left it. +normalized ~ /^[0-9.]+ +/ { + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 + sections[$1] = substr($0, length($1)) +} -# ---------------------------------------------------------------------- -# flaw() -# +normalized ~ /^status of (this )?memo/ { + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 +} -function flaw(str, indented) { - print fold(" " flawmark " " str, " ", columns); - print ""; - flaws++; +normalized ~ /^conventions used / { + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 } +normalized ~ /^requirements language/ { + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 +} -# ---------------------------------------------------------------------- -# err() -# +normalized ~ /^table of contents/ { + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 +} -function err(str, indented) { - print fold(" " errmark " " str, " ", columns); - if (indented) { - print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns); - print fold(" '" indented "' )", " ", columns); - } - print ""; - errors++; +normalized ~ /^([0123.]+ )? *abstract$/ { + has_abstract = 1 + in_abstract = 1 } +normalized ~ /^ +([0123.]+ )? *abstract$/ { + indented_abstract = $0 + in_abstract = 1 +} -# ---------------------------------------------------------------------- -# errc() -# -# Errors which are IESG checklist errors, but not submission errors +normalized ~ /^appendix/ { + if (has_refs) { + has_appendix = 1 + } + in_refs = 0 + nnnote("Appendix start: " $0) +} -function errc(str, indented) { - if (!option_submitcheck) { - if (option_checklistwarn) { - warn(str, indented); - } else { - err(str, indented); +normalized ~ /^ +appendix/ { + if (has_refs) { + indented_appendix = $0 } - } } +normalized ~ /(^| )abnf([ .]|$)/ { + abnf_mentioned = 1 +} -# ---------------------------------------------------------------------- -# errw() -# -# Errors which are only warnings in submission mode +normalized ~ abnf_rule_format { + in_abnf++ +} +$0 ~ imap_rule_format { + in_imap++ +} -function errw(str, indented) { - if (option_submitcheck) { - warn(str, indented); - } else { - err(str, indented); - } +# The imap rule format has some parts specifically in uppercase -- can't use 'normalized' +normalized ~ /^ *$/ { + in_abnf = 0 + in_imap = 0 } +$0 ~ code_start_format { + in_code = 1 + nnote("Code start at " FNR ": " $0) +} -# ---------------------------------------------------------------------- -# warnc() -# -# Warnings which are IESG checlist warnings, but not submission warnings +$0 ~ code_end_format { + in_code = 0 + nnote("Code end at " FNR ": " $0) +} -function warnc(str, indented) { - if (!option_submitcheck) { - warn(str, indented); - } +$0 ~ inline_code_format { + if (! in_code) { + code_comment_found = 1 + nnote("Possible code comment in line: " $0) + } } +normalized ~ /^([0-9]+[.]?0? )? ? ? ? ? ?references$/ { + if (has_intro || has_security || has_iana) { + has_refs = 1 + in_refs = 1 + in_normref = 1 + } +} -# ---------------------------------------------------------------------- -# errg() -# +normalized ~ /^ +([0-9]+[.]?0? )? ? ? ? ? ?references$/ { + if (has_intro || has_security || has_iana) { + indented_refs = $0 + } +} -function errg(str, indented) { - if (option_guidelinewarn) { - warn(str, indented); - } else { - err(str, indented); - } +normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?normative references?$/ { + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + has_refs = 1 + in_refs = 1 + in_normref = 1 + } } +normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informative references?$/ { + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + has_refs = 1 + in_refs = 1 + in_normref = 0 + } +} -# ---------------------------------------------------------------------- -# get_state(draft) -# +normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informational references?$/ { + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + has_refs = 1 + in_refs = 1 + in_normref = 0 + } +} -function get_state(draft, state, quiet, count) { - for (key in state) delete state[key]; - statefile = statusdir "/" draft ".state" -## Not sure that this fallback handling is necessary. Keeping it commented out for now. -# if ( ( getline < statefile ) < 0 ) { -# close(statefile) -# note("... Trying to download missing state file for " draft " ...") -# command = "idnits --download '" draft " state' http://tools.ietf.org/draft/" draft "/state " statusdir "/" draft ".state 'Doc-tag: " draft "'" -# while ( (command | getline) > 0) print $0; -# } - while ( getline < statefile > 0 ) { - if ($1 ~ /^Doc-/) { - count++; - key = substr($1, 5, length($1)-5); - $1 = ""; - value = strip($0) - sub(/;[^;]*$/, "", value) - state[key] = value - } - } - close(statefile) - datefile = statefile ".date" - if ( getline < datefile > 0 && $0 ) { - state["downloaded"] = $0 - } else { - state["downloaded"] = "unsuccessful" - } - if (!count && !quiet) comment("No information found for " draft " - is the name correct?"); - return count +normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?non-normative references?$/ { + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + has_refs = 1 + in_refs = 1 + in_normref = 0 + } } +normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?references[^a-z]+normative\)?$/ { + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + in_refs = 1 + in_normref = 1 + } +} -# ---------------------------------------------------------------------- -# check_downref(tag) -# +normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?references[^a-z]+informative\)?$/ { + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + in_refs = 1 + in_normref = 0 + } +} -function referr(msg, num, tag, comment, info, numstr) { - numstr = sprintf("%d", num); - if (numstr in obsoleted) { - info = obsoleted[numstr]; - gsub(" ", ", RFC ", info); - info = " (Obsoleted by " substr(info, 3) ")"; - } - - if (tag ~ numstr) { - errc(sprintf("%s: RFC %4d%s%s", msg, num, info, comment)); - } else { - errc(sprintf("%s: RFC %4d (ref. '%s')%s%s", msg, num, tag, info, comment)); - } -} - -function refcomment(msg, num, tag, info, numstr) { - numstr = sprintf("%d", num); - if (numstr in obsoleted) { - info = obsoleted[numstr]; - gsub(" ", ", RFC ", info); - info = " (Obsoleted by " substr(info, 3) ")"; - } - - if (tag ~ numstr) { - comment(sprintf("%s: RFC %4d%s", msg, num, info)); - } else { - comment(sprintf("%s: RFC %4d (ref. '%s')%s", msg, num, tag, info)); - } -} - -function get_rfcnum(ref, num) { - for (;;) { - if (match(ref, /(RFC|rfc)[0-9][0-9]+/)){ - num = substr(ref, RSTART+3, RLENGTH-3) + 0; - } else if (match(ref, /(RFC|rfc)[ -][0-9][0-9]+/)) { - num = substr(ref, RSTART+4, RLENGTH-4) + 0; - } else if (match(ref, /(Request [Ff]or Comments) [0-9][0-9]+/)) { - num = substr(ref, RSTART+21, RLENGTH-21) + 0; - } else if (match(ref, /(Request [Ff]or Comments)( \([^\)]*\))? [0-9][0-9]+/)) { - num = substr(ref, RSTART+RLENGTH-4, 4) + 0; - } else { - if (! num) note( "Unexpected reference format, failed extracting the RFC number: " ref ) - break; - } - if (RSTART+RLENGTH <= 1) break - ref = substr(ref, RSTART+RLENGTH) - } - return num -} - -function get_draftname(ref, draftname) { -# print "** ref:", ref - if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9][^a-zA-Z0-9_-]/)) { - draftname = substr(ref, RSTART, RLENGTH-4); - } else if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9]$/)) { - draftname = substr(ref, RSTART, RLENGTH-3); - } else if (match(ref, /draft-[a-zA-Z0-9_-]+/)) { - draftname = substr(ref, RSTART, RLENGTH); - } else if (match(ref, /I-D\.[a-zA-Z0-9_-]+/)) { - draftname = "draft-" substr(ref, RSTART+4, RLENGTH-4); - } -# print "** doc:", draftname - return draftname; -} - -function get_draftrev(ref, draftrev) { - if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9]$/)) { - draftrev = substr(ref, RSTART+RLENGTH-2, 2); - } else if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9][^a-zA-Z0-9_-]/)) { - draftrev = substr(ref, RSTART+RLENGTH-3, 2); - } - return draftrev; -} - -function get_draftcode(draftname, state, code) { - if (draftname) { - if ("deststatus" in state) { - status = tolower(state["deststatus"]); - if (status != "none") { - code = status2code[status]; - } - } - } - return code; -} - -function check_downref(tag, warnlist, rfcnum, draftname, code, status, doc) { - - if (tag in ref_text) ref = ref_text[tag]; else ref = tag; - gsub(/ +/, " ", ref); - - if (option_verbose > 2) { - note("Reference text: " ref) - } - - if (ref ~ /[, ([](draft-|I-D\.)/) { - draftname = get_draftname(ref); - draftrev = get_draftrev(ref); - doc = draftname; - get_state(draftname, state); - if (state["downloaded"] != today) { - download_state = " (However, the state information for " draftname " is not up-to-date. The last update was " state["downloaded"] ")" - } - - ## Refactoring needed. We probably need a check_reference() rather than check_downref(), - ## with the published and current-version checks below being done as part of the general - ## reference checking, rather than inside the downref check. - if ("rfcnum" in state) { - warnc(sprintf("Outdated reference: %s has been published as RFC %s", draftname, state["rfcnum"])); - } else if (draftrev && ("rev" in state) && (draftrev != state["rev"])) { - if (draftrev+0 < state["rev"]+0) { - warnc(sprintf("Outdated reference: A later version (-%s) exists of %s-%s", state["rev"], draftname, draftrev)) - } else { - comment(sprintf("Unexpected draft version: The latest known version of %s is -%s, but you're referring to -%s.%s", draftname, state["rev"], draftrev, download_state)) - } - } - } else if (ref ~ /(RFC|rfc|Request [Ff]or Comments)( \([^\)]*\)|-)? ?[0-9][0-9]+/) { - rfcnum = get_rfcnum(ref); - doc = "RFC" rfcnum; - } - if (doc && doc in seen_ref && !(seen_ref[doc] in miss_ref) ) { - comment(sprintf("Duplicate reference: %s, mentioned in '%s', was also mentioned in '%s'.", doc, tag, seen_ref[doc])); - } - seen_ref[doc] = tag; - - if (rfcnum) code = substr(rfcstatus, rfcnum, 1); - if (draftname) code = get_draftcode(draftname, state); - if (rfcnum && code == "O") { - if (tag in ref_norm) { - referr("Obsolete normative reference", rfcnum, tag); - } else if (!(tag in ref_def)) { - referr("Obsolete undefined reference", rfcnum, tag); - } else { - refcomment("Obsolete informational reference (is this intentional?)", rfcnum, tag); - } - } else { - if (tag in ref_norm) { - if (rfcnum) { - if (code in warnlist) { - if ( rfcnum in exception ) { - referr(sprintf("Downref: Normative reference to an %s RFC", code2status[code]), rfcnum, tag, \ - "\n(Excemption has been granted for downref to this document in the past, see https://trac.tools.ietf.org/group/iesg/trac/wiki/DownrefRegistry)"); - } else { - referr(sprintf("Downref: Normative reference to an %s RFC", code2status[code]), rfcnum, tag); - } - } - } else if ("U" in warnlist) { - if (ref ~ /[, ([](draft-|I-D\.)/) { - if (code) { - if (code in warnlist) { - errc(sprintf("Downref: Normative reference to an %s draft: %s (ref. '%s')", code2status[code], draftname, tag)); - } - } else { - if (state["deststatus"] == "None") { - statmsg = " (No intended status found in state file of " draftname ")"; - } else { - statmsg = ""; - } - comment(sprintf("Possible downref: Normative reference to a draft: ref. '%s' %s", tag, statmsg)); - } - } else { - comment(sprintf("Possible downref: Non-RFC (?) normative reference: ref. '%s'", tag)); - } - } - } else if (!(tag in ref_def)) { - # Comment out this -- the warning for a missing reference is enough for a first pass. -# if (rfcnum) { -# if (code in warnlist) { -# refcomment(sprintf("Possible downref: Undefined reference to an %s RFC", code2status[code]), rfcnum, tag); -# } -# } else if ("U" in warnlist) { -# if (ref ~ /[, ([](draft-|I-D\.)/) { -# if (code) { -# if (code in warnlist) { -# warnc(sprintf("Possible downref: Undefined reference to an %s draft: %s (ref. '%s')", code2status[code], draftname, tag)); -# } -# } else { -# warnc(sprintf("Possible downref: Undefined reference to a draft: ref. '%s'", tag)); -# if (state["deststatus"] == "None") { -# note("(No intended status found in state file of " draftname ")"); -# } -# } -# } else { -# comment(sprintf("Possible downref: Undefined Non-RFC (?) reference : ref. '%s'", tag)); -# } -# } - } - } +normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?normative$/ { + if (has_refs) { + has_splitrefs = 1 + in_refs = 1 + in_normref = 1 + } } -# ---------------------------------------------------------------------- -function jdn(date , part, year, month, day, a, y, m, d) { - split(date, part, "-") - year = part[1] - month = part[2]; sub(/^0/, "", month) - day = part[3]; sub(/^0/, "", day) +normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informative$/ { + if (has_refs) { + has_splitrefs = 1 + in_refs = 1 + in_normref = 0 + } +} - a = int((14-month)/12) - y = year + 4800 - a - m = month + 12*a - 3 +normalized ~ /^[0-9a-z.]* *((author|editor)(\047s|s\047) +(and +)?)+address(es)?/ { + has_addr = 1 +} - d = day + int((153*m+2)/5) +365*y + int(y/4) - int(y/100) + int(y/400) - 32045 - return d +normalized ~ /^[0-9a-z.]* *author information$/ { + has_addr = 1 } -# ---------------------------------------------------------------------- -function get_creation_date(doc, state, created, i) { - get_state(doc, state); - split("creationdate created submitted", keys); - for (i in keys) { - key = keys[i] - if (key in state) { - created = state[key]; - if (created == "None") created = ""; - break; - } - } - return created; +normalized ~ /^[0-9a-z.]* *(author|editor)(\047s|s\047) contact information$/ { + has_addr = 1 } -# ---------------------------------------------------------------------- -# report() -# -function report(filename) { - if (skip_file) return; - if (option_pass1) return; - if (option_status) { - if ( ! (tolower(option_status) in status2code) ) { - note(sprintf("Unexpected value in --status switch ('%s'), ignoring it. (Use one of 'informational', 'experimental', 'bcp', 'ps', 'ds', 'standard'.)", option_status)); - } else { - intended_status = tolower(option_status); - } - } +normalized ~ /^[0-9A-Z.]* *contact information$/ { + has_addr = 1 +} - if (got_input) { - is_rfc = (filename ~ /[Rr][Ff][Cc][0-9]+\.txt$/); +normalized ~ /^[0-9A-Z.]* *(author|editor)s?:?$/ { + has_addr = 1 +} - draftname = full_docname - sub(/\.[a-z]+$/, "", draftname) - sub(/-[0-9][0-9]$/, "", draftname) - get_state(draftname, state, quiet=1) - destcode = get_draftcode(draftname, state) +# RFC 3978 / 2026 compliance +/^[ \t0-9.]*This document may only be posted in an Internet-Draft.$/ { + has["rfc3978_5_3"] = FNR +} - if (option_submitcheck) { - printf("\n Showing Errors (" errmark "), Flaws (" flawmark "), Warnings (" warnmark "), and Comments (" infomark ").\n") - print(" Errors MUST be fixed before draft submission. Flaws SHOULD be fixed before draft submission."); - } - - announce("Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info):") - errcount = errors; flawcount = flaws; warncount = warnings; commentcount = comments; - - # 12 Sep 2009 values below are valid during the post-28-dec-2009 transition - if (has["trust-28-dec-2009_6_a"] || - has["trust-12-sep-2009_6_a"] || - has["trust-28-dec-2009_6_b_i_p2"] || - has["trust-28-dec-2009_6_b_i_p3"] || - has["trust-28-dec-2009_6_b_ii_p3"] || - has["trust-12-sep-2009_6_b_p3"]) { - - # We have some text from the current Trust Provisions boilerplate. Check that we don't have older - # boilerplate, too. - for ( bpname in bp ) { - if ( bpname ~ /^rfc2026/ || - bpname ~ /^rfc3667/ || - bpname ~ /^rfc3978/ || - bpname ~ /^rfc3979/ ) { - if ( has[bpname] && !(bpname ~ "_now")) newandolderr(bpname, "IETF Trust Provisions of 12 Sep 2009") - } - } - - if ( !is_rfc ) { - if ( ! (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"]) ) sectionerr("trust-28-dec-2009_6_a", - "Notice of Compliance with BCP 78 and BCP 79 according to " \ - "IETF Trust Provisions of 28 Dec 2009, Section 6.a " \ - "or Provisions of 12 Sep 2009, Section 6.a"); - } - if ( ! has["trust-28-dec-2009_6_b_i_p2"] ) sectionerr("trust-28-dec-2009_6_b_i_p2", - "IETF Trust Provisions of 28 Dec 2009, Section 6.b Copyright Notice"); - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes ) { - if ( ! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-12-sep-2009_6_b_p3"]) ) { - sectionerr("trust-28-dec-2009_6_b_i_p3", - "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.i or Provisions of 12 Sep 2009 Section 6.b"); - if ( has["trust-28-dec-2009_6_b_ii_p3"] ) comment("It seems you're using the 'non-IETF stream' Licence Notice instead"); - } - } else if (full_docname ~ /^draft-(iab|irtf|rfced|rfc-editor)-/ ) { - if ( ! (has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"]) ) { - sectionerr("trust-28-dec-2009_6_b_ii_p3", - "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b"); - if ( has["trust-28-dec-2009_6_b_i_p3"] ) comment("It seems you're using the 'IETF stream' Licence Notice instead"); - } - } else { - if ( ! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"]) ) { - sectionerr("trust-28-dec-2009_6_b_ii_p3", - "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b"); - } - } - # The following is just an informational note because we've emitted an error earlier: - if (has["trust-12-feb-2009_6_b_p3"]) note("(You're using the IETF Trust Provisions' Section 6.b License Notice from " \ - "12 Feb 2009 rather than one of the newer Notices. " \ - "See https://trustee.ietf.org/license-info/.)\n"); - if (has["trust-12-sep-2009_6_b_p3"]) err("You're using the IETF Trust Provisions' Section 6.b License Notice from " \ - "12 Sep 2009 rather than the newer Notice from 28 Dec 2009. " \ - "(See https://trustee.ietf.org/license-info/)"); - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes ) { - if ( has["trust-28-dec-2009_6_c_i"]) - { warn("The document has an IETF Trust Provisions of 28 Dec 2009, Section 6.c(i) Publication Limitation clause."); } - if ( has["trust-28-dec-2009_6_c_ii"]) - { err("The document has an IETF Trust Provisions, 28 Dec 2009, Section 6.c(ii) Publication Limitation clause."); } - } else { - if ( has["trust-28-dec-2009_6_c_i"]) - { comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(i) Publication Limitation clause."); } - if ( has["trust-28-dec-2009_6_c_ii"]) - { comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(ii) Publication " \ - "Limitation clause. If this document is intended for submission to the IESG for " \ - "publication, this constitutes an error."); } - } - } else if ( (has["rfc3667_5_1"] || - has["rfc3978_5_1_a"] || - has["rfc3978_5_1"] || - has["rfc3978_5_2b"] || - has["rfc3978_5_3"] || - has["rfc3978_5_5"] || - has["rfc3978_5_5_u4748"] || - has["rfc3979_5_p1"] || - has["rfc3979_5_p2"] || - has["rfc3979_5_p3"] ) ) { - - err("It looks like you\047re using RFC 3978 boilerplate. You should update this to the " \ - "boilerplate described in the IETF Trust License Policy document (see " \ - "https://trustee.ietf.org/license-info), which is required now.") - { - if (has["rfc3667_5_1"]) olderr("rfc3667_5_1"); - if (has["rfc3978_5_1_a"]) olderr("rfc3978_5_1_a"); - if (has["rfc3978_5_1"]) olderr("rfc3978_5_1"); - if (has["rfc3978_5_2b"]) olderr("rfc3978_5_2b"); - if (has["rfc3978_5_3"]) olderr("rfc3978_5_3"); - if (has["rfc3978_5_5"]) olderr("rfc3978_5_5"); - if (has["rfc3978_5_5_u4748"]) olderr("rfc3978_5_5_u4748"); - if (has["rfc3979_5_p1"]) olderr("rfc3979_5_p1"); - if (has["rfc3979_5_p2"]) olderr("rfc3979_5_p2"); - if (has["rfc3979_5_p3"]) olderr("rfc3979_5_p3"); - } - # Ok, so we have some 3978/3979 boilerplate - make sure we don't *also* have some - # lingering old boilerplate... - { - if ( has["rfc3978_5_1"] ) if ( has["rfc3667_5_1"] ) oldandnewerr("rfc3667_5_1", "rfc3978_5_1"); - - if ( has["rfc3978_5_4_p1"] ) if ( has["rfc2026_10_4C_p1"] ) oldandnewerr("rfc2026_10_4C_p1", "rfc3978_5_4_p1"); - if ( has["rfc3978_5_4_p1_u4748"] ) if ( has["rfc2026_10_4C_p1"] ) oldandnewerr("rfc2026_10_4C_p1", "rfc3978_5_4_p1_u4748"); - if ( has["rfc3978_5_4_p1_u4748"] ) if ( has["rfc3978_5_4_p1"] ) oldandnewerr("rfc3978_5_4_p1", "rfc3978_5_4_p1_u4748"); - if ( has["rfc3978_5_4_p1_u4748_e"] ) if ( has["rfc3978_5_4_p1"] ) oldandnewerr("rfc3978_5_4_p1", "rfc3978_5_4_p1_u4748_e"); - if ( has["rfc3978_5_4_p1_u4748"] ) if ( has["rfc3978_5_4_p1_e"] ) oldandnewerr("rfc3978_5_4_p1_e", "rfc3978_5_4_p1_u4748"); - - if ( has["rfc3978_5_5"] ) if ( has["rfc2026_10_4C_p4"] ) oldandnewerr("rfc2026_10_4C_p4", "rfc3978_5_5"); - if ( has["rfc3978_5_5_u4748"] ) if ( has["rfc2026_10_4C_p4"] ) oldandnewerr("rfc2026_10_4C_p4", "rfc3978_5_5_u4748"); - if ( has["rfc3978_5_5_u4748"] ) if ( has["rfc3978_5_5"] ) oldandnewerr("rfc3978_5_5", "rfc3978_5_5_u4748"); - - if ( has["rfc3979_5_p1"] ) if ( has["rfc2026_10_4A"] ) oldandnewerr("rfc2026_10_4A", "rfc3979_5_p1"); - if ( has["rfc3979_5_p3"] ) if ( has["rfc2026_10_4B"] ) oldandnewerr("rfc2026_10_4B", "rfc3979_5_p3"); - } - - if ( has["rfc2026_lax_claim"] || - has["rfc2026b_lax_claim"] ) - { - err("The document claims conformance with section 10 of RFC 2026, but uses " \ - "some RFC 3978/3979 boilerplate. As RFC 3978/3979 replaces section 10 of " \ - "RFC 2026, you should not claim conformance with it if you have changed " \ - "to using RFC 3978/3979 boilerplate."); - } +{ + gsub(/ +/, " ", normalized) +} - if (!(has["rfc3978_5_1"]) && !is_rfc ) - { - sectionerr("rfc3978_5_1", "RFC 3978 Section 5.1 IPR Disclosure Acknowledgement"); - } - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes ) { - if ( has["rfc3978_5_2b"] ) { err("The document has an RFC 3978 Section 5.2(b) Derivative Works Limitation clause."); } - if ( has["rfc3978_5_3"]) { err("The document has an RFC 3978 Section 5.3 Publication Limitation clause."); } - } else { - - if ( has["rfc3978_5_2b"] ) { comment("The document has an RFC 3978 Section 5.2(b) Derivative Works Limitation clause. " \ - "If this document is intended for submission to the IESG for publication, this " \ - "constitutes an error."); } - if ( has["rfc3978_5_3"]) { comment("The document has an RFC 3978 Section 5.3 Publication Limitation clause. " \ - "If this document is intended for submission to the IESG for publication, this " \ - "constitutes an error."); } - } - if (! has["rfc3978_5_4_p1_u4748"]) { - if (has["rfc3978_5_4_p1"]) { - err("This document has an original RFC 3978 Section 5.4 Copyright Line, " \ - "instead of the newer IETF Trust Copyright according " \ - "to RFC 4748."); - } else { - sectionerr("rfc3978_5_4_p1_u4748", "RFC 3978 Section 5.4 (updated by RFC 4748) Copyright Line"); - } - } - if (! has["rfc3978_5_4_p2"]) { - sectionerr("rfc3978_5_4_p2", "RFC 3978 Section 5.4 Reference to BCP 78"); - } - if (! has["rfc3978_5_5_u4748"]) { - if (has["rfc3978_5_5"]) { - err("This document has an original RFC 3978 Section 5.5 Disclaimer, " \ - "instead of the newer disclaimer which includes the IETF Trust according " \ - "to RFC 4748."); - } else { - sectionerr("rfc3978_5_5_u4748", "RFC 3978 Section 5.5 (updated by RFC 4748) Disclaimer"); - } - } - if (! has["rfc3979_5_p1"]) { - sectionerr("rfc3979_5_p1", "RFC 3979 Section 5, para. 1 IPR Disclosure Acknowledgement"); - if (has["rfc2026_10_4A"]) { - note("( - It does however have an RFC 2026 Section 10.4(A) Disclaimer.)"); - } - } - if (! has["rfc3979_5_p2"]) { - sectionerr("rfc3979_5_p2", "RFC 3979 Section 5, para. 2 IPR Disclosure Acknowledgement"); - } - if (! has["rfc3979_5_p3"]) { - sectionerr("rfc3979_5_p3", "RFC 3979 Section 5, para. 3 IPR Disclosure Invitation"); - if (has["rfc2026_10_4B"]) { - note("( - It does however have an RFC 2026 Section 10.4(B) IPR Disclosure Invitation.)"); - } - } - if ( has["rfc3667_3_claim"] || (has["rfc3667_5_1"] || has["rfc3978_5_1_a"]) && !has["rfc3978_5_1"]) { - err("The document uses RFC 3667 boilerplate or RFC 3978-like " \ - "boilerplate instead of verbatim RFC 3978 boilerplate. After 6 May 2005, " \ - "submission of drafts without verbatim RFC 3978 boilerplate is not " \ - "accepted."); +normalized ~ /by submitting this internet-draft/ { + para = get_para() + almost = almost_boilerplate["rfc3978_5_1"] + # Order is significant here -- try the longer text before subsets of it + if (match_para(para, "rfc3978_5_1", "rfc3978_5_2ax") || match_para(para, "rfc3978_5_1", "rfc3978_5_2a") || match_para(para, "rfc3978_5_1", "rfc3978_5_2bx") || match_para(para, "rfc3978_5_1", "rfc3978_5_2b") || match_para(para, "rfc3978_5_1") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2ax") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2a") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2bx") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2b") || match_para(para, "rfc3978_5_1_a") || match_para(para, "rfc3667_5_1", "rfc3978_5_2ax") || match_para(para, "rfc3667_5_1", "rfc3978_5_2a") || match_para(para, "rfc3667_5_1", "rfc3978_5_2bx") || match_para(para, "rfc3667_5_1", "rfc3978_5_2b") || match_para(para, "rfc3667_5_1")) { + almost_boilerplate["rfc3978_5_1"] = almost + } +} - note("The following non-3978 patterns matched text found in the document. That text should be removed or replaced:\n") - if (has["rfc3667_3_claim"]) showsection("rfc3667_3_claim", 2) - if (has["rfc3667_5_1"]) showsection("rfc3667_5_1", 2) - if (has["rfc3978_5_1_a"] && !has["rfc3978_5_1"]) showsection("rfc3978_5_1_a", 2) +normalized ~ /this document may not be modified/ { + para = get_para() + match_para(para, "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_c_ii") || match_para(para, "rfc3978_5_2a") || match_para(para, "rfc3978_5_2ax") || match_para(para, "rfc3978_5_2b") || match_para(para, "rfc3978_5_2bx") +} - } - if ((has["rfc3978_5_4_p1"] && has["rfc3978_5_4_p1_e"] ) || - (has["rfc3978_5_4_p1_u4748"] && has["rfc3978_5_4_p1_u4748_e"])) { - warn("In addition to a regular copyright notice, the document also has a " \ - "copyright notice embedded in the text."); - } - } else if (( has["rfc2026_lax_claim"] || - has["rfc2026b_lax_claim"] || - has["rfc2026_10_4C_p2"] || - has["rfc2026_10_4C_p3"] || - has["rfc2026_10_4C_p4"] ) ) { - if (option_verbose) { - print ""; - if (has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) - note(" [Claims RFC 2026 conformance...]") - if (has["rfc2026_10_4C_p1"]) - note(" [Has RFC 2026 Sec. 10.4 para. 1...]") - if (has["rfc2026_10_4C_p2"]) - note(" [Has RFC 2026 Sec. 10.4 para. 2...]") - if (has["rfc2026_10_4C_p3"]) - note(" [Has RFC 2026 Sec. 10.4 para. 3...]") - if (has["rfc2026_10_4C_p4"]) - note(" [Has RFC 2026 Sec. 10.4 para. 4...]") - print ""; - } - err("Looks like you\047re using RFC 2026 boilerplate. This must be updated to follow RFC 3978/3979, as updated by RFC 4748."); - } else { - if (some_copyright) { - copyright_msg = " Found some kind of copyright notice around line " some_copyright " but it does not match any copyright boilerplate known by this tool." - } else { - copyright_msg = "" - } - err("Cannot find the required boilerplate sections (Copyright, IPR, etc.) in this document." copyright_msg); +normalized ~ /copyright ?\(c\) ?the / { + if (! in_mib) { + some_copyright = FNR + para = get_para() + has_some_year = match_para(para, "rfc3978_5_4_p1", "rfc3978_5_4_p2", "rfc3978_5_5") + has_some_year = match_para(para, "rfc3978_5_4_p1_u4748", "rfc3978_5_4_p2", "rfc3978_5_5_u4748") || has_some_year + has_this_year = match_para(para, "rfc3978_5_4_p1_now") + has_this_year = match_para(para, "rfc3978_5_4_p1_u4748_now") || has_this_year + if (! has_some_year) { + match_para(para, "rfc3978_5_4_p1_e") + match_para(para, "rfc3978_5_4_p1_u4748_e") + } + match_para(para, "rfc2026_10_4C_p1", "rfc2026_10_4C_p2", "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") + if (has_some_year && ! has_this_year) { + has["rfc3978_5_4_p1_old"] = FNR + } + } +} + +normalized ~ /this document is subject to the rights/ { + para = get_para() + match_para(para, "rfc3978_5_4_p2") +} + +normalized ~ /this document and the information/ { + para = get_para() + match_para(para, "rfc3978_5_5") + match_para(para, "rfc3978_5_5_u4748") + match_para(para, "rfc2026_10_4C_p4") +} - note("Expected boilerplate is as follows today (" today ") according to https://trustee.ietf.org/license-info :\n") - showsection("trust-28-dec-2009_6_a") - showsection("trust-28-dec-2009_6_b_i_p2") - showsection("trust-28-dec-2009_6_b_i_p3") +normalized ~ /the ietf takes no position regarding/ { + para = get_para() + match_para(para, "rfc3979_5_p1", "rfc3979_5_p2", "rfc3979_5_p3") + match_para(para, "rfc2026_10_4A") +} + +normalized ~ /copies of ipr disclosures made to the/ { + para = get_para() + match_para(para, "rfc3979_5_p2", "rfc3979_5_p3") +} + +normalized ~ /the ietf invites any interested party/ { + para = get_para() + match_para(para, "rfc3979_5_p3") + match_para(para, "rfc2026_10_4B") +} + +normalized ~ /this document and translations of it/ { + para = get_para() + match_para(para, "rfc2026_10_4C_p2", "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") +} + +normalized ~ /the limited permissions granted above/ { + para = get_para() + match_para(para, "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") +} + +normalized ~ /the ietf has been notified of intellectual/ { + para = get_para() + match_para(para, "rfc2026_10_4D") +} + +normalized ~ /this document is an internet-draft and is/ { + para = get_para() + match_para(para, "rfc2026_lax_claim") + match_para(para, "rfc2026b_lax_claim") + ref_in_heading_nit = (has["rfc2026_lax_claim"] || has["rfc2026_lax_claim"]) && ! match_para(para, "rfc2026_claim") && ! match_para(para, "rfc2026b_claim") + match_para(para, "rfc3667_3_claim", "rfc3667_5_1") + match_para(para, "rfc3667_3_claim", "rfc3978_5_1_a") + match_para(para, "rfc3978_3_claim", "rfc3667_5_1") + match_para(para, "rfc3978_3_claim", "rfc3978_5_1") + match_para(para, "rfc3978_3_claim", "rfc3978_5_1_a") + if (match(para, reference_format)) { + update_references(para, FNR) } +} + +# IETF Trust Provisions boilerplate +normalized ~ /this internet-draft is submitted to ietf in/ { + para = get_para() + match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_i") + match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_ii") + match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_iii") + match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_i") + match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_ii") + match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_iii") +} - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) note("No issues found here."); +normalized ~ /this internet-draft is submitted in full/ { + para = get_para() + match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1a") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_ii") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_iii") +} - if ( !is_rfc ) { - announce("Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt:"); - errcount = errors; flawcount = flaws; warncount = warnings; commentcount = comments; +normalized ~ /copyright \(c\) [0-9]+ ietf trust and/ { + if (! in_mib) { + some_copyright = FNR + para = get_para() + has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_i_p3") + has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_ii_p3") + has_this_year = match_para(para, "trust-28-dec-2009_6_b_i_p2_now") + } +} - if (! has_id_indication) { - errg("Missing document type: Expected \"INTERNET-DRAFT\" in the upper left hand corner of the first page"); - } - - if (! has_expiration) { - errg("Missing expiration date. The document expiration date should appear on the first and last page.") - } - - if (!(has["1id_guidelines_p1"] || - has["1id_guidelines_p1a"])) { sectionerr("1id_guidelines_p1", "1id_guidelines paragraph about Internet-Drafts being working documents"); } - if (!(has["1id_guidelines_p2"] || - has["1id_guidelines_p2a"])) { sectionerr("1id_guidelines_p2", "1id_guidelines paragraph about 6 months document validity"); } - if (!(has["1id_guidelines_p3"] || - has["1id_guidelines_p3a"] || - has["1id_guidelines_p1a"])) { sectionerr("1id_guidelines_p3", "1id_guidelines paragraph about the list of current Internet-Drafts"); } - if (!(has["1id_guidelines_p4"] || - has["1id_guidelines_p4a"] || - has["1id_guidelines_p1a"])) { sectionerr("1id_guidelines_p4", "1id_guidelines paragraph about the list of Shadow Directories"); } - if (has["1id_guidelines_p1a"] && - has["1id_guidelines_p3"]) { newandolderr("1id_guidelines_p3", "1id_guidelines_p1a"); } - if (has["1id_guidelines_p1a"] && - has["1id_guidelines_p3a"]) { newandolderr("1id_guidelines_p3a", "1id_guidelines_p1a"); } - if (has["1id_guidelines_p1a"] && - has["1id_guidelines_p4"]) { newandolderr("1id_guidelines_p4", "1id_guidelines_p1a"); } - if (has["1id_guidelines_p1a"] && - has["1id_guidelines_p4a"]) { newandolderr("1id_guidelines_p4a", "1id_guidelines_p1a"); } - - if (has_docname) { - file_docname = option_filename - - # Get rid of path and extension - sub(".*/", "", file_docname) - sub(/\.(txt|pdf|xml|doc|nr)$/, "", file_docname) - - sub(".*/", "", full_docname) - sub(/\.(txt|pdf|xml|doc)$/, "", full_docname) - - if (good_docname != full_docname || full_docname ~ /[^a-z0-9-]/) { - errg(sprintf("Bad filename characters: the document name given in the document, '%s', contains other characters than digits, lowercase letters and dash.", full_docname)) - } else if (file_docname ~ /[^a-z0-9-]/) { - errg(sprintf("Bad filename characters: the file name of the draft, '%s', contains other characters than digits, lowercase letters and dash.", file_docname)) - } - - if ( ! match(full_docname, /.*-[0-9][0-9]$/) ) { - errg(sprintf("Missing revision: the document name given in the document, '%s', does not give the document revision number", full_docname)) - } - - doc_has_empty_source = 0; - if ( match(full_docname, /^draft--/) ) { - doc_has_empty_source = 1; - errg(sprintf("Empty name element: the document name given in the document, '%s', lacks the source element (it starts with 'draft--'). See https://www.ietf.org/id-info/1id-guidelines.txt, section 7, on how to construct a good document name.", full_docname)) - } - - if ( match(full_docname, /--[0-9][0-9]$/) ) { - errg(sprintf("Negative revision number: the document name given in the document, '%s', seems to have a negative revision number (it ends with '--%s'). See https://www.ietf.org/id-info/1id-guidelines.txt, section 7, on how to construct a good document name.", full_docname, substr(full_docname, length(full_docname)-1))) - } - - if ( ! match(full_docname, /^draft-[^-]+-.+-[0-9][0-9](\.[a-z]+)?$/) ) { - if (! doc_has_empty_source) { - flaw(sprintf("Missing draftname component: the document name given in the document, '%s', does not seem to contain all the document name components required ('draft' prefix, document source, document name, and revision) -- see https://www.ietf.org/id-info/guidelines#naming for more information.", full_docname)); - } - } - - if (length(file_docname) > length(full_docname)) long_docname = file_docname; else long_docname = full_docname; - sub(/-[0-9][0-9]$/, "", long_docname); - if (length(long_docname) > 50) { - errg(sprintf("Too long document name: The document name (without revision number), '%s', is %d characters long, but may be at most 50 characters", long_docname, length(long_docname))) - } - - if (file_docname && file_docname != full_docname) { - warn(sprintf("Mismatching filename: the document gives the document name as '%s', but the file name used is '%s'", full_docname, file_docname)) - } - - } else { - errg("Expected the document's filename to be given on the first page, but didn't find any"); - } - - if (has["rfc3978_5_1"] > firstpagelength && !is_rfc) { - errg("An " expandname("rfc3978_5_1") " paragraph was found, but not on the first page, as required." ); - } - - # According to the nits page we should be comparing to 15 here, but - # that may be without the boilerplate - and practice seems to permit - # also 16 pages including boilerplate, so... - if (!has_toc && ((pagecount > 16) || (FNR > 50*16))) { - errw("The document is more than 15 pages and seems to lack a Table of Contents."); - } +normalized ~ /this document is subject to bcp 78/ { + para = get_para() + match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_i") + match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_ii") + match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_iii") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_i") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_ii") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_iii") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_i") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_ii") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_iii") + match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_i") + match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_ii") + match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_iii") + match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_i") + match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_ii") + match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_iii") +} - if (nonascii && !option_nonascii) { - warn(sprintf("There %s %d instance%s of lines with non-ascii characters in the document.", \ - (nonascii==1?"is":"are"), nonascii, (nonascii==1?"":"s") )); - } +normalized ~ /this document may contain material from ietf/ { + para = get_para() + match_para(para, "trust-12-sep-2009_6_c_iii") + match_para(para, "trust-28-dec-2009_6_c_iii") +} - if (length(intended_status) == 0) { - warn("No 'Intended status' indicated for this document; assuming Proposed Standard"); - intended_status = "proposed standard"; - } - - if ( maxpagelength > 58 ) { - warnc(sprintf("The page length should not exceed 58 lines per page, " \ - "but there was %d longer page%s, the longest (page %d) being %d lines", longpagecount, (longpagecount==1?"":"s"), longestpage, maxpagelength)); - } - if ( pagecount > formfeedcount+1 ) { - warnc(sprintf("It seems as if not all pages are separated by form feeds - " \ - "found %d form feeds but %d page%s", formfeedcount, pagecount, (pagecount==1?"":"s"))); - } - if ( missing_nroff_postprocessing ) { - comment(sprintf("Found %d instances of the string 'FORMFEED[Page...' -- is this a case of missing nroff postprocessing?", missing_nroff_postprocessing)) - } - - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) note("No issues found here."); +# RFC 2119 compliance +normalized ~ /(the key ?words|in this document, several words are used)/ { + para = get_para() + if (match_para(para, "rfc2119_p2") || match_para(para, "rfc2119_p2a") || match_para(para, "rfc8174_p11")) { + if (match(para, /NOT RECOMMENDED/)) { + rfc2119_p2_not_recommended++ + } + } + if (match(para, reference_format)) { + reftag = substr(para, RSTART + 1, RLENGTH - 2) + reftag2119 = reftag + update_references(para, FNR) } +} - if (option_submitcheck) { - announce("Running in submission checking mode -- *not* checking nits according to https://www.ietf.org/id-info/checklist .") - } else { - announce("Checking nits according to https://www.ietf.org/id-info/checklist :") - errcount = errors; flawcount = flaws; warncount = warnings; commentcount = comments; - - if (!has_abstract) { err("The document seems to lack an Abstract section.", indented_abstract); } - if (!has_intro) { errc("The document seems to lack an Introduction section.", indented_intro); } - if (!has_security) { errc("The document seems to lack a Security Considerations section.", indented_security); } - if (is_rfc) { - if (!has_iana) { comment("The document seems to lack an IANA Considerations section. ", indented_iana); } - } else { - if (!has_iana) { errc("The document seems to lack an IANA Considerations section. " \ - "(See Section 2.2 of https://www.ietf.org/id-info/checklist for how " \ - "to handle the case when there are no actions for IANA.)", indented_iana); } - } - if (!has_addr) { errc("The document seems to lack an Authors\047 Addresses Section."); } - if (has_refs && ! has_splitrefs) { - errc("The document seems to lack separate sections for Informative/Normative References. " \ - "All references will be assumed normative when checking for downward references."); - } - - if (option_list_matches) { - print fold(" Boilerplate matches:", " ", columns) - for ( n in has ) { - if (n) note(sprintf("Found", n, "on line", has[n])) - } - print ""; - } - - if (spacing > 50) { - errc(sprintf("There %s %d instance%s of weird spacing in the document. " \ - "Is it really formatted ragged-right, rather than justified?", \ - (spacing==1?"is":"are"), spacing, (spacing==1?"":"s") )); - } - - if (longlines) { - msg = sprintf("There %s %d instance%s of too long lines in the document, " \ - "the longest one being %d character%s in excess of 72.", \ - (longlines==1?"is":"are"), longlines, (longlines==1?"":"s"), \ - excesslength, ((excesslength > 1) ? "s" : "")); - if (!option_submitcheck) { - errc(msg); - } else { - warn(msg); - } - } - - if (controlchars) { - errc(sprintf("There %s %d instance%s of lines with control characters in the document.", \ - (controlchars==1?"is":"are"), controlchars, (controlchars==1?"":"s") )); - } - - if (abstract_references) { - list(abstract_references, ref_list) - ref_str = "" - for (i in ref_list) { - if (ref_str) ref_str = ref_str ", "; - ref_str = ref_str i; - } - errc("The abstract seems to contain references (" ref_str "), which it shouldn't. Please replace those with straight textual mentions of the documents in question.") - } - - if (badfqdns) { - warnc(sprintf("There %s %d instance%s of lines with " \ - "non-RFC2606-compliant FQDNs in the document.", \ - (controlchars==1?"is":"are"), badfqdns, (badfqdns==1?"":"s") )); - } - - if (badipv4addr) { - warnc(sprintf("There %s %d instance%s of lines with " \ - "non-RFC6890-compliant IPv4 addresses in the document. " \ - "If these are example addresses, they should be changed.", \ - (controlchars==1?"is":"are"), badipv4addr, (badipv4addr==1?"":"s") )); - } - if (mcastipv4addr) { - warnc(sprintf("There %s %d instance%s of lines with " \ - "multicast IPv4 addresses in the document. " \ - "If these are generic example addresses, they should be changed " \ - "to use the 233.252.0.x range defined in RFC 5771", \ - (controlchars==1?"is":"are"), mcastipv4addr, (mcastipv4addr==1?"":"s") )); - } - if (privipv4addr) { - warnc(sprintf("There %s %d instance%s of lines with " \ - "private range IPv4 addresses in the document. " \ - "If these are generic example addresses, they should be changed " \ - "to use any of the ranges defined in RFC 6890 (or successor): " \ - "192.0.2.x, 198.51.100.x or 203.0.113.x.", \ - (controlchars==1?"is":"are"), privipv4addr, (privipv4addr==1?"":"s") )); - } - - if (badipv6addr) { - warnc(sprintf("There %s %d instance%s of lines with " \ - "non-RFC3849-compliant IPv6 addresses in the document. " \ - "If these are example addresses, they should be changed.", \ - (controlchars==1?"is":"are"), badipv6addr, (badipv6addr==1?"":"s") )); - } - if (ulipv6addr) { - warnc(sprintf("There %s %d instance%s of lines with " \ - "Unique Local Unicast IPv6 addresses (RFC 4193) in the document. " \ - "If these are generic example addresses, they should be changed", \ - "to use the 2001:DB8::/32 range defined in RFC 4291.", \ - (controlchars==1?"is":"are"), ulipv6addr, (ulipv6addr==1?"":"s") )); - } - if (llipv6addr) { - warnc(sprintf("There %s %d instance%s of lines with " \ - "Link Local Unicast IPv6 addresses (RFC 4291) in the document. " \ - "If these are generic example addresses, they should be changed", \ - "to use the 2001:DB8::/32 range defined in RFC 4291.", \ - (controlchars==1?"is":"are"), llipv6addr, (llipv6addr==1?"":"s") )); - } - if (ipv4_example_addr && !ipv6_example_addr) { - comment("The document has examples using IPv4 documentation addresses " \ - "according to RFC6890, but does not use any IPv6 documentation " \ - "addresses. Maybe there should be IPv6 examples, too?"); - } - - if ( keywords && !has["rfc2119_p2"] && !has["rfc2119_p2a"] !has["rfc8174_p11"]) { - # Check whether there is a reference to RFC 2119 at all - for (reftag in ref_text) { - if (ref_text[reftag] ~ /RFC[- ]?2119/) found_2119_ref = ref_def[reftag]; - } - if ( ! found_2119_ref ) { - sectionerr("rfc8174_p11" , "both a reference to RFC 2119 and the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords", option_checklistwarn) - if ( option_verbose <= 1) { - for (i=1; i<=5; i++) { - if (i in rfc2119line) { - fnr = rfc2119line[i] - printf(" RFC 2119 keyword, line %d: '...%s...'\n", fnr, line[fnr]); - } - } - if (keywords > 5) - note(sprintf("(%d more instance%s...)",keywords-5, (keywords-5==1?"":"s"))); - } - print(""); - } - } - - if (obsoletes_junk) { - warnc("The 'Obsoletes: ' line in the draft header should list only the _numbers_ of the RFCs " \ - "which will be obsoleted by this document (if approved); it should not include the word " \ - "'RFC' in the list."); - } - - if (updates_junk) { - warnc("The 'Updates: ' line in the draft header should list only the _numbers_ of the RFCs " \ - "which will be updated by this document (if approved); it should not include the word " \ - "'RFC' in the list."); - } - - list(abstract_mentions, abstract_rfcs) - - list(obsoletes_docs, obsoletes_list) - list(abstract_obsoletes, abs_obs_list) - for (doc in obsoletes_list) { - if (! (doc in abs_obs_list)) { - if (doc in abstract_rfcs) { - comment("The draft header indicates that this document obsoletes " doc ", but the abstract doesn't seem to directly say this. It does mention " doc " though, so this could be OK.") - } else { - comment("The draft header indicates that this document obsoletes " doc ", but the abstract doesn't seem to mention this, which it should.") - } - } - } - for (doc in abs_obs_list) { - if (! (doc in obsoletes_list)) { - comment("The abstract seems to indicate that this document obsoletes " doc ", but the header doesn't have an 'Obsoletes:' line to match this.") - } - } - - list(updates_docs, updates_list) - list(abstract_updates, abs_upd_list) - for (doc in updates_list) { - if (! (doc in abs_upd_list)) { - if (doc in abstract_rfcs) { - comment("The draft header indicates that this document updates " doc ", but the abstract doesn't seem to directly say this. It does mention " doc " though, so this could be OK.") - } else { - comment("The draft header indicates that this document updates " doc ", but the abstract doesn't seem to mention this, which it should.") - } - } - } - for (doc in abs_upd_list) { - if (! (doc in updates_list)) { - comment("The abstract seems to indicate that this document updates " doc ", but the header doesn't have an 'Updates:' line to match this.") - } - } - - - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) note("No issues found here."); - - - # -------------------------------------------------------------- - # Warnings - - { - announce("Miscellaneous warnings:") - errcount = errors; flawcount = flaws; warncount = warnings; commentcount = comments; - warnshere = warnings; - - if (has_pk_mark) { comment("The first octets (the first characters of the first line) of this " \ - "draft are 'PK', which can make Internet Explorer erroneously think " \ - "that it is a zip file. It is recommended that you change this, for " \ - "instance by inserting a blank line before the line starting with 'PK'.") } - - if (has_bm_mark) { comment("The first octets (the first characters of the first line) of this " \ - "draft are 'BM', which can make the draft submission tool erroneously think " \ - "that it is an image .bmp file. It is recommended that you change this, for " \ - "instance by inserting a blank line before the line starting with 'BM'.") } - - checkmultibp("rfc3978_5_1"); - checkmultibp("rfc3978_5_2b"); - checkmultibp("rfc3978_5_3"); - checkmultibp("rfc3978_5_5"); - checkmultibp("rfc3978_5_5_u4748"); - checkmultibp("rfc3979_5_p1"); - checkmultibp("rfc3979_5_p2"); - checkmultibp("rfc3979_5_p3"); - - if ( ( has["rfc2026_lax_claim"] || - has["rfc2026b_lax_claim"] ) && - - ( has["rfc2026_10_4C_p2"] || - has["rfc2026_10_4C_p3"] || - has["rfc2026_10_4C_p4"] ) ) { - if (option_rfc2026) { - - if (!has["rfc2026_10_4A"] ) { warn("The document seems to lack an RFC 2026 Section 10.4(A) Disclaimer."); } - if (!has["rfc2026_10_4B"] ) { warn("The document seems to lack an RFC 2026 Section 10.4(B) IPR Disclosure Invitation."); } - if ( has["rfc2026_10_4D"]) { warn("The document has an RFC 2026 Section 10.4(D) IPR Notice."); } - - } +#/^[ \t0-9.]*Table Of [Cc]ontents?:?$/ { has_toc = 1; misspelled_toc = 1} +/^[ \t0-9.]*(Author|Editor)([^\047]s|s[^\047]) [Aa]ddress(es)?$/ { + has_addr = 1 + misspelled_addr = 1 +} + +/^[ \t0-9.]*(Authors?|Editors?) +[Aa]ddress(es)?$/ { + has_addr = 1 + misspelled_addr = 1 +} + +# 1id_guidelines.txt compliance +normalized ~ /internet-drafts are working documents of/ { + para = get_para() + match_para(para, "1id_guidelines_p1", "1id_guidelines_p2", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p1", "1id_guidelines_p2a", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p1a", "1id_guidelines_p2") || match_para(para, "1id_guidelines_p1a", "1id_guidelines_p2a") +} + +normalized ~ /internet-drafts are draft documents valid for/ { + para = get_para() + match_para(para, "1id_guidelines_p2", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p2a") +} + +normalized ~ /the list of current internet-drafts can be/ { + para = get_para() + match_para(para, "1id_guidelines_p3", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p3a", "1id_guidelines_p4a") +} + +normalized ~ /the list of internet-draft shadow directories/ { + para = get_para() + match_para(para, "1id_guidelines_p4") || match_para(para, "1id_guidelines_p4a") +} + +normalized ~ /^obsoletes: / { + if (FNR < 10) { + c = split($0, obsoletelist, /[, ]+/) + docs = "" + for (i = 2; i < c; i++) { + header_obsoletes = 1 + word = obsoletelist[i] + if (word ~ /^[0-9]+/) { + docs = docs "RFC" word " " + } + if (word ~ /^draft-/) { + docs = docs word " " + } + if (word ~ /^[0-9]+$/) { + obsoletes[word] = FNR + } else if (word ~ /[Rr][Ff][Cc]/) { + obsoletes_junk = FNR + } else { + break + } } - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes ) { - if ( has["rfc3978_5_2a"]) { warn("The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause."); } - } else { - if ( has["rfc3978_5_2a"]) { note("The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause."); } + if (docs) { + gsub(/ $/, "", docs) } - if ( has["rfc3978_5_4_p1"] && - !has["rfc3978_5_4_p1_now"]) { warn("The copyright year in the RFC 3978 Section 5.4 Copyright Line does not match the current year"); } - if ( has["rfc3978_5_4_p1_u4748"] && - !has["rfc3978_5_4_p1_u4748_now"]) { warn("The copyright year in the IETF Trust Copyright Line does not match the current year"); } - if ( has["trust-28-dec-2009_6_b_i_p2"] && - !has["trust-28-dec-2009_6_b_i_p2_now"]) { warn("The copyright year in the IETF Trust and authors Copyright Line does not match the current year"); } - if ( has["rfc3978_5_4_p1_old"] && - has["rfc3978_5_4_p1_now"]) { warn(sprintf("The copyright year in the RFC 3978 Section 5.4 Copyright around line %s does not match the year around line %s", - has["rfc3978_5_4_p1_old"], has["rfc3978_5_4_p1_now"])); - } - if ( has["rfc3978_5_4_p1_old"] && - has["rfc3978_5_4_p1_u4748_now"]) { warn(sprintf("The copyright year in the IETF Trust Copyright around line %s does not match the year around line %s", - has["rfc3978_5_4_p1_old"], has["rfc3978_5_4_p1_u4748_now"])); - } - - # if (has["rfc3978_5_4_p1"] > firstpagelength) { - # warn( "An " expandname("rfc3978_5_4_p1") " paragraph was found, but not on the first page, as suggested." ); - # } - # - # if (has["rfc3978_5_4_p1_u4748"] > firstpagelength) { - # warn( "An " expandname("rfc3978_5_4_p1_u4748") " paragraph was found, but not on the first page, as suggested." ); - # } - # - - if (hyphens && !is_rfc) { - warnc(sprintf("There %s %d instance%s of lines with hyphenated line breaks in the document.", \ - (hyphens==1?"is":"are"), hyphens, (hyphens==1?"":"s"))); - } - - if ( misspelled_toc ) { warnc("The \"Table of Contents\" section title seems to be misspelled."); } - - if ( misspelled_addr ) { warnc("The \"Author\047s Address\" (or \"Authors\047 Addresses\") section title is misspelled."); } - - if (!option_verbose && spacing) { - for (i=1; i<=5; i++) { - if (i in sp_line) - warnc(sprintf("Line %d has weird spacing: \047...%s...\047", linenum[i], extract[i])); - } - if (spacing > 5) - warnc(sprintf("(%d more instance%s...)",spacing-5, (spacing-5==1?"":"s"))); - } - - if ( keywords && !has["rfc2119_p2"] && !has["rfc2119_p2a"] && !has["rfc8174_p11"] && found_2119_ref ) { - sectionwarn("rfc8174_p11", "the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords") - note("(The document does seem to have the reference to RFC 2119 which the ID-Checklist requires).") - } - - if ( keywords && !has["rfc2119_p2"] && has["rfc2119_p2a"] && !has["rfc8174_p11"]) { - # Require that the reference used in "rfc2119_p2a" actually mentions RFC 2119... - if ( ref_text[reftag2119] !~ /RFC[- ]?2119/) { - errg(sprintf("The document contains RFC2119-like boilerplate, but doesn't seem to mention RFC 2119. The boilerplate contains a reference [%s], but that reference does not seem to mention RFC 2119 either.", reftag2119)) - } - } - - if ( has_not_recommended && ( has["rfc2119_p2"] || has["rfc2119_p2a"] || has["rfc8174_p11"]) && !rfc2119_p2_not_recommended ) { - warnc("The document seems to use 'NOT RECOMMENDED' as an RFC 2119 keyword, but does not include the phrase in its RFC 2119 key words list."); - } - - if ( !keywords ) { - if (has["rfc2119_p2"] || has["rfc2119_p2a"] || has["rfc8174_p11"]) { - warnc("The document doesn't use any RFC 2119 keywords, yet seems to have RFC 2119 boilerplate text.") - } else if (almost_boilerplate["rfc2119_p2"] || almost_boilerplate["rfc2119_p2a"] || almost_boilerplate["rfc8174_p11"]) { - warnc("The document doesn't use any RFC 2119 keywords, yet has text resembling RFC 2119 boilerplate text.") - } - } - - for (combo in rfc2119undefined) { - comment("The exact meaning of the all-uppercase expression '" combo \ - "' is not defined in RFC 2119. If it is intended as a requirements " \ - "expression, it should be rewritten using one of the combinations " \ - "defined in RFC 2119; otherwise it should not be all-uppercase.") - } - - for (bad_line in found_bad_pat) { - pattern = found_bad_pat[bad_line] - para = found_bad_para[bad_line] - warn(bad[pattern] "\n\n Found '" strip(pattern) "' in this paragraph:\n\n " para) - } - - if ( ! (intended_status in status2code) ) { - warn(sprintf("Unrecognized Status in '%s', assuming Proposed Standard", intended_status_text)); - note("(Expected one of 'Standards Track', 'Full Standard', 'Draft Standard', 'Proposed Standard', 'Best Current Practice', 'Informational', 'Experimental', 'Informational', 'Historic'.)\n") - intended_status = "proposed standard"; - } - - - { - # The 'RFC 5378 fix' announced around 5 Feb 2009 means that drafts first - # submitted before 10 Nov 2008 with a high probability should have an additional - # boilerplate paragraph excempting it from full 5378 compliance. On the other - # hand, a draft first submitted on or after 10 Nov 2008 should probably not have - # such a paragraph. - if (has_docname) docname = full_docname; else docname = file_docname; - sub(/-[0-9][0-9](\.txt)?$/, "", docname) - get_state(docname, docstate, 1) - if ("creationdate" in docstate) created = docstate["creationdate"] - if ("created" in docstate) created = docstate["created"] - - for (i in obsoletes) { - if (i !~ /draft-/) continue; - refcreated = get_creation_date("rfc" i); - if (refcreated && jdn(refcreated) < jdn(created) && jdn(refcreated) < jdn("2008-11-10")) { - created = refcreated; - refcreated = ""; - note(sprintf("(Using the creation date from RFC%i, obsoleted by this document, for RFC5378 checks: %s)\n", i, created)) - } - } - for (i in updates) { - if (i ~ /draft-/) continue; - refcreated = get_creation_date("rfc" i); - if (refcreated && jdn(refcreated) < jdn(created) && jdn(refcreated) < jdn("2008-11-10")) { - created = refcreated; - refcreated = ""; - note(sprintf("(Using the creation date from RFC%i, updated by this document, for RFC5378 checks: %s)\n", i, created)) - } - } -# for (key in docstate) { -# printf("docstate[%s]: %s\n", key, docstate[key]); -# } - - - if (created ~ /[12][0-9][0-9][0-9]-[01][0-9]-[0123][0-9]/) {\ - if (jdn(created) < jdn("2008-11-10")) { - if (! has["trust-28-dec-2009_6_c_iii"]) { - sectioncomment("trust-28-dec-2009_6_c_iii", - "disclaimer for pre-RFC5378 work, but may have content which was first " \ - "submitted before 10 " \ - "November 2008. If you have contacted all the original authors and they " \ - "are all willing to grant the BCP78 rights to the IETF Trust, then this " \ - "is fine, and you can ignore this comment. If not, you may need to add " \ - "the pre-RFC5378 disclaimer. (See the Legal Provisions document at " \ - "https://trustee.ietf.org/license-info for more information.)") - } else { - comment("The document seems to contain a disclaimer for pre-RFC5378 work, and " \ - "may have content which was first submitted before 10 November 2008. " \ - "The disclaimer is necessary when "\ - "there are original authors that you have been unable to contact, or " \ - "if some do not wish to grant the BCP78 rights to the IETF Trust. If " \ - "you are able to get all authors (current and original) to grant those " \ - "rights, you can and should remove the disclaimer; otherwise, the " \ - "disclaimer is needed and you can ignore this comment. " \ - "(See the Legal Provisions document at https://trustee.ietf.org/license-info " \ - "for more information.)") - } - } else { # document created on or after 2008-11-10 - if (has["trust-28-dec-2009_6_c_iii"]) { - warn("The document seems to contain a disclaimer for pre-RFC5378 work, but was " \ - "first submitted on or after 10 November 2008. The disclaimer is usually " \ - "necessary only for documents that revise or obsolete older RFCs, and " \ - "that take significant amounts of text from those RFCs. If you can " \ - "contact all authors of the source material and they are willing to " \ - "grant the BCP78 rights to the IETF Trust, you can and should remove " \ - "the disclaimer. Otherwise, the disclaimer is needed and you can " \ - "ignore this comment. (See the Legal Provisions document at " \ - "https://trustee.ietf.org/license-info for more information.)") - } else { - ; # No comment for documents created after 2008-11-10 without a disclaimer - } - } - } else { - warn("Couldn't figure out when the document was first submitted -- there may comments " \ - "or warnings related to the use of a disclaimer for pre-RFC5378 work that could " \ - "not be issued because of this. Please check the Legal Provisions document at " \ - "https://trustee.ietf.org/license-info to determine if you need the pre-RFC5378 " \ - "disclaimer."); - - } - } - - { - if (doc_date) { - days_off = doc_date - jdn(today) - if (days_off > date_skew) - comment(sprintf("The document date (%s) is %s days in the future. Is this intentional?", date_lit, days_off)); - if (days_off < -date_skew) - comment(sprintf("The document date (%s) is %s days in the past. Is this intentional?", date_lit, -days_off)); - } else { - comment("Couldn't find a document date in the document -- date freshness check skipped.") - } - } - - - if (code_comment_found) { - comment("Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines."); - } - - - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) note("No issues found here."); - } - { - announce("Checking references for intended status: " (code2status[status2code[intended_status]] ? code2status[status2code[intended_status]] : "None")) - errcount = errors; flawcount = flaws; warncount = warnings; commentcount = comments; - warnshere = warnings; - - intended_code = status2code[intended_status]; - split(warncodes[intended_code], warnlist); - for (i in warnlist) warnlist[warnlist[i]]; - - std_codes["B"];std_codes["P"];std_codes["D"];std_codes["S"]; - if (intended_code in std_codes) { - note("(See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs)\n") - } - - for ( i = 1; i <= ref_use_count; i++ ) { - tag = ref_use_list[i] - if (! (tag in ref_def)) { - is_numeric = tag ~ /^[0-9]+$/ - if ((is_numeric && has_numeric_refs) || (!is_numeric && has_symbolic_refs)) { - warnc(sprintf("Missing Reference: '%s' is mentioned on line %s, but not defined", tag, ref_use[tag]) \ - (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]],1,68))) : "")); - miss_ref[tag]; - check_downref(tag, warnlist); - } else if (has_numeric_refs || has_symbolic_refs) { - comment(sprintf("Looks like a reference, but probably isn't: '%s' on line %s", tag, ref_use[tag]) \ - (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]],1,68))) : "")); + obsoletes_docs = docs + } +} + +normalized ~ /^updates: / { + if (FNR < 10) { + c = split($0, updatelist, /[, ]+/) + docs = "" + for (i = 2; i < c; i++) { + header_updates = 1 + word = updatelist[i] + if (word ~ /^[0-9]+/) { + docs = docs "RFC" word " " + } + if (word ~ /^draft-/) { + docs = docs word " " + } + if (word ~ /^[0-9]+$/) { + updates[word] = FNR + } else if (word ~ /[Rr][Ff][Cc]/) { + updates_junk = FNR } else { - comment(sprintf("Missing reference section? '%s' on line %s looks like a reference", tag, ref_use[tag]) \ - (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]],1,68))) : "")); + break } - - } } - - for ( i = 1; i <= ref_def_count; i++ ) { - tag = ref_def_list[i]; - if (! (tag in ref_use)) { - warnc(sprintf("Unused Reference: '%s' is defined on line %s, but no explicit reference was found in the text", tag, ref_def[tag]) \ - (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_def[tag]],1,68))) : "")); - } + if (docs) { + gsub(/ $/, "", docs) } + updates_docs = docs + } +} - for ( i = 1; i <= ref_def_count; i++ ) { - tag = ref_def_list[i]; - check_downref(tag, warnlist); +/draft-/ { + if (! has_intro && ! has_abstract && ! has_refs && ! has_appendix && ! has_docname) { + if ($0 ~ /Updates: *draft-/) { + updates[$2] + } else if ($0 ~ /Obsoletes: *draft-/) { + obsoletes[$2] + } else { + match($0, /draft-[a-z0-9-]*/) + good_docname = substr($0, RSTART, RLENGTH) + match($0, /draft-[^ \t>]*/) + full_docname = substr($0, RSTART, RLENGTH) + has_docname = 1 } - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) note("No issues found here."); - } } +} - # -------------------------------------------------------------- - # Summary +# References and downref checking +normalized ~ /(intended status|category):/ { + if (! has_intro && ! has_abstract && ! has_refs && ! has_appendix && ! has_status_of_memo) { + sta = tolower($0) + sub(/^.*(intended status|category): */, "", sta) + sub(/ .*$/, "", sta) + if (length(intended_status) == 0) { + intended_status = sta + intended_status_text = $0 + sub(/ .*$/, "", intended_status_text) + } + } +} - if (errors == 0 && warnings == 0 && comments == 0) { - print ""; - note("No nits found."); +$0 ~ reference_format { + if (in_refs) { + refpos = FNR + reftext = strip($0) + while (((getline) > 0) && (text = strip($0)) != "") { + check_line() + if ($0 ~ reference_format) { + # start of a new reference without intervening blank line + update_references(reftext, refpos) + refpos = FNR + reftext = text + } else if (reftext ~ /-$/) { + reftext = reftext text + } else { + reftext = reftext " " text + } + } + update_references(reftext, refpos) } else { - print ""; - note(sprintf("Summary: %d error%s (%s), %d flaw%s (%s), %d warning%s (%s), %d comment%s (%s).", errors, (errors==1?"":"s"), errmark, flaws, (flaws==1?"":"s"), flawmark, warnings, (warnings==1?"":"s"), warnmark, comments, (comments==1?"":"s"), infomark)); - if ( !option_verbose && !option_submitcheck ) { - print ""; - note("Run idnits with the --verbose option for more detailed information about the items above."); - } - } - } -} - - -function check_line() { - got_input = 1; - - gsub(/\r/,""); - sub(/[\n\t ]+$/, ""); - thiscolumn = match($0, /[^ ]/); - if (thiscolumn && thiscolumn < indentation) indentation = thiscolumn; - - # 1.1.a Max column 72 - if (length($0) > 72 && ! skip_file) { - if (match($0, "[^\001-\177]")) { - printf("%s(%d): Line appears to be too long, but this could be caused by non-ascii characters in UTF-8 encoding\n", FILENAME, FNR); - } else { - if (option_verbose && option_pass1) { - printf("%s(%d): Line is too long: the offending characters are \047%s\047\n", FILENAME, FNR, substr($0,73)); - } - longlines++; - if (length($0) - 72 > excesslength) { - excesslength = length($0) - 72; - } - } - } - - # 1.1.b Ragged right - if (! skip_file && ! match($0, /^ *Internet.Draft/) && ! match($0, /^ *INTERNET.DRAFT/) && match($0, /[A-Za-z][a-z] ? ?[a-z]/) ) { - if (option_verbose && option_pass1 ) { - printf("%s(%d): Line has weird spacing: \047...%s...\047\n", FILENAME, FNR, substr($0, RSTART-5, 14)); - } - spacing++; - sp_line[spacing] = $0; - linenum[spacing] = FNR; - extract[spacing] = substr($0, RSTART-5, 14) - - } - - # 1.1.c No hyphenation for line-breaks - if ( $0 ~ /[A-Za-z0-9_]-$/ && ! skip_file && ! has_refs && has_hyphenlist ) { - word = $0 - sub(/^.*[^A-Za-z0-9_-]/, "", word) - if ( ! word in hyphenfrags ) { - if (option_verbose && option_pass1) { - printf("%s(%d): Line seems to end with a hyphenated word.\n", FILENAME, FNR) - if (option_verbose > 1 && option_pass1) { - printf(" --> %s\n", $0); - } - } - hyphens++ - } - } - - # 1.1.e ASCII-only - # The test really should go from \200 to \377 - but the awk implementation - # on *BSD seems to have used \377 internally as a sentinel or something... - if (match($0, "[^\001-\177]") && ! skip_file) { - if (option_verbose && option_pass1) { - printf("%s(%d): Found non-ascii character (%s) in position %d.\n", FILENAME, FNR, substr($0, RSTART,1), RSTART); - if (option_verbose > 1 && option_pass1) { - printf(" --> %s\n", $0); - printf(" %*s\n", RSTART, "^"); - } - } - nonascii++; - } - # 1.1.e no control characer except CR NL FF - # nawk can't handle octal escapes inside character classes, it seems. Sigh. - # if (match($0, /[\001-\011\013\016-\037]/) && ! skip_file) ... - if (match($0, /(\001|\002|\003|\004|\005|\006|\007|\010|\011|\013|\016|\017|\020|\021|\022|\023|\024|\025|\026|\027|\030|\031|\032|\033|\034|\035|\036|\037)/) && ! skip_file) { - if (option_verbose && option_pass1) { - printf("%s(%d): Found control character %s in position %d.\n", FILENAME, FNR, controlchar[substr($0, RSTART, 1)], RSTART); - if (option_verbose > 1 && option_pass1) { - printf(" --> %s\n", $0); - printf(" %*s\n", RSTART, "^"); - } - } - controlchars++; - } - - # 1.1.f Do not number the Abstract section - if ( $0 ~ /^[ \t]*Abstract[ \t]*$/ ) { - abstract_seen = 1; - } - if ( $0 ~ /^[ \t]*[0-9][.0-9 \t]*Abstract[ \t]*$/ && ( ! abstract_seen ) && ! skip_file && option_pass2) { - errg("The Abstract section seems to be numbered"); - abstract_seen = 1; - } - - # 1.1.f Do not number the "Status of Memo" section - if ( $0 ~ /^[ \t]*Status of (This )?Memo[ \t]*$/ ) { - has_status_of_memo = 1; - } - if ( $0 ~ /^[ \t]*[0-9][.0-9 \t]*Status of (This )?Memo[ \t]*$/ && ( ! has_status_of_memo ) && ! skip_file && option_pass2) { - errg("The Status of Memo section seems to be numbered"); - has_status_of_memo = 1; - } - - # RFC 2119 language - if (!match($0, "IN NO EVENT SHALL") && !match($0,"SHALL THE COPYRIGHT") \ - && match($0, /[ \t](MUST|REQUIRED|SHALL|SHOULD|RECOMMENDED|MAY|OPTIONAL)([ \t\.,]|$)/ ) \ - ) { - - keywords++; - rfc2119line[keywords] = FNR; - rstart = RSTART-16; - rlength = 38; - if (rstart+rlength > length($0)) rstart = length($0) - rlength +1; - if (rstart < 1) rstart = 1; - if ( ! (FNR in line) ) line[FNR] = substr($0, rstart, rlength); - if (option_verbose > 1 && option_pass1) { - printf("%s(%d): RFC 2119 keyword: %s.\n", FILENAME, FNR, $0); - } - - # Keywords: - # - # MUST MUST NOT - # SHALL SHALL NOT - # SHOULD SHOULD NOT - # RECOMMENDED NOT RECOMMENDED - # REQUIRED - # MAY - # OPTIONAL - - # Find uppercase words before or after our keywords, and check if the combination is defined - l = $0 - sub(/\t/, " ", l) - notkwds["MAY NOT"]; notkwds["NOT REQUIRED"]; notkwds["NOT OPTIONAL"]; - for (combo in notkwds) { - if (l ~ combo) { - rfc2119undefined[combo] - if (option_verbose > 1 && option_pass1) { - printf("%s(%d): Undefined keyword combination: '%s'.\n", FILENAME, FNR, combo) - } - } - } - } - - # ID-Checklist section 3.6: Example domain names - if ( has_intro && !has_refs && (match($0, /[ \t]([A-Z0-9_-]+\.)+[A-Z0-9_-]+\.[A-Z]+/) \ - || match($0, /[ \t]([a-z0-9_-]+\.)+[a-z0-9_-]+\.[a-z]+/) ) ) { - FQDN = substr($0, RSTART+1, RLENGTH-1) - FQDN1 = substr($0, RSTART+1, RLENGTH) - addrstart = RSTART - fqdn = tolower(FQDN) - fqdn1= tolower(FQDN1) - - if ( fqdn !~ /([a-z0-9_-]+\.)+example(.(com|org|net))?$/ \ - && fqdn !~ /([a-z0-9_-]+\.)+(urn|uri|in-addr)\.arpa?$/ \ - && fqdn !~ /www.ietf.org/ \ - && fqdn !~ /[0-9]+\.[0-9]+\./ \ - && fqdn !~ /.\..\../ \ - && fqdn1!~ /.*@$/ ) { - if (option_verbose && option_pass1) { - printf("%s(%d): Found possible FQDN '%s' in position %d; this doesn't match " \ - "RFC 2606's suggested \".example\" or \".example.(com|org|net)\".\n", \ - FILENAME, FNR, FQDN, addrstart) - if (option_verbose > 1 && option_pass1) { - printf(" --> %s\n", $0); - printf(" %*s\n", addrstart, "^"); - } - } - badfqdns++; - } - } - # ID-Checklist section 3.6 A: Example numeric IPv4 addresses - if ( has_intro && !in_refs && match($0, /[ \t][0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)+/)) { - IPv4addr = substr($0, RSTART+1, RLENGTH-1); - - if (IPv4addr ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { - addrstart = RSTART+1; - split(IPv4addr, part); - for (i=1; i <= 4; i++) if (part[i]+0 > bigpart) bigpart = part[i]+0; - - if (IPv4addr ~ /^192\.0\.2\.[0-9]+$/) { - ipv4_example_addr++; - } - - - if (IPv4addr !~ /^192\.0\.2\.[0-9]+$/ \ - && IPv4addr !~ /198\.51\.100\.[0-9]+$/ \ - && IPv4addr !~ /203\.0\.113\.[0-9]+$/ \ - && IPv4addr !~ /233\.252\.0\.[0-9]+$/ \ - && IPv4addr !~ /^0\.0\.0\.0$/ \ - && IPv4addr !~ /^255\.255\.255\.255$/ \ - && !(IPv4addr in sections) \ - && bigpart < 256 \ - && !match($0, "([Ss]ections?|[Cc]lause)[ \t]" IPv4addr)) { - if (option_verbose && option_pass1) { - printf("%s(%d): Found possible IPv4 address '%s' in position %d; this doesn't match " \ - "the suggested documentation address ranges specified in RFC 6890 (or successor): " \ - "blocks 192.0.2.0/24 (TEST-NET-1), 198.51.100.0/24 " \ - "(TEST-NET-2), and 203.0.113.0/24 (TEST-NET-3); " \ - "or the 233.252.0.0/24 (MCAST-TEST-NET) example multicast " \ - "address range specified in RFC 5771.\n", \ - FILENAME, FNR, IPv4addr, addrstart) - if (option_verbose > 1 && option_pass1) { - printf(" --> %s\n", $0); - printf(" %*s\n", addrstart, "^"); - } - } - if (IPv4addr ~ /^192\.168\.[0-9]+\.[0-9]+$/ \ - || IPv4addr ~ /^10\.[0-9]\.[0-9]+\.[0-9]+$/ \ - || IPv4addr ~ /^172\.(1[6-9]|2[0-9]|3[01])\.[0-9]+\.[0-9]+$/) { - privipv4addr++; - } else if (IPv4addr ~ /^2(2[4-9]|3[0-9])\.[0-9]+\.[0-9]+\.[0-9]+$/ \ - && IPv4addr !~ /233\.252\.0\.[0-9]+$/) { - mcastipv4addr++; - } else { - badipv4addr++; - } - } + if ((! abnf_mentioned || ! in_abnf) && ! in_imap && ! in_code) { + update_references($0, FNR) + } + if ((abnf_mentioned && in_abnf) && ($0 ~ (";.*" reference_format))) { + update_references($0, FNR) + } } - } - } - -function is_ipv6(addr) { - # We have to match either 8 parts separated by colons or fewer parts with one embedded '::' or fewer parts ending in '::': - if ( addr ~ /^[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+$/ \ - || addr ~ /([0-9A-Fa-f]+:)([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?:$/ \ - || addr ~ /([0-9A-Fa-f]+:)([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?(:[0-9A-Fa-f]+)(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?$/ ) { - return 1; - } else { - return 0; - } +/\[[0-9A-Z-]+- *$/ { + incomplete_ref_line = strip($0) + incomplete_ref_pos = FNR } -function check_para(para) { - # Checking various things that need to be checked after assembling a full paragraph; - # in particular, word combinations can't be reliably checked line-by-line as they - # may be split across a line break. - for (pattern in bad) { - xpat = "[^-A-Za-z0-9_]" pattern "[^-A-Za-z0-9_]" - if (para ~ xpat) { - found_bad_pat[FNR] = pattern - found_bad_para[FNR] = para +/^ *[0-9A-Z-]+\]/ { + if (incomplete_ref_pos + 1 == FNR) { + update_references(incomplete_ref_line strip($0), incomplete_ref_pos) } - } +} - if (match(para, /NOT RECOMMENDED/)) { has_not_recommended++; } +{ + text = strip($0) + if (text == "") { + if (para) { + check_para(para) + } + para = "" + } else if (para ~ /-$/) { + para = para text + } else { + para = para " " text + } +} - # ID-Checklist section 3.6 B: Example numeric IPv6 addresses - if ( has_intro && !in_refs && match(para, /[ \t\[][0-9A-Fa-f]+:[0-9A-Fa-f]+(:[0-9A-Fa-f]*)+(EUI64)?/)) { - if (para ~ /.+EUI64/) { - IPv6addr = substr(para, RSTART+1, RLENGTH-6) "0" +END { + report(option_filename) + if (errors || longlines || hyphens || spacing || nonascii || controlchars) { + print "" + } + if (errors < 256) { + exit errors } else { - IPv6addr = substr(para, RSTART+1, RLENGTH-1) + exit 255 } - addrstart = RSTART+1 +} + + +# ---------------------------------------------------------------------- +# announce() +# +function announce(str) +{ + ### print "" + print "" + print fold(" " str, " ", columns) + print " " substr("----------------------------------------------------------------------------", 1, columns - 2) + print "" +} - if (IPv6addr ~ /^2001:0?[Dd][Bb]8(:[0-9A-Fa-f]*)+$/) { - if (is_ipv6(IPv6addr)) { - ipv6_example_addr++; - } +function check_downref(tag, warnlist, rfcnum, draftname, code, status, doc) +{ + if (tag in ref_text) { + ref = ref_text[tag] } else { - if (is_ipv6(IPv6addr)) { - if (option_verbose && option_pass1) { - printf("%s(%d): Found possible IPv6 address '%s' in position %d in the paragraph; this doesn't match " \ - "RFC 3849's suggested 2001:DB8::/32 address range or RFC 4193's Unique Local Address range FC00::/7.\n", \ - FILENAME, FNR, IPv6addr, addrstart) - if (option_verbose > 1 && option_pass1) { - printf(" --> %s\n", para); - printf(" %*s\n", addrstart, "^"); - } - } - if (IPv6addr ~ /^[Ff][CcDd][0-9A-Fa-f]?[0-9A-Fa-f]?(:[0-9A-Fa-f]*)+$/) { - ulpv6addr++; - } else if (IPv6addr ~ /^[Ff][Ee][89ABab][0-9A-Fa-f](:[0-9A-Fa-f]*)+$/) { - lldipv6addr++; + ref = tag + } + gsub(/ +/, " ", ref) + if (option_verbose > 2) { + note("Reference text: " ref) + } + if (ref ~ /[, ([](draft-|I-D\.)/) { + draftname = get_draftname(ref) + draftrev = get_draftrev(ref) + doc = draftname + get_state(draftname, state) + if (state["downloaded"] != today) { + download_state = " (However, the state information for " draftname " is not up-to-date. The last update was " state["downloaded"] ")" + } + ## Refactoring needed. We probably need a check_reference() rather than check_downref(), + ## with the published and current-version checks below being done as part of the general + ## reference checking, rather than inside the downref check. + if ("rfcnum" in state) { + warnc(sprintf("Outdated reference: %s has been published as RFC %s", draftname, state["rfcnum"])) + } else if (draftrev && ("rev" in state) && (draftrev != state["rev"])) { + if (draftrev + 0 < state["rev"] + 0) { + warnc(sprintf("Outdated reference: A later version (-%s) exists of %s-%s", state["rev"], draftname, draftrev)) + } else { + comment(sprintf("Unexpected draft version: The latest known version of %s is -%s, but you're referring to -%s.%s", draftname, state["rev"], draftrev, download_state)) + } + } + } else if (ref ~ /(RFC|rfc|Request [Ff]or Comments)( \([^\)]*\)|-)? ?[0-9][0-9]+/) { + rfcnum = get_rfcnum(ref) + doc = "RFC" rfcnum + } + if (doc && doc in seen_ref && ! (seen_ref[doc] in miss_ref)) { + comment(sprintf("Duplicate reference: %s, mentioned in '%s', was also mentioned in '%s'.", doc, tag, seen_ref[doc])) + } + seen_ref[doc] = tag + if (rfcnum) { + code = substr(rfcstatus, rfcnum, 1) + } + if (draftname) { + code = get_draftcode(draftname, state) + } + if (rfcnum && code == "O") { + if (tag in ref_norm) { + referr("Obsolete normative reference", rfcnum, tag) + } else if (! (tag in ref_def)) { + referr("Obsolete undefined reference", rfcnum, tag) } else { - badipv6addr++; + refcomment("Obsolete informational reference (is this intentional?)", rfcnum, tag) + } + } else if (tag in ref_norm) { + if (rfcnum) { + if (code in warnlist) { + if (rfcnum in exception) { + referr(sprintf("Downref: Normative reference to an %s RFC", code2status[code]), rfcnum, tag, "\n(Excemption has been granted for downref to this document in the past, see https://trac.tools.ietf.org/group/iesg/trac/wiki/DownrefRegistry)") + } else { + referr(sprintf("Downref: Normative reference to an %s RFC", code2status[code]), rfcnum, tag) + } + } + } else if ("U" in warnlist) { + if (ref ~ /[, ([](draft-|I-D\.)/) { + if (code) { + if (code in warnlist) { + errc(sprintf("Downref: Normative reference to an %s draft: %s (ref. '%s')", code2status[code], draftname, tag)) + } + } else { + if (state["deststatus"] == "None") { + statmsg = " (No intended status found in state file of " draftname ")" + } else { + statmsg = "" + } + comment(sprintf("Possible downref: Normative reference to a draft: ref. '%s' %s", tag, statmsg)) + } + } else { + comment(sprintf("Possible downref: Non-RFC (?) normative reference: ref. '%s'", tag)) + } } + } else if (! (tag in ref_def)) { + # Comment out this -- the warning for a missing reference is enough for a first pass. + # if (rfcnum) { + # if (code in warnlist) { + # refcomment(sprintf("Possible downref: Undefined reference to an %s RFC", code2status[code]), rfcnum, tag); + # } + # } else if ("U" in warnlist) { + # if (ref ~ /[, ([](draft-|I-D\.)/) { + # if (code) { + # if (code in warnlist) { + # warnc(sprintf("Possible downref: Undefined reference to an %s draft: %s (ref. '%s')", code2status[code], draftname, tag)); + # } + # } else { + # warnc(sprintf("Possible downref: Undefined reference to a draft: ref. '%s'", tag)); + # if (state["deststatus"] == "None") { + # note("(No intended status found in state file of " draftname ")"); + # } + # } + # } else { + # comment(sprintf("Possible downref: Undefined Non-RFC (?) reference : ref. '%s'", tag)); + # } + # } + } +} - # TODO: Permit IPv6 addresses with embedded IPv4 example addresses. The prefixes which - # may have such are (from David Thaler 2010-08-20 19:45 +0000): +function check_line() +{ + got_input = 1 + gsub(/\r/, "", $0) + sub(/[\n\t ]+$/, "", $0) + thiscolumn = match($0, /[^ ]/) + if (thiscolumn && thiscolumn < indentation) { + indentation = thiscolumn + # 1.1.a Max column 72 + } + if (length($0) > 72 && ! skip_file) { + if (match($0, "[^\001-\177]")) { + printf "%s(%d): Line appears to be too long, but this could be caused by non-ascii characters in UTF-8 encoding\n", FILENAME, FNR + } else { + if (option_verbose && option_pass1) { + printf "%s(%d): Line is too long: the offending characters are '%s'\n", FILENAME, FNR, substr($0, 73) + } + longlines++ + if (length($0) - 72 > excesslength) { + excesslength = length($0) - 72 + } + } + } + # 1.1.b Ragged right + if (! skip_file && ! match($0, /^ *Internet.Draft/) && ! match($0, /^ *INTERNET.DRAFT/) && match($0, /[A-Za-z][a-z] ? ?[a-z]/)) { + if (option_verbose && option_pass1) { + printf "%s(%d): Line has weird spacing: '...%s...'\n", FILENAME, FNR, substr($0, RSTART - 5, 14) + } + spacing++ + sp_line[spacing] = $0 + linenum[spacing] = FNR + extract[spacing] = substr($0, RSTART - 5, 14) + } + # 1.1.c No hyphenation for line-breaks + if ($0 ~ /[A-Za-z0-9_]-$/ && ! skip_file && ! has_refs && has_hyphenlist) { + word = $0 + sub(/^.*[^A-Za-z0-9_-]/, "", word) + if (! word in hyphenfrags) { + if (option_verbose && option_pass1) { + printf "%s(%d): Line seems to end with a hyphenated word.\n", FILENAME, FNR + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + } + } + hyphens++ + } + } + # 1.1.e ASCII-only + # The test really should go from \200 to \377 - but the awk implementation + # on *BSD seems to have used \377 internally as a sentinel or something... + if (match($0, "[^\001-\177]") && ! skip_file) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found non-ascii character (%s) in position %d.\n", FILENAME, FNR, substr($0, RSTART, 1), RSTART + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + printf " %*s\n", RSTART, "^" + } + } + nonascii++ + } + # 1.1.e no control characer except CR NL FF + # nawk can't handle octal escapes inside character classes, it seems. Sigh. + # if (match($0, /[\001-\011\013\016-\037]/) && ! skip_file) ... + if (match($0, /(\001|\002|\003|\004|\005|\006|\007|\010|\011|\013|\016|\017|\020|\021|\022|\023|\024|\025|\026|\027|\030|\031|\032|\033|\034|\035|\036|\037)/) && ! skip_file) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found control character %s in position %d.\n", FILENAME, FNR, controlchar[substr($0, RSTART, 1)], RSTART + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + printf " %*s\n", RSTART, "^" + } + } + controlchars++ + } + # 1.1.f Do not number the Abstract section + if ($0 ~ /^[ \t]*Abstract[ \t]*$/) { + abstract_seen = 1 + } + if ($0 ~ /^[ \t]*[0-9][.0-9 \t]*Abstract[ \t]*$/ && (! abstract_seen) && ! skip_file && option_pass2) { + errg("The Abstract section seems to be numbered") + abstract_seen = 1 + } + # 1.1.f Do not number the "Status of Memo" section + if ($0 ~ /^[ \t]*Status of (This )?Memo[ \t]*$/) { + has_status_of_memo = 1 + } + if ($0 ~ /^[ \t]*[0-9][.0-9 \t]*Status of (This )?Memo[ \t]*$/ && (! has_status_of_memo) && ! skip_file && option_pass2) { + errg("The Status of Memo section seems to be numbered") + has_status_of_memo = 1 + } + # RFC 2119 language + if (! match($0, "IN NO EVENT SHALL") && ! match($0, "SHALL THE COPYRIGHT") && match($0, /[ \t](MUST|REQUIRED|SHALL|SHOULD|RECOMMENDED|MAY|OPTIONAL)([ \t\.,]|$)/)) { + keywords++ + rfc2119line[keywords] = FNR + rstart = RSTART - 16 + rlength = 38 + if (rstart + rlength > length($0)) { + rstart = length($0) - rlength + 1 + } + if (rstart < 1) { + rstart = 1 + } + if (! (FNR in line)) { + line[FNR] = substr($0, rstart, rlength) + } + if (option_verbose > 1 && option_pass1) { + printf "%s(%d): RFC 2119 keyword: %s.\n", FILENAME, FNR, $0 + } + # Keywords: # - # The list of relevant IPv4-embedded IPv6 address formats I'm currently aware of is: + # MUST MUST NOT + # SHALL SHALL NOT + # SHOULD SHOULD NOT + # RECOMMENDED NOT RECOMMENDED + # REQUIRED + # MAY + # OPTIONAL + + # Find uppercase words before or after our keywords, and check if the combination is defined + l = $0 + sub(/\t/, " ", l) + notkwds["MAY NOT"] + notkwds["NOT REQUIRED"] + notkwds["NOT OPTIONAL"] + for (combo in notkwds) { + if (l ~ combo) { + rfc2119undefined[combo] + if (option_verbose > 1 && option_pass1) { + printf "%s(%d): Undefined keyword combination: '%s'.\n", FILENAME, FNR, combo + } + } + } + } + # ID-Checklist section 3.6: Example domain names + if (has_intro && ! has_refs && (match($0, /[ \t]([A-Z0-9_-]+\.)+[A-Z0-9_-]+\.[A-Z]+/) || match($0, /[ \t]([a-z0-9_-]+\.)+[a-z0-9_-]+\.[a-z]+/))) { + FQDN = substr($0, RSTART + 1, RLENGTH - 1) + FQDN1 = substr($0, RSTART + 1, RLENGTH) + addrstart = RSTART + fqdn = tolower(FQDN) + fqdn1 = tolower(FQDN1) + if (fqdn !~ /([a-z0-9_-]+\.)+example(.(com|org|net))?$/ && fqdn !~ /([a-z0-9_-]+\.)+(urn|uri|in-addr)\.arpa?$/ && fqdn !~ /www.ietf.org/ && fqdn !~ /[0-9]+\.[0-9]+\./ && fqdn !~ /.\..\../ && fqdn1 !~ /.*@$/) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found possible FQDN '%s' in position %d; this doesn't match " "RFC 2606's suggested \".example\" or \".example.(com|org|net)\".\n", FILENAME, FNR, FQDN, addrstart + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + printf " %*s\n", addrstart, "^" + } + } + badfqdns++ + } + } + # ID-Checklist section 3.6 A: Example numeric IPv4 addresses + if (has_intro && ! in_refs && match($0, /[ \t][0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)+/)) { + IPv4addr = substr($0, RSTART + 1, RLENGTH - 1) + if (IPv4addr ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { + addrstart = RSTART + 1 + split(IPv4addr, part, FS) + for (i = 1; i <= 4; i++) { + if (part[i] + 0 > bigpart) { + bigpart = part[i] + 0 + } + } + if (IPv4addr ~ /^192\.0\.2\.[0-9]+$/) { + ipv4_example_addr++ + } + if (IPv4addr !~ /^192\.0\.2\.[0-9]+$/ && IPv4addr !~ /198\.51\.100\.[0-9]+$/ && IPv4addr !~ /203\.0\.113\.[0-9]+$/ && IPv4addr !~ /233\.252\.0\.[0-9]+$/ && IPv4addr !~ /^0\.0\.0\.0$/ && IPv4addr !~ /^255\.255\.255\.255$/ && ! (IPv4addr in sections) && bigpart < 256 && ! match($0, "([Ss]ections?|[Cc]lause)[ \t]" IPv4addr)) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found possible IPv4 address '%s' in position %d; this doesn't match " "the suggested documentation address ranges specified in RFC 6890 (or successor): " "blocks 192.0.2.0/24 (TEST-NET-1), 198.51.100.0/24 " "(TEST-NET-2), and 203.0.113.0/24 (TEST-NET-3); " "or the 233.252.0.0/24 (MCAST-TEST-NET) example multicast " "address range specified in RFC 5771.\n", FILENAME, FNR, IPv4addr, addrstart + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + printf " %*s\n", addrstart, "^" + } + } + if (IPv4addr ~ /^192\.168\.[0-9]+\.[0-9]+$/ || IPv4addr ~ /^10\.[0-9]\.[0-9]+\.[0-9]+$/ || IPv4addr ~ /^172\.(1[6-9]|2[0-9]|3[01])\.[0-9]+\.[0-9]+$/) { + privipv4addr++ + } else if (IPv4addr ~ /^2(2[4-9]|3[0-9])\.[0-9]+\.[0-9]+\.[0-9]+$/ && IPv4addr !~ /233\.252\.0\.[0-9]+$/) { + mcastipv4addr++ + } else { + badipv4addr++ + } + } + } + } +} + +function check_para(para) +{ + # Checking various things that need to be checked after assembling a full paragraph; + # in particular, word combinations can't be reliably checked line-by-line as they + # may be split across a line break. + for (pattern in bad) { + xpat = "[^-A-Za-z0-9_]" pattern "[^-A-Za-z0-9_]" + if (para ~ xpat) { + found_bad_pat[FNR] = pattern + found_bad_para[FNR] = para + } + } + if (match(para, /NOT RECOMMENDED/)) { + has_not_recommended++ + } + # ID-Checklist section 3.6 B: Example numeric IPv6 addresses + if (has_intro && ! in_refs && match(para, /[ \t\[][0-9A-Fa-f]+:[0-9A-Fa-f]+(:[0-9A-Fa-f]*)+(EUI64)?/)) { + if (para ~ /.+EUI64/) { + IPv6addr = substr(para, RSTART + 1, RLENGTH - 6) "0" + } else { + IPv6addr = substr(para, RSTART + 1, RLENGTH - 1) + } + addrstart = RSTART + 1 + if (IPv6addr ~ /^2001:0?[Dd][Bb]8(:[0-9A-Fa-f]*)+$/) { + if (is_ipv6(IPv6addr)) { + ipv6_example_addr++ + } + } else if (is_ipv6(IPv6addr)) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found possible IPv6 address '%s' in position %d in the paragraph; this doesn't match " "RFC 3849's suggested 2001:DB8::/32 address range or RFC 4193's Unique Local Address range FC00::/7.\n", FILENAME, FNR, IPv6addr, addrstart + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", para + printf " %*s\n", addrstart, "^" + } + } + if (IPv6addr ~ /^[Ff][CcDd][0-9A-Fa-f]?[0-9A-Fa-f]?(:[0-9A-Fa-f]*)+$/) { + ulpv6addr++ + } else if (IPv6addr ~ /^[Ff][Ee][89ABab][0-9A-Fa-f](:[0-9A-Fa-f]*)+$/) { + lldipv6addr++ + } else { + badipv6addr++ + } + # TODO: Permit IPv6 addresses with embedded IPv4 example addresses. The prefixes which + # may have such are (from David Thaler 2010-08-20 19:45 +0000): + # + # The list of relevant IPv4-embedded IPv6 address formats I'm currently aware of is: + # + # 6to4 (RFC 3056 section 2): + # 2002:<4 bytes of IPv4 address>::/48 + # + # Teredo (RFC 4380 section 4): + # 2001:0:<4 bytes of IPv4 address>::/64 + # + # IPv6/IPv4 Translation Address (https://tools.ietf.org/html/draft-ietf-behave-address-format-10#section-2.2 table 2): + # 64:ff9b::<4 bytes of IPv4 address> + # + # IPv4-Compatible IPv6 Address (RFC 4291 section 2.5.5.1): + # ::<4 bytes of IPv4 address> + # + # IPv4-Mapped IPv6 Address (RFC 4291 section 2.5.5.2): + # ::FFFF:<4 bytes of IPv4 address> + # + # IPv4-Translatable (aka IPv4-Translated) IPv6 Address (RFC 2765 section 2.1): + # ::FFFF:0:<4 bytes of IPv4 address> + # + # And two other relevant cases of *multicast* address spaces with well-known prefixes + # and embedded IPv4 or IPv6 *unicast* address prefixes: + # + # Unicast-Prefix-Based IPv6 Multicast Address (RFC 3306 section 4): + # FF3x:::: + # So since 2001:DB8::/32 is a doc prefix, then + # FF3x:20:2001:DB8::/64 would be a multicast range for documentation. + # And by changing the "20" hex to anything larger is also ok of course. + # + # Embedded RP (RFC 3956) section 3 modifies the above to also allow FF7x... in addition to FF3x... + # + # Unicast-Prefix-Based IPv4 Multicast Address (https://tools.ietf.org/html/draft-ietf-mboned-ipv4-uni-based-mcast-06 section 3, in RFC editors queue): + # . + # Where it's still waiting for IANA to assign the TBD byte out of the multicast range (so stay tuned). + # So the multicast addresss + # TBD.192.0.2 + # TBD.198.51.100 + # TBD.203.0.113 + # would automatically be for documentation purposes once TBD is assigned. + } + # TODO: Warn for violations of RFC 5952: # - # 6to4 (RFC 3056 section 2): - # 2002:<4 bytes of IPv4 address>::/48 + # RFC 5952 IPv6 Text Representation August 2010 # - # Teredo (RFC 4380 section 4): - # 2001:0:<4 bytes of IPv4 address>::/64 + # 4. A Recommendation for IPv6 Text Representation # - # IPv6/IPv4 Translation Address (https://tools.ietf.org/html/draft-ietf-behave-address-format-10#section-2.2 table 2): - # 64:ff9b::<4 bytes of IPv4 address> + # A recommendation for a canonical text representation format of IPv6 + # addresses is presented in this section. The recommendation in this + # document is one that complies fully with [RFC4291], is implemented by + # various operating systems, and is human friendly. The recommendation + # in this section SHOULD be followed by systems when generating an + # address to be represented as text, but all implementations MUST + # accept and be able to handle any legitimate [RFC4291] format. It is + # advised that humans also follow these recommendations when spelling + # an address. # - # IPv4-Compatible IPv6 Address (RFC 4291 section 2.5.5.1): - # ::<4 bytes of IPv4 address> + # 4.1. Handling Leading Zeros in a 16-Bit Field # - # IPv4-Mapped IPv6 Address (RFC 4291 section 2.5.5.2): - # ::FFFF:<4 bytes of IPv4 address> + # Leading zeros MUST be suppressed. For example, 2001:0db8::0001 is + # not acceptable and must be represented as 2001:db8::1. A single 16- + # bit 0000 field MUST be represented as 0. # - # IPv4-Translatable (aka IPv4-Translated) IPv6 Address (RFC 2765 section 2.1): - # ::FFFF:0:<4 bytes of IPv4 address> + # 4.2. "::" Usage # - # And two other relevant cases of *multicast* address spaces with well-known prefixes - # and embedded IPv4 or IPv6 *unicast* address prefixes: + # 4.2.1. Shorten as Much as Possible # - # Unicast-Prefix-Based IPv6 Multicast Address (RFC 3306 section 4): - # FF3x:::: - # So since 2001:DB8::/32 is a doc prefix, then - # FF3x:20:2001:DB8::/64 would be a multicast range for documentation. - # And by changing the "20" hex to anything larger is also ok of course. + # The use of the symbol "::" MUST be used to its maximum capability. + # For example, 2001:db8:0:0:0:0:2:1 must be shortened to 2001:db8::2:1. + # Likewise, 2001:db8::0:1 is not acceptable, because the symbol "::" + # could have been used to produce a shorter representation 2001:db8::1. # - # Embedded RP (RFC 3956) section 3 modifies the above to also allow FF7x... in addition to FF3x... + # 4.2.2. Handling One 16-Bit 0 Field # - # Unicast-Prefix-Based IPv4 Multicast Address (https://tools.ietf.org/html/draft-ietf-mboned-ipv4-uni-based-mcast-06 section 3, in RFC editors queue): - # . - # Where it's still waiting for IANA to assign the TBD byte out of the multicast range (so stay tuned). - # So the multicast addresss - # TBD.192.0.2 - # TBD.198.51.100 - # TBD.203.0.113 - # would automatically be for documentation purposes once TBD is assigned. - } - } - - # TODO: Warn for violations of RFC 5952: - # - # RFC 5952 IPv6 Text Representation August 2010 - # - # 4. A Recommendation for IPv6 Text Representation - # - # A recommendation for a canonical text representation format of IPv6 - # addresses is presented in this section. The recommendation in this - # document is one that complies fully with [RFC4291], is implemented by - # various operating systems, and is human friendly. The recommendation - # in this section SHOULD be followed by systems when generating an - # address to be represented as text, but all implementations MUST - # accept and be able to handle any legitimate [RFC4291] format. It is - # advised that humans also follow these recommendations when spelling - # an address. - # - # 4.1. Handling Leading Zeros in a 16-Bit Field - # - # Leading zeros MUST be suppressed. For example, 2001:0db8::0001 is - # not acceptable and must be represented as 2001:db8::1. A single 16- - # bit 0000 field MUST be represented as 0. - # - # 4.2. "::" Usage - # - # 4.2.1. Shorten as Much as Possible - # - # The use of the symbol "::" MUST be used to its maximum capability. - # For example, 2001:db8:0:0:0:0:2:1 must be shortened to 2001:db8::2:1. - # Likewise, 2001:db8::0:1 is not acceptable, because the symbol "::" - # could have been used to produce a shorter representation 2001:db8::1. - # - # 4.2.2. Handling One 16-Bit 0 Field - # - # The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field. - # For example, the representation 2001:db8:0:1:1:1:1:1 is correct, but - # 2001:db8::1:1:1:1:1 is not correct. - # - # 4.2.3. Choice in Placement of "::" - # - # When there is an alternative choice in the placement of a "::", the - # longest run of consecutive 16-bit 0 fields MUST be shortened (i.e., - # the sequence with three consecutive zero fields is shortened in 2001: - # 0:0:1:0:0:0:1). When the length of the consecutive 16-bit 0 fields - # are equal (i.e., 2001:db8:0:0:1:0:0:1), the first sequence of zero - # bits MUST be shortened. For example, 2001:db8::1:0:0:1 is correct - # representation. - # - # 4.3. Lowercase - # - # The characters "a", "b", "c", "d", "e", and "f" in an IPv6 address - # MUST be represented in lowercase. - } - - if (in_abstract && para !~ /^[ \t]*Abstract[ \t]*$/ ) { - lcpara = tolower(para) - - if (match(lcpara, /obsoletes ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { - findall(lcpara, "obsoletes ((\\[?rfcs? ?)?[0-9]+\\]?(, )?)+", lst) - for (i in lst) { - txt = lst[i] - findall(txt, "(rfc ?)?[0-9]+", rfcs) - for (j in rfcs) { - r = rfcs[j] - if (! (r ~ /rfc/)) r = "rfc" r - sub(/ /, "", r); sub(/rfc/, "RFC", r) - abstract_obsoletes = abstract_obsoletes " " r - } - } - } - - # Accept 'replaces' as a synonym of 'obsoletes' in the abstract text - if (match(lcpara, /replaces ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { - findall(lcpara, "replaces ((\\[?rfcs? ?)?[0-9]+\\]?(, )?)+", lst) - for (i in lst) { - txt = lst[i] - findall(txt, "(rfc ?)?[0-9]+", rfcs) - for (j in rfcs) { - r = rfcs[j] - if (! (r ~ /rfc/)) r = "rfc" r - sub(/ /, "", r); sub(/rfc/, "RFC", r) - abstract_obsoletes = abstract_obsoletes " " r - } - } - } - - if (match(lcpara, /updates ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { - findall(lcpara, "updates ((\\[?rfcs? ?)?[0-9]+\\]?(, | and )?)+", lst) - for (i in lst) { - txt = lst[i] - findall(txt, "(rfc ?)?[0-9]+", rfcs) - for (j in rfcs) { - r = rfcs[j] - if (! (r ~ /rfc/)) r = "rfc" r - sub(/ /, "", r); sub(/rfc/, "RFC", r) - abstract_updates = abstract_updates " " r - } - } - } - - if (match(lcpara, /rfc ?[0-9]+/)) { - findall(lcpara, "rfc ?[0-9]+", rfcs) - for (j in rfcs) { - r = rfcs[j] - sub(/ /, "", r); sub(/rfc/, "RFC", r) - abstract_mentions = abstract_mentions " " r - } - } - - if (match(para, reference_format)) { - findall(para, reference_format, refs) - for (j in refs) { - r = refs[j] - sub(/ /, "", r); sub(/rfc/, "RFC", r) - if ( tolower(r) !~ /\[page ?[0-9]+\]/) { - abstract_references = abstract_references " " r; - } - } - } - } + # The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field. + # For example, the representation 2001:db8:0:1:1:1:1:1 is correct, but + # 2001:db8::1:1:1:1:1 is not correct. + # + # 4.2.3. Choice in Placement of "::" + # + # When there is an alternative choice in the placement of a "::", the + # longest run of consecutive 16-bit 0 fields MUST be shortened (i.e., + # the sequence with three consecutive zero fields is shortened in 2001: + # 0:0:1:0:0:0:1). When the length of the consecutive 16-bit 0 fields + # are equal (i.e., 2001:db8:0:0:1:0:0:1), the first sequence of zero + # bits MUST be shortened. For example, 2001:db8::1:0:0:1 is correct + # representation. + # + # 4.3. Lowercase + # + # The characters "a", "b", "c", "d", "e", and "f" in an IPv6 address + # MUST be represented in lowercase. + } + if (in_abstract && para !~ /^[ \t]*Abstract[ \t]*$/) { + lcpara = tolower(para) + if (match(lcpara, /obsoletes ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { + findall(lcpara, "obsoletes ((\\[?rfcs? ?)?[0-9]+\\]?(, )?)+", lst) + for (i in lst) { + txt = lst[i] + findall(txt, "(rfc ?)?[0-9]+", rfcs) + for (j in rfcs) { + r = rfcs[j] + if (! (r ~ /rfc/)) { + r = "rfc" r + } + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + abstract_obsoletes = abstract_obsoletes " " r + } + } + } + # Accept 'replaces' as a synonym of 'obsoletes' in the abstract text + if (match(lcpara, /replaces ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { + findall(lcpara, "replaces ((\\[?rfcs? ?)?[0-9]+\\]?(, )?)+", lst) + for (i in lst) { + txt = lst[i] + findall(txt, "(rfc ?)?[0-9]+", rfcs) + for (j in rfcs) { + r = rfcs[j] + if (! (r ~ /rfc/)) { + r = "rfc" r + } + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + abstract_obsoletes = abstract_obsoletes " " r + } + } + } + if (match(lcpara, /updates ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { + findall(lcpara, "updates ((\\[?rfcs? ?)?[0-9]+\\]?(, | and )?)+", lst) + for (i in lst) { + txt = lst[i] + findall(txt, "(rfc ?)?[0-9]+", rfcs) + for (j in rfcs) { + r = rfcs[j] + if (! (r ~ /rfc/)) { + r = "rfc" r + } + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + abstract_updates = abstract_updates " " r + } + } + } + if (match(lcpara, /rfc ?[0-9]+/)) { + findall(lcpara, "rfc ?[0-9]+", rfcs) + for (j in rfcs) { + r = rfcs[j] + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + abstract_mentions = abstract_mentions " " r + } + } + if (match(para, reference_format)) { + findall(para, reference_format, refs) + for (j in refs) { + r = refs[j] + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + if (tolower(r) !~ /\[page ?[0-9]+\]/) { + abstract_references = abstract_references " " r + } + } + } + } } - # ---------------------------------------------------------------------- -# Pattern / actions: +# checkmultibp(name) # - -/^This Internet-Draft(, draft-.*)? has been deleted./ { - if (option_pass2) printf " Skipping this file; it looks like a tombstone file to me.\n"; - skip_file = 1; -} - -/^This +document has been replaced by/ { - if (option_pass2) printf " Skipping this file; it looks like a tombstone file to me.\n"; - skip_file = 1; +function checkmultibp(name) +{ + if (has[name] && almost_boilerplate[name]) { + warn(sprintf("In addition to %s boilerplate, a section with a similar start was also found:\n", expandname(name))) + showalmost(name) + } } -/^This Internet-Draft(, draft-.*)? was published as/ { - if (option_pass2) printf " Skipping this file; it looks like a tombstone file to me.\n"; - skip_file = 1; +# ---------------------------------------------------------------------- +# comment() +# +function comment(str, indented) +{ + if (option_warn) { + print fold(" " infomark " " str, " ", columns) + if (indented) { + print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) + print fold(" '" indented "' )", " ", columns) + } + print "" + comments++ + } } -/^A new Request for Comments is now available/ { - if (option_pass2) printf " Skipping this file; it looks like a tombstone file to me.\n"; - skip_file = 1; +# ---------------------------------------------------------------------- +# err() +# +function err(str, indented) +{ + print fold(" " errmark " " str, " ", columns) + if (indented) { + print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) + print fold(" '" indented "' )", " ", columns) + } + print "" + errors++ } -/^RFC [0-9]+ was never issued./ { - if (option_pass2) printf " Skipping this file; it looks like a tombstone file to me.\n"; - skip_file = 1; +# ---------------------------------------------------------------------- +# errc() +# +# Errors which are IESG checklist errors, but not submission errors +function errc(str, indented) +{ + if (! option_submitcheck) { + if (option_checklistwarn) { + warn(str, indented) + } else { + err(str, indented) + } + } } -/.*/ { check_line() } - -# Pagecount -/-\+- Pagecount: [0-9]+ -\+-/ { pagecount = $3+0; next } -/-\+- Firstpagelength: [0-9]+ -\+-/ { firstpagelength = $3+0; next } -/-\+- Maxpagelength: [0-9]+ -\+-/ { maxpagelength = $3+0; next } -/-\+- Longestpage: [0-9]+ -\+-/ { longestpage = $3+0; next } -/-\+- Longpagecount: [0-9]+ -\+-/ { longpagecount = $3+0; next } -/-\+- Formfeedcount: [0-9]+ -\+-/ { formfeedcount = $3+0; next } -/-\+- Expiration: [0-9]+ -\+-/ { has_expiration = $3+0; next } -/-\+- NoNroffPostproc: [0-9]+ -\+-/ { missing_nroff_postprocessing = $3+0; next } +# ---------------------------------------------------------------------- +# errg() +# +function errg(str, indented) +{ + if (option_guidelinewarn) { + warn(str, indented) + } else { + err(str, indented) + } +} +# ---------------------------------------------------------------------- +# errw() +# +# Errors which are only warnings in submission mode +function errw(str, indented) +{ + if (option_submitcheck) { + warn(str, indented) + } else { + err(str, indented) + } +} -# If the draft begins with 'PK' it some software will think it's a zip file. Mention this. -/^PK/ && FNR==1 { has_pk_mark = 1; } -/^BM/ && FNR==1 { has_bm_mark = 1; } +# ---------------------------------------------------------------------- +# expandname(name) +# +function expandname(name) +{ + sub(/_u/, ", updated by RFC ", name) + sub(/_p/, ", paragraph ", name) + sub(/_e/, " embedded", name) + if (name ~ /^rfc/ || name ~ /^trust-/) { + sub("_", ", Section ", name) + split("x ix viii vii vi v iv iii ii i", roman, FS) + for (i in roman) { + r = roman[i] + sub("_" r, "(" r ")", name) + } + gsub("_", ".", name) + sub("rfc", "RFC ", name) + sub("trust-", "IETF Trust Legal Provisions of ", name) + } + return name +} -# Check for required sections -# Nawk doesn't understand IGNORECASE = 0, so we have to explicitly convert. -# Also normalise the indentation -/\. ?\. ?\. ?\. ?\. *[0-9]+$/ { if (!has_intro) { has_toc = 1; in_toc = 1; }; next; } - { - normalized = tolower($0); - if (indentation) normalized = substr(normalized, indentation); - #if (option_verbose > 2 && option_pass1) printf " normalized: '%s'\n", normalized; - } -/::= +BEGIN *$/ { in_mib = 1 } -/^ +END *$/ { in_mib = 0 } - -normalized ~ /^internet[ -]draft/ { if (FNR < 15) has_id_indication = 1; else has_late_id_indication = 1; } - -normalized ~ /^expires:?.*20[0-9][0-9]/ { has_expiration = FNR; } - -normalized ~ /[12][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/ { - match($0, /[12][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/) - datestr = substr($0, RSTART, RLENGTH) - if ((FNR < 30) && ($0 !~ "(Expires|Expiration [Dd]ate): *" datestr)) { - split(datestr, part, /-/) - - m = part[2] - d = part[3] - y = part[1] - isodate = sprintf("%s-%s-%s", y, m, d) - new_date = jdn(isodate) - if (new_date > doc_date) { - doc_date = new_date - date_lit = datestr - iso_date = isodate - date_skew = 3 - } - } - } -normalized ~ /[adfjmnos][a-z]+ [0-9]+, [12][0-9][0-9][0-9]$/ { - match($0, /[ADFJMNOS][a-z]+ [0-9]+, [12][0-9][0-9][0-9]$/) - datestr = substr($0, RSTART, RLENGTH) - if ((FNR < 30) && ($0 !~ "(Expires|Expiration [Dd]ate): *" datestr)) { - split(datestr, part, /[ ,]+/) - - m = month[part[1]] - d = part[2] - y = part[3] - isodate = sprintf("%s-%s-%s", y, m, d) - new_date = jdn(isodate) - if (new_date > doc_date) { - doc_date = new_date - date_lit = datestr - iso_date = isodate - date_skew = 3 - } - } - } -normalized ~ /([0-9]+ )?[adfjmnos][a-z]+ [12][0-9][0-9][0-9]$/ { - is_docdate = 0 - if (match($0, /[0-9]+ [ADFJMNOS][a-z]+ [12][0-9][0-9][0-9]$/)) { - datestr = substr($0, RSTART, RLENGTH) - if ((FNR < 30) && ($0 !~ "(Expires|Expiration [Dd]ate): *" datestr)) { - is_docdate = 1 - split(datestr, part, /[ ,]+/) - - m = month[part[2]] - d = part[1] - y = part[3] - date_skew = 3 - } - } else { - match($0, /[ADFJMNOS][a-z]+ [12][0-9][0-9][0-9]$/) - datestr = substr($0, RSTART, RLENGTH) - if ((FNR < 30) && ($0 !~ "(Expires|Expiration [Dd]ate): *" datestr)) { - is_docdate = 1 - split(datestr, part, /[ ,]+/) - - m = month[part[1]] - d = 15 - y = part[2] - date_skew = 16 - } - } - if (is_docdate) { - isodate = sprintf("%s-%s-%s", y, m, d) - new_date = jdn(isodate) - if (new_date > doc_date) { - doc_date = new_date - date_lit = datestr - iso_date = isodate - } - } - } -normalized ~ /^([0123.]+ +)?table of contents:?( *\(.+\))?$/ { has_toc = 1; in_toc = 1; } - -normalized ~ /^[ \t]*contents$/ { if (!has_intro) { has_toc = 1; in_toc = 1; } } - -normalized ~ /^([0123.]+ )? ? ? ? ? ?introduction[ \t]*.*/ { has_intro = 1; } -normalized ~ /^ +([0123.]+ )? ? ? ? ? ?introduction[ \t]*.*/ { indented_intro = $0; } - -normalized ~ /^([0123.]+ )? ? ? ? ? ?overview[ \t]*.*/ { has_intro = 1; } -normalized ~ /^ +([0123.]+ )? ? ? ? ? ?overview[ \t]*.*/ { indented_intro = $0; } - -normalized ~ /^([0123.]+ )? ? ? ? ? ?rationale[ \t]*.*/ { has_intro = 1; } -normalized ~ /^ +([0123.]+ )? ? ? ? ? ?rationale[ \t]*.*/ { indented_intro = $0; } - -normalized ~ /^([0123.]+ )? ? ? ? ? ?scope[ \t]*.*/ { has_intro = 1; } -normalized ~ /^ +([0123.]+ )? ? ? ? ? ?scope[ \t]*.*/ { indented_intro = $0; } - -normalized ~ /^([0123.]+ )? ? ? ? ? ?(historical )?background[ \t]*.*/{ has_intro = 1; } -normalized ~ /^ +([0123.]+ )? ? ? ? ? ?(historical )?background[ \t]*.*/{ indented_intro = $0; } - -normalized ~ /^([0-9.]+ )? ? ? ? ? ?security considerations?[ \t]*.*/ { has_security = 1; } -normalized ~ /^ +([0-9.]+ )? ? ? ? ? ?security considerations?[ \t]*.*/ { indented_security = $0; } - -normalized ~ /^([0-9.]+ )? ? ? ? ? ?security$/ { has_security = 1; } -normalized ~ /^ +([0-9.]+ )? ? ? ? ? ?security$/ { indented_security = $0; } - -normalized ~ /^(appendix )?([0-9a-z.]+ )? ? ? ? ? ?iana considerations?[ \t]*.*/ { has_iana = 1; } -normalized ~ /^ +([0-9a-z.]+ )? ? ? ? ? ?iana considerations?[ \t]*.*/{ indented_iana = $0; } - - # New section. If we were in a reference section, we've now left it. -normalized ~ /^[0-9.]+ +/ { in_refs = 0; in_abnf = 0; in_imap = 0; in_abstract = 0; in_code=0; sections[$1] = substr($0, length($1)); } -normalized ~ /^status of (this )?memo/ { in_refs = 0; in_abnf = 0; in_imap = 0; in_abstract = 0; in_code=0; } -normalized ~ /^conventions used / { in_refs = 0; in_abnf = 0; in_imap = 0; in_abstract = 0; in_code=0; } -normalized ~ /^requirements language/ { in_refs = 0; in_abnf = 0; in_imap = 0; in_abstract = 0; in_code=0; } -normalized ~ /^table of contents/ { in_refs = 0; in_abnf = 0; in_imap = 0; in_abstract = 0; in_code=0; } - -normalized ~ /^([0123.]+ )? *abstract$/ { has_abstract = 1; in_abstract = 1; } -normalized ~ /^ +([0123.]+ )? *abstract$/ { indented_abstract = $0; in_abstract = 1; } - -normalized ~ /^appendix/ { if (has_refs) has_appendix = 1; in_refs = 0; nnnote("Appendix start: " $0); } -normalized ~ /^ +appendix/ { if (has_refs) indented_appendix = $0; } - -normalized ~ /(^| )abnf([ .]|$)/ { abnf_mentioned = 1; } -normalized ~ abnf_rule_format { in_abnf++; } -$0 ~ imap_rule_format { in_imap++; } # The imap rule format has some parts specifically in uppercase -- can't use 'normalized' -normalized ~ /^ *$/ { in_abnf = 0; in_imap = 0; } -$0 ~ code_start_format { in_code = 1; nnote("Code start at " FNR ": " $0); } -$0 ~ code_end_format { in_code = 0; nnote("Code end at " FNR ": " $0); } -$0 ~ inline_code_format { if (! in_code) { code_comment_found = 1; nnote("Possible code comment in line: " $0); }} - - -normalized ~ /^([0-9]+[.]?0? )? ? ? ? ? ?references$/ { if (has_intro || has_security || has_iana) { has_refs = 1; in_refs = 1; in_normref = 1; }} -normalized ~ /^ +([0-9]+[.]?0? )? ? ? ? ? ?references$/ { if (has_intro || has_security || has_iana) { indented_refs = $0; }} -normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?normative references?$/ { if (has_intro || has_security || has_iana) { has_splitrefs = 1; has_refs = 1; in_refs = 1; in_normref = 1; }} -normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informative references?$/ { if (has_intro || has_security || has_iana) { has_splitrefs = 1; has_refs = 1; in_refs = 1; in_normref = 0; }} -normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informational references?$/ { if (has_intro || has_security || has_iana) { has_splitrefs = 1; has_refs = 1; in_refs = 1; in_normref = 0; }} -normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?non-normative references?$/ { if (has_intro || has_security || has_iana) { has_splitrefs = 1; has_refs = 1; in_refs = 1; in_normref = 0; }} -normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?references[^a-z]+normative\)?$/ { if (has_intro || has_security || has_iana) { has_splitrefs = 1; in_refs = 1; in_normref = 1; }} -normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?references[^a-z]+informative\)?$/ { if (has_intro || has_security || has_iana) { has_splitrefs = 1; in_refs = 1; in_normref = 0; }} -normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?normative$/ { if (has_refs) { has_splitrefs = 1; in_refs = 1; in_normref = 1; }} -normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informative$/ { if (has_refs) { has_splitrefs = 1; in_refs = 1; in_normref = 0; }} - -normalized ~ /^[0-9a-z.]* *((author|editor)(\047s|s\047) +(and +)?)+address(es)?/{ has_addr = 1; } -normalized ~ /^[0-9a-z.]* *author information$/ { has_addr = 1; } -normalized ~ /^[0-9a-z.]* *(author|editor)(\047s|s\047) contact information$/ { has_addr = 1; } -normalized ~ /^[0-9A-Z.]* *contact information$/ { has_addr = 1; } -normalized ~ /^[0-9A-Z.]* *(author|editor)s?:?$/ { has_addr = 1; } +# ---------------------------------------------------------------------- +# findall() +# +function findall(str, re, array, i) +{ + array[0] = str + while (match(str, re) > 0) { + i += 1 + array[i] = substr(str, RSTART, RLENGTH) + str = substr(str, RSTART + RLENGTH) + } + delete array[0] +} +# ---------------------------------------------------------------------- +# flaw() +# +function flaw(str, indented) +{ + print fold(" " flawmark " " str, " ", columns) + print "" + flaws++ +} -# RFC 3978 / 2026 compliance +# ---------------------------------------------------------------------- +# fold(str) +# +# This could have been done by piping through fold, too, but we'd have +# to postprocess to add indentation anyway, and this should be a lot +# quicker for short texts. +# +function fold(str, indent, cols, width, pos, lpos, npos) +{ + pos = 1 + #print "str: ", str; + #print "indent: ", indent; + #print "cols: ", cols; + insert = "\n" indent + width = cols + while (pos + width - 1 < length(str)) { + frag = substr(str, pos, width) + lpos = rindex(frag, " ") + npos = index(frag, "\n") + if (npos && npos < lpos) { + lpos = npos + } + if (! lpos) { + frag = substr(str, pos + width) + lpos = index(frag, " ") + if (lpos) { + lpos += width + } + } + if (lpos) { + #print "** before break :", "..." substr(str, pos+lpos-9, 8) + #print "** after break :", substr(str, pos+lpos, 8) "..." + str = substr(str, 1, pos + lpos - 2) insert substr(str, pos + lpos) + pos = pos + lpos + length(insert) + } else { + return str + } + width = cols - length(indent) + } + return str +} + +# ---------------------------------------------------------------------- +function get_creation_date(doc, state, created, i) +{ + get_state(doc, state) + split("creationdate created submitted", keys, FS) + for (i in keys) { + key = keys[i] + if (key in state) { + created = state[key] + if (created == "None") { + created = "" + } + break + } + } + return created +} + +function get_draftcode(draftname, state, code) +{ + if (draftname) { + if ("deststatus" in state) { + status = tolower(state["deststatus"]) + if (status != "none") { + code = status2code[status] + } + } + } + return code +} -/^[ \t0-9.]*This document may only be posted in an Internet-Draft.$/ { has["rfc3978_5_3"] = FNR; } - - { gsub(/ +/, " ", normalized); } -normalized ~ /by submitting this internet-draft/ { - para = get_para() - - almost = almost_boilerplate["rfc3978_5_1"] - - # Order is significant here -- try the longer text before subsets of it - if ( match_para(para, "rfc3978_5_1", "rfc3978_5_2ax") \ - || match_para(para, "rfc3978_5_1", "rfc3978_5_2a") \ - || match_para(para, "rfc3978_5_1", "rfc3978_5_2bx") \ - || match_para(para, "rfc3978_5_1", "rfc3978_5_2b") \ - || match_para(para, "rfc3978_5_1") \ - || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2ax") \ - || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2a") \ - || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2bx") \ - || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2b") \ - || match_para(para, "rfc3978_5_1_a") \ - || match_para(para, "rfc3667_5_1", "rfc3978_5_2ax") \ - || match_para(para, "rfc3667_5_1", "rfc3978_5_2a") \ - || match_para(para, "rfc3667_5_1", "rfc3978_5_2bx") \ - || match_para(para, "rfc3667_5_1", "rfc3978_5_2b") \ - || match_para(para, "rfc3667_5_1") \ - ) { - almost_boilerplate["rfc3978_5_1"] = almost; - } - - - } -normalized ~ /this document may not be modified/ { - para = get_para() - match_para(para, "trust-28-dec-2009_6_c_i") \ - || match_para(para, "trust-28-dec-2009_6_c_ii") \ - || match_para(para, "rfc3978_5_2a") \ - || match_para(para, "rfc3978_5_2ax") \ - || match_para(para, "rfc3978_5_2b") \ - || match_para(para, "rfc3978_5_2bx"); - } -normalized ~ /copyright ?\(c\) ?the / { - if (! in_mib) { - some_copyright = FNR - para = get_para() - has_some_year = match_para(para, "rfc3978_5_4_p1", "rfc3978_5_4_p2", "rfc3978_5_5"); - has_some_year = match_para(para, "rfc3978_5_4_p1_u4748", "rfc3978_5_4_p2", "rfc3978_5_5_u4748") || has_some_year; - - has_this_year = match_para(para, "rfc3978_5_4_p1_now"); - has_this_year = match_para(para, "rfc3978_5_4_p1_u4748_now") || has_this_year; - - if ( ! has_some_year ) { - match_para(para, "rfc3978_5_4_p1_e"); - match_para(para, "rfc3978_5_4_p1_u4748_e"); - } - - match_para(para, "rfc2026_10_4C_p1", "rfc2026_10_4C_p2", "rfc2026_10_4C_p3", "rfc2026_10_4C_p4"); - if (has_some_year && !has_this_year) has["rfc3978_5_4_p1_old"] = FNR; - } - } -normalized ~ /this document is subject to the rights/ { - para = get_para() - match_para(para, "rfc3978_5_4_p2"); - } -normalized ~ /this document and the information/ { - para = get_para() - match_para(para, "rfc3978_5_5"); - match_para(para, "rfc3978_5_5_u4748"); - match_para(para, "rfc2026_10_4C_p4"); - } -normalized ~ /the ietf takes no position regarding/ { - para = get_para() - match_para(para, "rfc3979_5_p1", "rfc3979_5_p2", "rfc3979_5_p3"); - match_para(para, "rfc2026_10_4A"); - } -normalized ~ /copies of ipr disclosures made to the/ { - para = get_para() - match_para(para, "rfc3979_5_p2", "rfc3979_5_p3"); - } -normalized ~ /the ietf invites any interested party/ { - para = get_para() - match_para(para, "rfc3979_5_p3"); - match_para(para, "rfc2026_10_4B"); - } -normalized ~ /this document and translations of it/ { - para = get_para() - match_para(para, "rfc2026_10_4C_p2", "rfc2026_10_4C_p3", "rfc2026_10_4C_p4"); - } -normalized ~ /the limited permissions granted above/ { - para = get_para() - match_para(para, "rfc2026_10_4C_p3", "rfc2026_10_4C_p4"); - } -normalized ~ /the ietf has been notified of intellectual/ { - para = get_para() - match_para(para, "rfc2026_10_4D"); - } - -normalized ~ /this document is an internet-draft and is/ { - para = get_para() - match_para(para, "rfc2026_lax_claim"); - match_para(para, "rfc2026b_lax_claim"); - - ref_in_heading_nit = ( has["rfc2026_lax_claim"] || - has["rfc2026_lax_claim"] ) && - ! match_para(para, "rfc2026_claim") && - ! match_para(para, "rfc2026b_claim"); - - match_para(para, "rfc3667_3_claim", "rfc3667_5_1" ); - match_para(para, "rfc3667_3_claim", "rfc3978_5_1_a" ); - match_para(para, "rfc3978_3_claim", "rfc3667_5_1" ); - match_para(para, "rfc3978_3_claim", "rfc3978_5_1"); - match_para(para, "rfc3978_3_claim", "rfc3978_5_1_a"); - - if (match( para, reference_format )) { - update_references(para, FNR); - } - } +function get_draftname(ref, draftname) +{ + # print "** ref:", ref + if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9][^a-zA-Z0-9_-]/)) { + draftname = substr(ref, RSTART, RLENGTH - 4) + } else if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9]$/)) { + draftname = substr(ref, RSTART, RLENGTH - 3) + } else if (match(ref, /draft-[a-zA-Z0-9_-]+/)) { + draftname = substr(ref, RSTART, RLENGTH) + } else if (match(ref, /I-D\.[a-zA-Z0-9_-]+/)) { + draftname = "draft-" substr(ref, RSTART + 4, RLENGTH - 4) + } + # print "** doc:", draftname + return draftname +} +function get_draftrev(ref, draftrev) +{ + if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9]$/)) { + draftrev = substr(ref, RSTART + RLENGTH - 2, 2) + } else if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9][^a-zA-Z0-9_-]/)) { + draftrev = substr(ref, RSTART + RLENGTH - 3, 2) + } + return draftrev +} -# IETF Trust Provisions boilerplate -normalized ~ /this internet-draft is submitted to ietf in/ { - para = get_para() - match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_i") - match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_ii") - match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_iii") - - match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_i") - match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_ii") - match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_iii") - } -normalized ~ /this internet-draft is submitted in full/ { - para = get_para() - match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1") \ - || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1a") \ - || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_i") \ - || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_ii") \ - || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_iii") \ - } -normalized ~ /copyright \(c\) [0-9]+ ietf trust and/ { - if (! in_mib) { - some_copyright = FNR - para = get_para() - has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_i_p3"); - has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_ii_p3"); - has_this_year = match_para(para, "trust-28-dec-2009_6_b_i_p2_now"); - } - } -normalized ~ /this document is subject to bcp 78/ { - para = get_para() - match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_i") - match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_ii") - match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_iii") - - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_i") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_ii") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_iii") - - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_i") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_ii") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_iii") - - match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_i") - match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_ii") - match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_iii") - - match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_i") - match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_ii") - match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_iii") - } -normalized ~ /this document may contain material from ietf/ { - para = get_para() - match_para(para, "trust-12-sep-2009_6_c_iii") - match_para(para, "trust-28-dec-2009_6_c_iii") - } +# ---------------------------------------------------------------------- +# get_para() +# +function get_para() +{ + para = strip($0) + while (((getline) > 0) && (text = strip($0)) != "") { + check_line() + if (para ~ /-$/) { + para = para text + } else if (para ~ /[A-Za-z0-9]\/$/ && text ~ /^[a-z0-9_-]+([)\/]|\.[a-z])/) { + para = para text + } else if (para ~ /[A-Za-z0-9]$/ && text ~ /^\/[a-z0-9_-]+([)\/]|\.[a-z])/) { + para = para text + } else if (para ~ /[0-9A-Fa-f]:$/ && text ~ /^[0-9A-Fa-f]+:/) { + para = para text + } else { + para = para " " text + } + } + return para +} +function get_rfcnum(ref, num) +{ + for (;;) { + if (match(ref, /(RFC|rfc)[0-9][0-9]+/)) { + num = substr(ref, RSTART + 3, RLENGTH - 3) + 0 + } else if (match(ref, /(RFC|rfc)[ -][0-9][0-9]+/)) { + num = substr(ref, RSTART + 4, RLENGTH - 4) + 0 + } else if (match(ref, /(Request [Ff]or Comments) [0-9][0-9]+/)) { + num = substr(ref, RSTART + 21, RLENGTH - 21) + 0 + } else if (match(ref, /(Request [Ff]or Comments)( \([^\)]*\))? [0-9][0-9]+/)) { + num = substr(ref, RSTART + RLENGTH - 4, 4) + 0 + } else { + if (! num) { + note("Unexpected reference format, failed extracting the RFC number: " ref) + } + break + } + if (RSTART + RLENGTH <= 1) { + break + } + ref = substr(ref, RSTART + RLENGTH) + } + return num +} -# RFC 2119 compliance -normalized ~ /(the key ?words|in this document, several words are used)/ { - para = get_para() - if (match_para(para, "rfc2119_p2") || match_para(para, "rfc2119_p2a") || match_para(para, "rfc8174_p11") ) { - if (match(para, /NOT RECOMMENDED/)) rfc2119_p2_not_recommended++; - } - - if (match( para, reference_format )) { - reftag = substr(para, RSTART+1, RLENGTH-2); - reftag2119 = reftag - update_references(para, FNR); - } - } +# ---------------------------------------------------------------------- +# get_state(draft) +# +function get_state(draft, state, quiet, count) +{ + for (key in state) { + delete state[key] + } + statefile = statusdir "/" draft ".state" + ## Not sure that this fallback handling is necessary. Keeping it commented out for now. + # if ( ( getline < statefile ) < 0 ) { + # close(statefile) + # note("... Trying to download missing state file for " draft " ...") + # command = "idnits --download '" draft " state' http://tools.ietf.org/draft/" draft "/state " statusdir "/" draft ".state 'Doc-tag: " draft "'" + # while ( (command | getline) > 0) print $0; + # } + while ((getline < statefile) > 0) { + if ($1 ~ /^Doc-/) { + count++ + key = substr($1, 5, length($1) - 5) + $1 = "" + value = strip($0) + sub(/;[^;]*$/, "", value) + state[key] = value + } + } + close(statefile) + datefile = statefile ".date" + if ((getline < datefile) > 0 && $0) { + state["downloaded"] = $0 + } else { + state["downloaded"] = "unsuccessful" + } + if (! count && ! quiet) { + comment("No information found for " draft " - is the name correct?") + } + return count +} -#/^[ \t0-9.]*Table Of [Cc]ontents?:?$/ { has_toc = 1; misspelled_toc = 1} -/^[ \t0-9.]*(Author|Editor)([^\047]s|s[^\047]) [Aa]ddress(es)?$/ { has_addr = 1; misspelled_addr = 1; } -/^[ \t0-9.]*(Authors?|Editors?) +[Aa]ddress(es)?$/ { has_addr = 1; misspelled_addr = 1; } +function is_ipv6(addr) +{ + # We have to match either 8 parts separated by colons or fewer parts with one embedded '::' or fewer parts ending in '::': + if (addr ~ /^[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+$/ || addr ~ /([0-9A-Fa-f]+:)([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?:$/ || addr ~ /([0-9A-Fa-f]+:)([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?(:[0-9A-Fa-f]+)(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?$/) { + return 1 + } else { + return 0 + } +} -# 1id_guidelines.txt compliance -normalized ~ /internet-drafts are working documents of/ { - para = get_para() - match_para(para, "1id_guidelines_p1", "1id_guidelines_p2", "1id_guidelines_p3a", "1id_guidelines_p4a") || - match_para(para, "1id_guidelines_p1", "1id_guidelines_p2a", "1id_guidelines_p3a", "1id_guidelines_p4a") || - match_para(para, "1id_guidelines_p1a", "1id_guidelines_p2") || - match_para(para, "1id_guidelines_p1a", "1id_guidelines_p2a"); - } -normalized ~ /internet-drafts are draft documents valid for/ { - para = get_para() - match_para(para, "1id_guidelines_p2", "1id_guidelines_p3a", "1id_guidelines_p4a") || - match_para(para, "1id_guidelines_p2a"); - } -normalized ~ /the list of current internet-drafts can be/ { - para = get_para() - match_para(para, "1id_guidelines_p3", "1id_guidelines_p4a") || - match_para(para, "1id_guidelines_p3a", "1id_guidelines_p4a"); - } -normalized ~ /the list of internet-draft shadow directories/ { - para = get_para() - match_para(para, "1id_guidelines_p4") || - match_para(para, "1id_guidelines_p4a"); - } - -normalized ~ /^obsoletes: / { - if (FNR < 10) { - c = split($0, obsoletelist, /[, ]+/); - docs = "" - for (i=2; i]*/) - full_docname = substr($0, RSTART, RLENGTH) - has_docname = 1 - } - } - } +# ---------------------------------------------------------------------- +function jdn(date, part, year, month, day, a, y, m, d) +{ + split(date, part, "-") + year = part[1] + month = part[2] + sub(/^0/, "", month) + day = part[3] + sub(/^0/, "", day) + a = int((14 - month) / 12) + y = year + 4800 - a + m = month + 12 * a - 3 + d = day + int((153 * m + 2) / 5) + 365 * y + int(y / 4) - int(y / 100) + int(y / 400) - 32045 + return d +} -# References and downref checking +# ---------------------------------------------------------------------- +# list() +function list(str, lst) +{ + split(str, lst, FS) + for (i in lst) { + lst[lst[i]] = i + delete lst[i] + } +} + +# ---------------------------------------------------------------------- +# markiff(p1, p2) +# +function markdiff(p1, p2, prefixlen, para2, suffix, leading, point, temp) +{ + prefixlen = 0 + para2 = p2 + gsub(/\. +/, ". ", p1) + gsub(/\. +/, ". ", p2) + do { + if (substr(p1, 1, 1) == substr(p2, 1, 1)) { + p1 = substr(p1, 2) + p2 = substr(p2, 2) + } else { + break + } + prefixlen++ + } while (length(p1) && length(p2)) + prefix = substr(para2, 1, prefixlen) + suffix = substr(para2, prefixlen + 1) + leading = length(prefix) - rindex(prefix, "\n") + temp = substr(prefix, length(prefix) - leading) + spacefix = gsub(/\. +/, ". ", temp) + point = index(suffix, "\n") + marker = substr("........................................................................", 1, leading + spacefix) "^\n" + return (prefix substr(suffix, 1, point) marker substr(suffix, point + 1)) +} + +# ---------------------------------------------------------------------- +# match_para() +# +function match_para(para, name1, name2, name3, name4) +{ + name[1] = name1 + name[2] = name2 + name[3] = name3 + name[4] = name4 + for (i = 1; i <= 4; i++) { + pat[i] = bp[name[i]] + } + orig = para + gsub(/ +/, " ", para) + pattern = "" + for (i = 1; i <= 4; i++) { + if (! pat[i]) { + almost_boilerplate[name[1]] = orig + if (option_debug && option_pass2) { + print "** End of patterns **" + } + return 0 + } + gsub(/. /, ". ?", pat[i]) + pattern = pattern pat[i] + if (option_debug && option_pass2) { + print "\n----", name[i], "----" + print "line", FNR, "\n" + print "" + print "'" para "'" + print "" + print "'" pattern "'" + print "" + if (para ~ pattern) { + print "** Matches **" + } else { + print "** No Match **" + } + } + if (para ~ pattern) { + for (j = 1; j <= i; j++) { + has[name[j]] = FNR - 1 + } + if (option_debug && option_pass2) { + print "** Exit **" + } + return 1 + } + sub(/ *\$?$/, " +", pattern) + if (para ~ pattern) { + if (option_debug && option_pass2) { + print "** Match with trailing text **" + } + for (j = 1; j <= i; j++) { + has[name[j]] = FNR - 1 + } + if (! pat[i + 1]) { + if (option_debug && option_pass2) { + print "** Exit: end of patterns **" + } + return 1 + } + } else { + if (option_debug && option_pass2) { + print "** Exit: No prefix match **" + } + for (k = 1; k < i; k++) { + pref = pat[k] + sub(/ *\$?$/, " +", pref) + sub(pref, "", orig) + } + stripped_orig = strip(orig) + if (index(substr(bp[name[i]], 1, 48), substr(stripped_orig, 1, 32))) { + almost_boilerplate[name[i]] = orig + } + return 0 + } + } + almost_boilerplate[name[1]] = orig + return 0 +} + +# ---------------------------------------------------------------------- +# newandolderr(old, new) +# +function newandolderr(old, new) +{ + newname = expandname(new) + oldname = expandname(old) + str = sprintf("Found new %s boilerplate, which is fine, but *also* found old boilerplate from %s on line %s.", newname, oldname, has[old]) + err(str) + if (option_verbose && option_pass2) { + showsection(old, 1) + } +} + +function nnnote(str) +{ + if (option_verbose >= 2) { + if (option_pass1) { + printf "%s(%d): %s.\n", FILENAME, FNR, str + } else { + print fold(" " notemark " " str, " ", columns) + } + } +} -normalized ~ /(intended status|category):/ { - if ( !has_intro && !has_abstract && !has_refs && !has_appendix && !has_status_of_memo) { - sta = tolower($0); - sub(/^.*(intended status|category): */, "", sta); - sub(/ .*$/, "", sta); - if ( length(intended_status) == 0) { - intended_status = sta; - intended_status_text = $0; - sub(/ .*$/, "", intended_status_text) - } - } - } - -$0 ~ reference_format { - if (in_refs) { - refpos = FNR; - reftext = strip($0); - while ((getline > 0) && (text = strip($0)) != "") { - check_line() - if ($0 ~ reference_format) { - # start of a new reference without intervening blank line - update_references(reftext, refpos); - refpos = FNR; - reftext = text; - } else { - if (reftext ~ /-$/) { - reftext = reftext text; - } else { - reftext = reftext " " text; - } - } - } - update_references(reftext, refpos); - } else { - if ((!abnf_mentioned || !in_abnf ) && !in_imap && !in_code ) update_references($0, FNR); - if ((abnf_mentioned && in_abnf ) && ($0 ~ (";.*" reference_format))) update_references($0, FNR); - } - } -/\[[0-9A-Z-]+- *$/ { - incomplete_ref_line = strip($0) - incomplete_ref_pos = FNR - } -/^ *[0-9A-Z-]+\]/ { - if (incomplete_ref_pos+1 == FNR) { - update_references(incomplete_ref_line strip($0), incomplete_ref_pos) - } - } +function nnote(str) +{ + if (option_verbose) { + if (option_pass1) { + printf "%s(%d): %s.\n", FILENAME, FNR, str + } + } +} +# ---------------------------------------------------------------------- +# note() +# +function note(str) { - text = strip($0); - if ( text == "") { - if (para) check_para(para); - para = ""; - } else { - if (para ~ /-$/) { - para = para text; + if (option_pass1) { + printf "%s(%d): %s.\n", FILENAME, FNR, str } else { - para = para " " text; + print fold(" " notemark " " str, " ", columns) } - } } +# ---------------------------------------------------------------------- +# oldandnewerr(old, new) +# +function oldandnewerr(old, new) +{ + if (! new in has) { + print "?? internal error, expected a table match on %s", new + exit + } + newname = expandname(new) + oldname = expandname(old) + str = sprintf("Found boilerplate matching %s (on line %s), which is fine, but *also* found old %s text on line %s.", newname, has[new], oldname, has[old]) + err(str) + if (option_verbose && option_pass2) { + showsection(old, 1) + showsection(new, 1) + } +} +# ---------------------------------------------------------------------- +# olderr(old, new) +# +function olderr(old) +{ + oldname = expandname(old) + str = sprintf("Found old boilerplate from %s on line %s.", oldname, has[old]) + comment(str) + if (option_verbose && option_pass2) { + showsection(old, 1, "The obsolete ", " text") + } +} -END { +function refcomment(msg, num, tag, info, numstr) +{ + numstr = sprintf("%d", num) + if (numstr in obsoleted) { + info = obsoleted[numstr] + gsub(" ", ", RFC ", info) + info = " (Obsoleted by " substr(info, 3) ")" + } + if (tag ~ numstr) { + comment(sprintf("%s: RFC %4d%s", msg, num, info)) + } else { + comment(sprintf("%s: RFC %4d (ref. '%s')%s", msg, num, tag, info)) + } +} - report(option_filename); - if (errors || longlines || hyphens || spacing || nonascii || controlchars ) print ""; - if (errors < 256) { - exit errors; - } else { - exit 255; - } +# ---------------------------------------------------------------------- +# check_downref(tag) +# +function referr(msg, num, tag, comment, info, numstr) +{ + numstr = sprintf("%d", num) + if (numstr in obsoleted) { + info = obsoleted[numstr] + gsub(" ", ", RFC ", info) + info = " (Obsoleted by " substr(info, 3) ")" + } + if (tag ~ numstr) { + errc(sprintf("%s: RFC %4d%s%s", msg, num, info, comment)) + } else { + errc(sprintf("%s: RFC %4d (ref. '%s')%s%s", msg, num, tag, info, comment)) + } } + +# ---------------------------------------------------------------------- +# report() +# +function report(filename) +{ + if (skip_file) { + return + } + if (option_pass1) { + return + } + if (option_status) { + if (! (tolower(option_status) in status2code)) { + note(sprintf("Unexpected value in --status switch ('%s'), ignoring it. (Use one of 'informational', 'experimental', 'bcp', 'ps', 'ds', 'standard'.)", option_status)) + } else { + intended_status = tolower(option_status) + } + } + if (got_input) { + is_rfc = (filename ~ /[Rr][Ff][Cc][0-9]+\.txt$/) + draftname = full_docname + sub(/\.[a-z]+$/, "", draftname) + sub(/-[0-9][0-9]$/, "", draftname) + get_state(draftname, state, quiet = 1) + destcode = get_draftcode(draftname, state) + if (option_submitcheck) { + printf ("\n Showing Errors (" errmark "), Flaws (" flawmark "), Warnings (" warnmark "), and Comments (" infomark ").\n") + print (" Errors MUST be fixed before draft submission. Flaws SHOULD be fixed before draft submission.") + } + announce("Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info):") + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + # 12 Sep 2009 values below are valid during the post-28-dec-2009 transition + if (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"] || has["trust-28-dec-2009_6_b_i_p2"] || has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"]) { + # We have some text from the current Trust Provisions boilerplate. Check that we don't have older + # boilerplate, too. + for (bpname in bp) { + if (bpname ~ /^rfc2026/ || bpname ~ /^rfc3667/ || bpname ~ /^rfc3978/ || bpname ~ /^rfc3979/) { + if (has[bpname] && ! (bpname ~ "_now")) { + newandolderr(bpname, "IETF Trust Provisions of 12 Sep 2009") + } + } + } + if (! is_rfc) { + if (! (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"])) { + sectionerr("trust-28-dec-2009_6_a", "Notice of Compliance with BCP 78 and BCP 79 according to " "IETF Trust Provisions of 28 Dec 2009, Section 6.a " "or Provisions of 12 Sep 2009, Section 6.a") + } + } + if (! has["trust-28-dec-2009_6_b_i_p2"]) { + sectionerr("trust-28-dec-2009_6_b_i_p2", "IETF Trust Provisions of 28 Dec 2009, Section 6.b Copyright Notice") + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_i_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.i or Provisions of 12 Sep 2009 Section 6.b") + if (has["trust-28-dec-2009_6_b_ii_p3"]) { + comment("It seems you're using the 'non-IETF stream' Licence Notice instead") + } + } + } else if (full_docname ~ /^draft-(iab|irtf|rfced|rfc-editor)-/) { + if (! (has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") + if (has["trust-28-dec-2009_6_b_i_p3"]) { + comment("It seems you're using the 'IETF stream' Licence Notice instead") + } + } + } else if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") + } + # The following is just an informational note because we've emitted an error earlier: + if (has["trust-12-feb-2009_6_b_p3"]) { + note("(You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Feb 2009 rather than one of the newer Notices. " "See https://trustee.ietf.org/license-info/.)\n") + } + if (has["trust-12-sep-2009_6_b_p3"]) { + err("You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Sep 2009 rather than the newer Notice from 28 Dec 2009. " "(See https://trustee.ietf.org/license-info/)") + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (has["trust-28-dec-2009_6_c_i"]) { + warn("The document has an IETF Trust Provisions of 28 Dec 2009, Section 6.c(i) Publication Limitation clause.") + } + if (has["trust-28-dec-2009_6_c_ii"]) { + err("The document has an IETF Trust Provisions, 28 Dec 2009, Section 6.c(ii) Publication Limitation clause.") + } + } else { + if (has["trust-28-dec-2009_6_c_i"]) { + comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(i) Publication Limitation clause.") + } + if (has["trust-28-dec-2009_6_c_ii"]) { + comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(ii) Publication " "Limitation clause. If this document is intended for submission to the IESG for " "publication, this constitutes an error.") + } + } + } else if ((has["rfc3667_5_1"] || has["rfc3978_5_1_a"] || has["rfc3978_5_1"] || has["rfc3978_5_2b"] || has["rfc3978_5_3"] || has["rfc3978_5_5"] || has["rfc3978_5_5_u4748"] || has["rfc3979_5_p1"] || has["rfc3979_5_p2"] || has["rfc3979_5_p3"])) { + err("It looks like you're using RFC 3978 boilerplate. You should update this to the " "boilerplate described in the IETF Trust License Policy document (see " "https://trustee.ietf.org/license-info), which is required now.") + if (has["rfc3667_5_1"]) { + olderr("rfc3667_5_1") + } + if (has["rfc3978_5_1_a"]) { + olderr("rfc3978_5_1_a") + } + if (has["rfc3978_5_1"]) { + olderr("rfc3978_5_1") + } + if (has["rfc3978_5_2b"]) { + olderr("rfc3978_5_2b") + } + if (has["rfc3978_5_3"]) { + olderr("rfc3978_5_3") + } + if (has["rfc3978_5_5"]) { + olderr("rfc3978_5_5") + } + if (has["rfc3978_5_5_u4748"]) { + olderr("rfc3978_5_5_u4748") + } + if (has["rfc3979_5_p1"]) { + olderr("rfc3979_5_p1") + } + if (has["rfc3979_5_p2"]) { + olderr("rfc3979_5_p2") + } + if (has["rfc3979_5_p3"]) { + olderr("rfc3979_5_p3") + } + # Ok, so we have some 3978/3979 boilerplate - make sure we don't *also* have some + # lingering old boilerplate... + if (has["rfc3978_5_1"]) { + if (has["rfc3667_5_1"]) { + oldandnewerr("rfc3667_5_1", "rfc3978_5_1") + } + } + if (has["rfc3978_5_4_p1"]) { + if (has["rfc2026_10_4C_p1"]) { + oldandnewerr("rfc2026_10_4C_p1", "rfc3978_5_4_p1") + } + } + if (has["rfc3978_5_4_p1_u4748"]) { + if (has["rfc2026_10_4C_p1"]) { + oldandnewerr("rfc2026_10_4C_p1", "rfc3978_5_4_p1_u4748") + } + } + if (has["rfc3978_5_4_p1_u4748"]) { + if (has["rfc3978_5_4_p1"]) { + oldandnewerr("rfc3978_5_4_p1", "rfc3978_5_4_p1_u4748") + } + } + if (has["rfc3978_5_4_p1_u4748_e"]) { + if (has["rfc3978_5_4_p1"]) { + oldandnewerr("rfc3978_5_4_p1", "rfc3978_5_4_p1_u4748_e") + } + } + if (has["rfc3978_5_4_p1_u4748"]) { + if (has["rfc3978_5_4_p1_e"]) { + oldandnewerr("rfc3978_5_4_p1_e", "rfc3978_5_4_p1_u4748") + } + } + if (has["rfc3978_5_5"]) { + if (has["rfc2026_10_4C_p4"]) { + oldandnewerr("rfc2026_10_4C_p4", "rfc3978_5_5") + } + } + if (has["rfc3978_5_5_u4748"]) { + if (has["rfc2026_10_4C_p4"]) { + oldandnewerr("rfc2026_10_4C_p4", "rfc3978_5_5_u4748") + } + } + if (has["rfc3978_5_5_u4748"]) { + if (has["rfc3978_5_5"]) { + oldandnewerr("rfc3978_5_5", "rfc3978_5_5_u4748") + } + } + if (has["rfc3979_5_p1"]) { + if (has["rfc2026_10_4A"]) { + oldandnewerr("rfc2026_10_4A", "rfc3979_5_p1") + } + } + if (has["rfc3979_5_p3"]) { + if (has["rfc2026_10_4B"]) { + oldandnewerr("rfc2026_10_4B", "rfc3979_5_p3") + } + } + if (has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) { + err("The document claims conformance with section 10 of RFC 2026, but uses " "some RFC 3978/3979 boilerplate. As RFC 3978/3979 replaces section 10 of " "RFC 2026, you should not claim conformance with it if you have changed " "to using RFC 3978/3979 boilerplate.") + } + if (! (has["rfc3978_5_1"]) && ! is_rfc) { + sectionerr("rfc3978_5_1", "RFC 3978 Section 5.1 IPR Disclosure Acknowledgement") + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (has["rfc3978_5_2b"]) { + err("The document has an RFC 3978 Section 5.2(b) Derivative Works Limitation clause.") + } + if (has["rfc3978_5_3"]) { + err("The document has an RFC 3978 Section 5.3 Publication Limitation clause.") + } + } else { + if (has["rfc3978_5_2b"]) { + comment("The document has an RFC 3978 Section 5.2(b) Derivative Works Limitation clause. " "If this document is intended for submission to the IESG for publication, this " "constitutes an error.") + } + if (has["rfc3978_5_3"]) { + comment("The document has an RFC 3978 Section 5.3 Publication Limitation clause. " "If this document is intended for submission to the IESG for publication, this " "constitutes an error.") + } + } + if (! has["rfc3978_5_4_p1_u4748"]) { + if (has["rfc3978_5_4_p1"]) { + err("This document has an original RFC 3978 Section 5.4 Copyright Line, " "instead of the newer IETF Trust Copyright according " "to RFC 4748.") + } else { + sectionerr("rfc3978_5_4_p1_u4748", "RFC 3978 Section 5.4 (updated by RFC 4748) Copyright Line") + } + } + if (! has["rfc3978_5_4_p2"]) { + sectionerr("rfc3978_5_4_p2", "RFC 3978 Section 5.4 Reference to BCP 78") + } + if (! has["rfc3978_5_5_u4748"]) { + if (has["rfc3978_5_5"]) { + err("This document has an original RFC 3978 Section 5.5 Disclaimer, " "instead of the newer disclaimer which includes the IETF Trust according " "to RFC 4748.") + } else { + sectionerr("rfc3978_5_5_u4748", "RFC 3978 Section 5.5 (updated by RFC 4748) Disclaimer") + } + } + if (! has["rfc3979_5_p1"]) { + sectionerr("rfc3979_5_p1", "RFC 3979 Section 5, para. 1 IPR Disclosure Acknowledgement") + if (has["rfc2026_10_4A"]) { + note("( - It does however have an RFC 2026 Section 10.4(A) Disclaimer.)") + } + } + if (! has["rfc3979_5_p2"]) { + sectionerr("rfc3979_5_p2", "RFC 3979 Section 5, para. 2 IPR Disclosure Acknowledgement") + } + if (! has["rfc3979_5_p3"]) { + sectionerr("rfc3979_5_p3", "RFC 3979 Section 5, para. 3 IPR Disclosure Invitation") + if (has["rfc2026_10_4B"]) { + note("( - It does however have an RFC 2026 Section 10.4(B) IPR Disclosure Invitation.)") + } + } + if (has["rfc3667_3_claim"] || (has["rfc3667_5_1"] || has["rfc3978_5_1_a"]) && ! has["rfc3978_5_1"]) { + err("The document uses RFC 3667 boilerplate or RFC 3978-like " "boilerplate instead of verbatim RFC 3978 boilerplate. After 6 May 2005, " "submission of drafts without verbatim RFC 3978 boilerplate is not " "accepted.") + note("The following non-3978 patterns matched text found in the document. That text should be removed or replaced:\n") + if (has["rfc3667_3_claim"]) { + showsection("rfc3667_3_claim", 2) + } + if (has["rfc3667_5_1"]) { + showsection("rfc3667_5_1", 2) + } + if (has["rfc3978_5_1_a"] && ! has["rfc3978_5_1"]) { + showsection("rfc3978_5_1_a", 2) + } + } + if ((has["rfc3978_5_4_p1"] && has["rfc3978_5_4_p1_e"]) || (has["rfc3978_5_4_p1_u4748"] && has["rfc3978_5_4_p1_u4748_e"])) { + warn("In addition to a regular copyright notice, the document also has a " "copyright notice embedded in the text.") + } + } else if ((has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"] || has["rfc2026_10_4C_p2"] || has["rfc2026_10_4C_p3"] || has["rfc2026_10_4C_p4"])) { + if (option_verbose) { + print "" + if (has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) { + note(" [Claims RFC 2026 conformance...]") + } + if (has["rfc2026_10_4C_p1"]) { + note(" [Has RFC 2026 Sec. 10.4 para. 1...]") + } + if (has["rfc2026_10_4C_p2"]) { + note(" [Has RFC 2026 Sec. 10.4 para. 2...]") + } + if (has["rfc2026_10_4C_p3"]) { + note(" [Has RFC 2026 Sec. 10.4 para. 3...]") + } + if (has["rfc2026_10_4C_p4"]) { + note(" [Has RFC 2026 Sec. 10.4 para. 4...]") + } + print "" + } + err("Looks like you're using RFC 2026 boilerplate. This must be updated to follow RFC 3978/3979, as updated by RFC 4748.") + } else { + if (some_copyright) { + copyright_msg = " Found some kind of copyright notice around line " some_copyright " but it does not match any copyright boilerplate known by this tool." + } else { + copyright_msg = "" + } + err("Cannot find the required boilerplate sections (Copyright, IPR, etc.) in this document." copyright_msg) + note("Expected boilerplate is as follows today (" today ") according to https://trustee.ietf.org/license-info :\n") + showsection("trust-28-dec-2009_6_a") + showsection("trust-28-dec-2009_6_b_i_p2") + showsection("trust-28-dec-2009_6_b_i_p3") + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + } + if (! is_rfc) { + announce("Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt:") + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + if (! has_id_indication) { + errg("Missing document type: Expected \"INTERNET-DRAFT\" in the upper left hand corner of the first page") + } + if (! has_expiration) { + errg("Missing expiration date. The document expiration date should appear on the first and last page.") + } + if (! (has["1id_guidelines_p1"] || has["1id_guidelines_p1a"])) { + sectionerr("1id_guidelines_p1", "1id_guidelines paragraph about Internet-Drafts being working documents") + } + if (! (has["1id_guidelines_p2"] || has["1id_guidelines_p2a"])) { + sectionerr("1id_guidelines_p2", "1id_guidelines paragraph about 6 months document validity") + } + if (! (has["1id_guidelines_p3"] || has["1id_guidelines_p3a"] || has["1id_guidelines_p1a"])) { + sectionerr("1id_guidelines_p3", "1id_guidelines paragraph about the list of current Internet-Drafts") + } + if (! (has["1id_guidelines_p4"] || has["1id_guidelines_p4a"] || has["1id_guidelines_p1a"])) { + sectionerr("1id_guidelines_p4", "1id_guidelines paragraph about the list of Shadow Directories") + } + if (has["1id_guidelines_p1a"] && has["1id_guidelines_p3"]) { + newandolderr("1id_guidelines_p3", "1id_guidelines_p1a") + } + if (has["1id_guidelines_p1a"] && has["1id_guidelines_p3a"]) { + newandolderr("1id_guidelines_p3a", "1id_guidelines_p1a") + } + if (has["1id_guidelines_p1a"] && has["1id_guidelines_p4"]) { + newandolderr("1id_guidelines_p4", "1id_guidelines_p1a") + } + if (has["1id_guidelines_p1a"] && has["1id_guidelines_p4a"]) { + newandolderr("1id_guidelines_p4a", "1id_guidelines_p1a") + } + if (has_docname) { + file_docname = option_filename + # Get rid of path and extension + sub(".*/", "", file_docname) + sub(/\.(txt|pdf|xml|doc|nr)$/, "", file_docname) + sub(".*/", "", full_docname) + sub(/\.(txt|pdf|xml|doc)$/, "", full_docname) + if (good_docname != full_docname || full_docname ~ /[^a-z0-9-]/) { + errg(sprintf("Bad filename characters: the document name given in the document, '%s', contains other characters than digits, lowercase letters and dash.", full_docname)) + } else if (file_docname ~ /[^a-z0-9-]/) { + errg(sprintf("Bad filename characters: the file name of the draft, '%s', contains other characters than digits, lowercase letters and dash.", file_docname)) + } + if (! match(full_docname, /.*-[0-9][0-9]$/)) { + errg(sprintf("Missing revision: the document name given in the document, '%s', does not give the document revision number", full_docname)) + } + doc_has_empty_source = 0 + if (match(full_docname, /^draft--/)) { + doc_has_empty_source = 1 + errg(sprintf("Empty name element: the document name given in the document, '%s', lacks the source element (it starts with 'draft--'). See https://www.ietf.org/id-info/1id-guidelines.txt, section 7, on how to construct a good document name.", full_docname)) + } + if (match(full_docname, /--[0-9][0-9]$/)) { + errg(sprintf("Negative revision number: the document name given in the document, '%s', seems to have a negative revision number (it ends with '--%s'). See https://www.ietf.org/id-info/1id-guidelines.txt, section 7, on how to construct a good document name.", full_docname, substr(full_docname, length(full_docname) - 1))) + } + if (! match(full_docname, /^draft-[^-]+-.+-[0-9][0-9](\.[a-z]+)?$/)) { + if (! doc_has_empty_source) { + flaw(sprintf("Missing draftname component: the document name given in the document, '%s', does not seem to contain all the document name components required ('draft' prefix, document source, document name, and revision) -- see https://www.ietf.org/id-info/guidelines#naming for more information.", full_docname)) + } + } + if (length(file_docname) > length(full_docname)) { + long_docname = file_docname + } else { + long_docname = full_docname + } + sub(/-[0-9][0-9]$/, "", long_docname) + if (length(long_docname) > 50) { + errg(sprintf("Too long document name: The document name (without revision number), '%s', is %d characters long, but may be at most 50 characters", long_docname, length(long_docname))) + } + if (file_docname && file_docname != full_docname) { + warn(sprintf("Mismatching filename: the document gives the document name as '%s', but the file name used is '%s'", full_docname, file_docname)) + } + } else { + errg("Expected the document's filename to be given on the first page, but didn't find any") + } + if (has["rfc3978_5_1"] > firstpagelength && ! is_rfc) { + errg("An " expandname("rfc3978_5_1") " paragraph was found, but not on the first page, as required.") + } + # According to the nits page we should be comparing to 15 here, but + # that may be without the boilerplate - and practice seems to permit + # also 16 pages including boilerplate, so... + if (! has_toc && ((pagecount > 16) || (FNR > 50 * 16))) { + errw("The document is more than 15 pages and seems to lack a Table of Contents.") + } + if (nonascii && ! option_nonascii) { + warn(sprintf("There %s %d instance%s of lines with non-ascii characters in the document.", (nonascii == 1 ? "is" : "are"), nonascii, (nonascii == 1 ? "" : "s"))) + } + if (length(intended_status) == 0) { + warn("No 'Intended status' indicated for this document; assuming Proposed Standard") + intended_status = "proposed standard" + } + if (maxpagelength > 58) { + warnc(sprintf("The page length should not exceed 58 lines per page, " "but there was %d longer page%s, the longest (page %d) being %d lines", longpagecount, (longpagecount == 1 ? "" : "s"), longestpage, maxpagelength)) + } + if (pagecount > formfeedcount + 1) { + warnc(sprintf("It seems as if not all pages are separated by form feeds - " "found %d form feeds but %d page%s", formfeedcount, pagecount, (pagecount == 1 ? "" : "s"))) + } + if (missing_nroff_postprocessing) { + comment(sprintf("Found %d instances of the string 'FORMFEED[Page...' -- is this a case of missing nroff postprocessing?", missing_nroff_postprocessing)) + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + } + } + if (option_submitcheck) { + announce("Running in submission checking mode -- *not* checking nits according to https://www.ietf.org/id-info/checklist .") + } else { + announce("Checking nits according to https://www.ietf.org/id-info/checklist :") + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + if (! has_abstract) { + err("The document seems to lack an Abstract section.", indented_abstract) + } + if (! has_intro) { + errc("The document seems to lack an Introduction section.", indented_intro) + } + if (! has_security) { + errc("The document seems to lack a Security Considerations section.", indented_security) + } + if (is_rfc) { + if (! has_iana) { + comment("The document seems to lack an IANA Considerations section. ", indented_iana) + } + } else if (! has_iana) { + errc("The document seems to lack an IANA Considerations section. " "(See Section 2.2 of https://www.ietf.org/id-info/checklist for how " "to handle the case when there are no actions for IANA.)", indented_iana) + } + if (! has_addr) { + errc("The document seems to lack an Authors' Addresses Section.") + } + if (has_refs && ! has_splitrefs) { + errc("The document seems to lack separate sections for Informative/Normative References. " "All references will be assumed normative when checking for downward references.") + } + if (option_list_matches) { + print fold(" Boilerplate matches:", " ", columns) + for (n in has) { + if (n) { + note(sprintf("Found", n, "on line", has[n])) + } + } + print "" + } + if (spacing > 50) { + errc(sprintf("There %s %d instance%s of weird spacing in the document. " "Is it really formatted ragged-right, rather than justified?", (spacing == 1 ? "is" : "are"), spacing, (spacing == 1 ? "" : "s"))) + } + if (longlines) { + msg = sprintf("There %s %d instance%s of too long lines in the document, " "the longest one being %d character%s in excess of 72.", (longlines == 1 ? "is" : "are"), longlines, (longlines == 1 ? "" : "s"), excesslength, ((excesslength > 1) ? "s" : "")) + if (! option_submitcheck) { + errc(msg) + } else { + warn(msg) + } + } + if (controlchars) { + errc(sprintf("There %s %d instance%s of lines with control characters in the document.", (controlchars == 1 ? "is" : "are"), controlchars, (controlchars == 1 ? "" : "s"))) + } + if (abstract_references) { + list(abstract_references, ref_list) + ref_str = "" + for (i in ref_list) { + if (ref_str) { + ref_str = ref_str ", " + } + ref_str = ref_str i + } + errc("The abstract seems to contain references (" ref_str "), which it shouldn't. Please replace those with straight textual mentions of the documents in question.") + } + if (badfqdns) { + warnc(sprintf("There %s %d instance%s of lines with " "non-RFC2606-compliant FQDNs in the document.", (controlchars == 1 ? "is" : "are"), badfqdns, (badfqdns == 1 ? "" : "s"))) + } + if (badipv4addr) { + warnc(sprintf("There %s %d instance%s of lines with " "non-RFC6890-compliant IPv4 addresses in the document. " "If these are example addresses, they should be changed.", (controlchars == 1 ? "is" : "are"), badipv4addr, (badipv4addr == 1 ? "" : "s"))) + } + if (mcastipv4addr) { + warnc(sprintf("There %s %d instance%s of lines with " "multicast IPv4 addresses in the document. " "If these are generic example addresses, they should be changed " "to use the 233.252.0.x range defined in RFC 5771", (controlchars == 1 ? "is" : "are"), mcastipv4addr, (mcastipv4addr == 1 ? "" : "s"))) + } + if (privipv4addr) { + warnc(sprintf("There %s %d instance%s of lines with " "private range IPv4 addresses in the document. " "If these are generic example addresses, they should be changed " "to use any of the ranges defined in RFC 6890 (or successor): " "192.0.2.x, 198.51.100.x or 203.0.113.x.", (controlchars == 1 ? "is" : "are"), privipv4addr, (privipv4addr == 1 ? "" : "s"))) + } + if (badipv6addr) { + warnc(sprintf("There %s %d instance%s of lines with " "non-RFC3849-compliant IPv6 addresses in the document. " "If these are example addresses, they should be changed.", (controlchars == 1 ? "is" : "are"), badipv6addr, (badipv6addr == 1 ? "" : "s"))) + } + if (ulipv6addr) { + warnc(sprintf("There %s %d instance%s of lines with " "Unique Local Unicast IPv6 addresses (RFC 4193) in the document. " "If these are generic example addresses, they should be changed", "to use the 2001:DB8::/32 range defined in RFC 4291.", (controlchars == 1 ? "is" : "are"), ulipv6addr, (ulipv6addr == 1 ? "" : "s"))) + } + if (llipv6addr) { + warnc(sprintf("There %s %d instance%s of lines with " "Link Local Unicast IPv6 addresses (RFC 4291) in the document. " "If these are generic example addresses, they should be changed", "to use the 2001:DB8::/32 range defined in RFC 4291.", (controlchars == 1 ? "is" : "are"), llipv6addr, (llipv6addr == 1 ? "" : "s"))) + } + if (ipv4_example_addr && ! ipv6_example_addr) { + comment("The document has examples using IPv4 documentation addresses " "according to RFC6890, but does not use any IPv6 documentation " "addresses. Maybe there should be IPv6 examples, too?") + } + if (keywords && ! has["rfc2119_p2"] && ! has["rfc2119_p2a"] ! has["rfc8174_p11"]) { + # Check whether there is a reference to RFC 2119 at all + for (reftag in ref_text) { + if (ref_text[reftag] ~ /RFC[- ]?2119/) { + found_2119_ref = ref_def[reftag] + } + } + if (! found_2119_ref) { + sectionerr("rfc8174_p11", "both a reference to RFC 2119 and the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords", option_checklistwarn) + if (option_verbose <= 1) { + for (i = 1; i <= 5; i++) { + if (i in rfc2119line) { + fnr = rfc2119line[i] + printf " RFC 2119 keyword, line %d: '...%s...'\n", fnr, line[fnr] + } + } + if (keywords > 5) { + note(sprintf("(%d more instance%s...)", keywords - 5, (keywords - 5 == 1 ? "" : "s"))) + } + } + print ("") + } + } + if (obsoletes_junk) { + warnc("The 'Obsoletes: ' line in the draft header should list only the _numbers_ of the RFCs " "which will be obsoleted by this document (if approved); it should not include the word " "'RFC' in the list.") + } + if (updates_junk) { + warnc("The 'Updates: ' line in the draft header should list only the _numbers_ of the RFCs " "which will be updated by this document (if approved); it should not include the word " "'RFC' in the list.") + } + list(abstract_mentions, abstract_rfcs) + list(obsoletes_docs, obsoletes_list) + list(abstract_obsoletes, abs_obs_list) + for (doc in obsoletes_list) { + if (! (doc in abs_obs_list)) { + if (doc in abstract_rfcs) { + comment("The draft header indicates that this document obsoletes " doc ", but the abstract doesn't seem to directly say this. It does mention " doc " though, so this could be OK.") + } else { + comment("The draft header indicates that this document obsoletes " doc ", but the abstract doesn't seem to mention this, which it should.") + } + } + } + for (doc in abs_obs_list) { + if (! (doc in obsoletes_list)) { + comment("The abstract seems to indicate that this document obsoletes " doc ", but the header doesn't have an 'Obsoletes:' line to match this.") + } + } + list(updates_docs, updates_list) + list(abstract_updates, abs_upd_list) + for (doc in updates_list) { + if (! (doc in abs_upd_list)) { + if (doc in abstract_rfcs) { + comment("The draft header indicates that this document updates " doc ", but the abstract doesn't seem to directly say this. It does mention " doc " though, so this could be OK.") + } else { + comment("The draft header indicates that this document updates " doc ", but the abstract doesn't seem to mention this, which it should.") + } + } + } + for (doc in abs_upd_list) { + if (! (doc in updates_list)) { + comment("The abstract seems to indicate that this document updates " doc ", but the header doesn't have an 'Updates:' line to match this.") + } + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + # -------------------------------------------------------------- + # Warnings + } + announce("Miscellaneous warnings:") + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + warnshere = warnings + if (has_pk_mark) { + comment("The first octets (the first characters of the first line) of this " "draft are 'PK', which can make Internet Explorer erroneously think " "that it is a zip file. It is recommended that you change this, for " "instance by inserting a blank line before the line starting with 'PK'.") + } + if (has_bm_mark) { + comment("The first octets (the first characters of the first line) of this " "draft are 'BM', which can make the draft submission tool erroneously think " "that it is an image .bmp file. It is recommended that you change this, for " "instance by inserting a blank line before the line starting with 'BM'.") + } + checkmultibp("rfc3978_5_1") + checkmultibp("rfc3978_5_2b") + checkmultibp("rfc3978_5_3") + checkmultibp("rfc3978_5_5") + checkmultibp("rfc3978_5_5_u4748") + checkmultibp("rfc3979_5_p1") + checkmultibp("rfc3979_5_p2") + checkmultibp("rfc3979_5_p3") + if ((has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) && (has["rfc2026_10_4C_p2"] || has["rfc2026_10_4C_p3"] || has["rfc2026_10_4C_p4"])) { + if (option_rfc2026) { + if (! has["rfc2026_10_4A"]) { + warn("The document seems to lack an RFC 2026 Section 10.4(A) Disclaimer.") + } + if (! has["rfc2026_10_4B"]) { + warn("The document seems to lack an RFC 2026 Section 10.4(B) IPR Disclosure Invitation.") + } + if (has["rfc2026_10_4D"]) { + warn("The document has an RFC 2026 Section 10.4(D) IPR Notice.") + } + } + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (has["rfc3978_5_2a"]) { + warn("The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause.") + } + } else if (has["rfc3978_5_2a"]) { + note("The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause.") + } + if (has["rfc3978_5_4_p1"] && ! has["rfc3978_5_4_p1_now"]) { + warn("The copyright year in the RFC 3978 Section 5.4 Copyright Line does not match the current year") + } + if (has["rfc3978_5_4_p1_u4748"] && ! has["rfc3978_5_4_p1_u4748_now"]) { + warn("The copyright year in the IETF Trust Copyright Line does not match the current year") + } + if (has["trust-28-dec-2009_6_b_i_p2"] && ! has["trust-28-dec-2009_6_b_i_p2_now"]) { + warn("The copyright year in the IETF Trust and authors Copyright Line does not match the current year") + } + if (has["rfc3978_5_4_p1_old"] && has["rfc3978_5_4_p1_now"]) { + warn(sprintf("The copyright year in the RFC 3978 Section 5.4 Copyright around line %s does not match the year around line %s", has["rfc3978_5_4_p1_old"], has["rfc3978_5_4_p1_now"])) + } + if (has["rfc3978_5_4_p1_old"] && has["rfc3978_5_4_p1_u4748_now"]) { + warn(sprintf("The copyright year in the IETF Trust Copyright around line %s does not match the year around line %s", has["rfc3978_5_4_p1_old"], has["rfc3978_5_4_p1_u4748_now"])) + } + # if (has["rfc3978_5_4_p1"] > firstpagelength) { + # warn( "An " expandname("rfc3978_5_4_p1") " paragraph was found, but not on the first page, as suggested." ); + # } + # + # if (has["rfc3978_5_4_p1_u4748"] > firstpagelength) { + # warn( "An " expandname("rfc3978_5_4_p1_u4748") " paragraph was found, but not on the first page, as suggested." ); + # } + # + if (hyphens && ! is_rfc) { + warnc(sprintf("There %s %d instance%s of lines with hyphenated line breaks in the document.", (hyphens == 1 ? "is" : "are"), hyphens, (hyphens == 1 ? "" : "s"))) + } + if (misspelled_toc) { + warnc("The \"Table of Contents\" section title seems to be misspelled.") + } + if (misspelled_addr) { + warnc("The \"Author's Address\" (or \"Authors' Addresses\") section title is misspelled.") + } + if (! option_verbose && spacing) { + for (i = 1; i <= 5; i++) { + if (i in sp_line) { + warnc(sprintf("Line %d has weird spacing: '...%s...'", linenum[i], extract[i])) + } + } + if (spacing > 5) { + warnc(sprintf("(%d more instance%s...)", spacing - 5, (spacing - 5 == 1 ? "" : "s"))) + } + } + if (keywords && ! has["rfc2119_p2"] && ! has["rfc2119_p2a"] && ! has["rfc8174_p11"] && found_2119_ref) { + sectionwarn("rfc8174_p11", "the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords") + note("(The document does seem to have the reference to RFC 2119 which the ID-Checklist requires).") + } + if (keywords && ! has["rfc2119_p2"] && has["rfc2119_p2a"] && ! has["rfc8174_p11"]) { + # Require that the reference used in "rfc2119_p2a" actually mentions RFC 2119... + if (ref_text[reftag2119] !~ /RFC[- ]?2119/) { + errg(sprintf("The document contains RFC2119-like boilerplate, but doesn't seem to mention RFC 2119. The boilerplate contains a reference [%s], but that reference does not seem to mention RFC 2119 either.", reftag2119)) + } + } + if (has_not_recommended && (has["rfc2119_p2"] || has["rfc2119_p2a"] || has["rfc8174_p11"]) && ! rfc2119_p2_not_recommended) { + warnc("The document seems to use 'NOT RECOMMENDED' as an RFC 2119 keyword, but does not include the phrase in its RFC 2119 key words list.") + } + if (! keywords) { + if (has["rfc2119_p2"] || has["rfc2119_p2a"] || has["rfc8174_p11"]) { + warnc("The document doesn't use any RFC 2119 keywords, yet seems to have RFC 2119 boilerplate text.") + } else if (almost_boilerplate["rfc2119_p2"] || almost_boilerplate["rfc2119_p2a"] || almost_boilerplate["rfc8174_p11"]) { + warnc("The document doesn't use any RFC 2119 keywords, yet has text resembling RFC 2119 boilerplate text.") + } + } + for (combo in rfc2119undefined) { + comment("The exact meaning of the all-uppercase expression '" combo "' is not defined in RFC 2119. If it is intended as a requirements " "expression, it should be rewritten using one of the combinations " "defined in RFC 2119; otherwise it should not be all-uppercase.") + } + for (bad_line in found_bad_pat) { + pattern = found_bad_pat[bad_line] + para = found_bad_para[bad_line] + warn(bad[pattern] "\n\n Found '" strip(pattern) "' in this paragraph:\n\n " para) + } + if (! (intended_status in status2code)) { + warn(sprintf("Unrecognized Status in '%s', assuming Proposed Standard", intended_status_text)) + note("(Expected one of 'Standards Track', 'Full Standard', 'Draft Standard', 'Proposed Standard', 'Best Current Practice', 'Informational', 'Experimental', 'Informational', 'Historic'.)\n") + intended_status = "proposed standard" + } + # The 'RFC 5378 fix' announced around 5 Feb 2009 means that drafts first + # submitted before 10 Nov 2008 with a high probability should have an additional + # boilerplate paragraph excempting it from full 5378 compliance. On the other + # hand, a draft first submitted on or after 10 Nov 2008 should probably not have + # such a paragraph. + if (has_docname) { + docname = full_docname + } else { + docname = file_docname + } + sub(/-[0-9][0-9](\.txt)?$/, "", docname) + get_state(docname, docstate, 1) + if ("creationdate" in docstate) { + created = docstate["creationdate"] + } + if ("created" in docstate) { + created = docstate["created"] + } + for (i in obsoletes) { + if (i !~ /draft-/) { + continue + } + refcreated = get_creation_date("rfc" i) + if (refcreated && jdn(refcreated) < jdn(created) && jdn(refcreated) < jdn("2008-11-10")) { + created = refcreated + refcreated = "" + note(sprintf("(Using the creation date from RFC%i, obsoleted by this document, for RFC5378 checks: %s)\n", i, created)) + } + } + for (i in updates) { + if (i ~ /draft-/) { + continue + } + refcreated = get_creation_date("rfc" i) + if (refcreated && jdn(refcreated) < jdn(created) && jdn(refcreated) < jdn("2008-11-10")) { + created = refcreated + refcreated = "" + note(sprintf("(Using the creation date from RFC%i, updated by this document, for RFC5378 checks: %s)\n", i, created)) + } + } + # for (key in docstate) { + # printf("docstate[%s]: %s\n", key, docstate[key]); + # } + if (created ~ /[12][0-9][0-9][0-9]-[01][0-9]-[0123][0-9]/) { + if (jdn(created) < jdn("2008-11-10")) { + if (! has["trust-28-dec-2009_6_c_iii"]) { + sectioncomment("trust-28-dec-2009_6_c_iii", "disclaimer for pre-RFC5378 work, but may have content which was first " "submitted before 10 " "November 2008. If you have contacted all the original authors and they " "are all willing to grant the BCP78 rights to the IETF Trust, then this " "is fine, and you can ignore this comment. If not, you may need to add " "the pre-RFC5378 disclaimer. (See the Legal Provisions document at " "https://trustee.ietf.org/license-info for more information.)") + } else { + comment("The document seems to contain a disclaimer for pre-RFC5378 work, and " "may have content which was first submitted before 10 November 2008. " "The disclaimer is necessary when " "there are original authors that you have been unable to contact, or " "if some do not wish to grant the BCP78 rights to the IETF Trust. If " "you are able to get all authors (current and original) to grant those " "rights, you can and should remove the disclaimer; otherwise, the " "disclaimer is needed and you can ignore this comment. " "(See the Legal Provisions document at https://trustee.ietf.org/license-info " "for more information.)") + } + } else { # document created on or after 2008-11-10 + if (has["trust-28-dec-2009_6_c_iii"]) { + warn("The document seems to contain a disclaimer for pre-RFC5378 work, but was " "first submitted on or after 10 November 2008. The disclaimer is usually " "necessary only for documents that revise or obsolete older RFCs, and " "that take significant amounts of text from those RFCs. If you can " "contact all authors of the source material and they are willing to " "grant the BCP78 rights to the IETF Trust, you can and should remove " "the disclaimer. Otherwise, the disclaimer is needed and you can " "ignore this comment. (See the Legal Provisions document at " "https://trustee.ietf.org/license-info for more information.)") + } else { + # No comment for documents created after 2008-11-10 without a disclaimer + } + } + } else { + warn("Couldn't figure out when the document was first submitted -- there may comments " "or warnings related to the use of a disclaimer for pre-RFC5378 work that could " "not be issued because of this. Please check the Legal Provisions document at " "https://trustee.ietf.org/license-info to determine if you need the pre-RFC5378 " "disclaimer.") + } + if (doc_date) { + days_off = doc_date - jdn(today) + if (days_off > date_skew) { + comment(sprintf("The document date (%s) is %s days in the future. Is this intentional?", date_lit, days_off)) + } + if (days_off < -date_skew) { + comment(sprintf("The document date (%s) is %s days in the past. Is this intentional?", date_lit, -days_off)) + } + } else { + comment("Couldn't find a document date in the document -- date freshness check skipped.") + } + if (code_comment_found) { + comment("Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines.") + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + } + announce("Checking references for intended status: " (code2status[status2code[intended_status]] ? code2status[status2code[intended_status]] : "None")) + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + warnshere = warnings + intended_code = status2code[intended_status] + split(warncodes[intended_code], warnlist, FS) + for (i in warnlist) { + warnlist[warnlist[i]] + } + std_codes["B"] + std_codes["P"] + std_codes["D"] + std_codes["S"] + if (intended_code in std_codes) { + note("(See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs)\n") + } + for (i = 1; i <= ref_use_count; i++) { + tag = ref_use_list[i] + if (! (tag in ref_def)) { + is_numeric = tag ~ /^[0-9]+$/ + if ((is_numeric && has_numeric_refs) || (! is_numeric && has_symbolic_refs)) { + warnc(sprintf("Missing Reference: '%s' is mentioned on line %s, but not defined", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) + miss_ref[tag] + check_downref(tag, warnlist) + } else if (has_numeric_refs || has_symbolic_refs) { + comment(sprintf("Looks like a reference, but probably isn't: '%s' on line %s", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) + } else { + comment(sprintf("Missing reference section? '%s' on line %s looks like a reference", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) + } + } + } + for (i = 1; i <= ref_def_count; i++) { + tag = ref_def_list[i] + if (! (tag in ref_use)) { + warnc(sprintf("Unused Reference: '%s' is defined on line %s, but no explicit reference was found in the text", tag, ref_def[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_def[tag]], 1, 68))) : "")) + } + } + for (i = 1; i <= ref_def_count; i++) { + tag = ref_def_list[i] + check_downref(tag, warnlist) + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + } + } + # -------------------------------------------------------------- + # Summary + if (errors == 0 && warnings == 0 && comments == 0) { + print "" + note("No nits found.") + } else { + print "" + note(sprintf("Summary: %d error%s (%s), %d flaw%s (%s), %d warning%s (%s), %d comment%s (%s).", errors, (errors == 1 ? "" : "s"), errmark, flaws, (flaws == 1 ? "" : "s"), flawmark, warnings, (warnings == 1 ? "" : "s"), warnmark, comments, (comments == 1 ? "" : "s"), infomark)) + if (! option_verbose && ! option_submitcheck) { + print "" + note("Run idnits with the --verbose option for more detailed information about the items above.") + } + } + } +} + +# ---------------------------------------------------------------------- +# rindex(str, find) +# +function rindex(str, find, start, pos, incr, i) +{ + start = 0 + pos = 0 + incr = length(find) + while (1) { + i = index(str, find) + if (i == 0) { + return pos + } + pos = start + i + str = substr(str, i + incr) + start = start + i + incr - 1 + } +} + +function sectioncomment(name, str) +{ + sectionerr(name, str, 3) +} + +# ---------------------------------------------------------------------- +# sectionerr(name, str) +# +function sectionerr(name, str, wflag) +{ + if (! name in has) { + print "?? internal error, expected a table match on %s", name + exit + } + if (str ~ /^the /) { + str = "The document seems to lack " str + } else if (str ~ /^[aeiouyAEIOUYRH]/) { + str = "The document seems to lack an " str + } else { + str = "The document seems to lack a " str + } + if (name in almost_boilerplate) { + str = str " -- however, there's a paragraph with a matching beginning. Boilerplate error?" + } else if (str !~ /(\.|\.\))$/) { + str = str ". " + } + if (wflag == 3) { + comment(str) + } else if (wflag == 2) { + warn(str) + } else if (wflag == 1) { + flaw(str) + } else { + err(str) + } + if ((option_verbose || option_submitcheck) && option_pass2) { + showsection(name) + } +} + +function sectionflaw(name, str) +{ + sectionerr(name, str, 1) +} + +function sectionwarn(name, str) +{ + sectionerr(name, str, 2) +} + +# ---------------------------------------------------------------------- +# showalmost(name) +# +function showalmost(name, orig) +{ + p2 = almost_boilerplate[name] + p2 = fold(p2, " ", bpcols) + p2 = sprintf(" %s\n\n", p2) + if (orig) { + p2 = markdiff(orig, p2) + } + printf (p2) +} + +# ---------------------------------------------------------------------- +# showsection(name) +# +function showsection(name, suppress, initial, final) +{ + p = bp[name] + "date +'%Y'" | getline year + # Get rid of regexp stuff in the boilerplate text we show the user: + # - mark metacharacters with mark character "!" + gsub(/[()|?+*^$]/, "!&", p) + # - get rid of mark preceeded by escape char... + gsub(/\\!/, "", p) + # - get rid of alternates, keeping the first only + gsub(/!\|[^)]*!\)/, "", p) + # - and we can get rid of metacharacters not preceeded by escape char + gsub(/![\(\)?+*^$]/, "", p) + # and also of escape chars themselves + gsub(/\\/, "", p) + # - also say "year" instead of "[0-9]" + ##gsub(/\[0-9\]/, "", p); + gsub(/\[0-9\]\[0-9\]\[0-9\]\[0-9\]/, year, p) + if (suppress < 2) { + note(initial expandname(name) final ":") + } + p1 = fold(p, " ", bpcols) + p1 = sprintf(" %s", p1) + printf (p1) + if (name in almost_boilerplate && suppress == 0) { + note("\n\n ... text found in draft:") + showalmost(name, p1) + print "" + } else { + print "\n" + } +} + +# ---------------------------------------------------------------------- +# strip() +# +function strip(str) +{ + sub(/^[ \t\f\r]+/, "", str) + sub(/[ \t\f\r]+$/, "", str) + return str +} + +# ---------------------------------------------------------------------- +# update_references(line, pos) +# +function update_references(this, pos) +{ + if (! match(this, /\[Page/)) { + nnnote(sprintf("update_references( %s)\n", this)) + if (match(this, "(^|[\\]A-Za-z0-9 \t.()])" reference_format "\\)?([) \t,;:.?[]|$)")) { + line[pos] = this + if (in_refs && this ~ ("^ *([0-9.]+ *)?" reference_format)) { + # Reference definitions + match(this, reference_format) + reftag = substr(this, RSTART + 1, RLENGTH - 2) + numrefs = split(reftag, reftags, /, +/) + for (i = 1; i <= numrefs; i++) { + reftag = reftags[i] + ref_def[reftag] = pos + if (! (reftag in ref_def_seen)) { + ref_def_seen[reftag] + ref_def_list[++ref_def_count] = reftag + } + if (reftag ~ /^[0-9]+$/) { + has_numeric_refs = 1 + } else { + has_symbolic_refs = 1 + } + if (option_pass2) { + nnnote(sprintf("\tref_def[%s] at %s: %s\n", reftag, pos, this)) + } + ref_text[reftag] = this + if (in_normref) { + ref_norm[reftag] + } + } + } else { + # Reference usage + while (match(this, reference_format)) { + reftag = substr(this, RSTART + 1, RLENGTH - 2) + numrefs = split(reftag, reftags, /, +/) + for (i = 1; i <= numrefs; i++) { + tags = substr(this, RSTART + 1, RLENGTH - 2) + split(tags, reftags, /(,|, )/) + for (i in reftags) { + reftag = reftags[i] + ref_use[reftag] = pos + if (! (reftag in ref_use_seen)) { + ref_use_seen[reftag] + ref_use_list[++ref_use_count] = reftag + } + if (option_verbose > 2 && option_pass2) { + printf "\tref_use[%s] = %s\n", reftag, pos + } + } + this = substr(this, RSTART + RLENGTH) + } + } + } + } else if (option_verbose && option_pass1) { + match(this, /\[[0-9A-Z-]+\]/) + printf "%s(%d): Unexpected reference format: '...%s...'\n", FILENAME, pos, substr(this, RSTART - 5, RLENGTH + 10) + if (option_verbose > 1) { + printf " --> %s\n", this + printf " %*s\n", RSTART, "^" + } + } + } +} + +# ---------------------------------------------------------------------- +# usage() +# +function usage() +{ + print "" "Usage: idnits [options] filename\n" "\n" " Options:\n" "\t--version\tPrint the version and exit\n" "\t--help\t\tPrint this text and exit\n" "\t--nowarn\tDon't issue warnings, only ID-Checklist violations\n" "\t--verbose\tShow more information about offending lines\n" "\t--nitcount\tShow a count of nits\n" "\t--debug\t\tDebug output, especially of boilerplate matching\n" "\t--year NNNN\tExpect the given year in the boilerplate\n" "\t--checklistwarn\tOnly warn (no errors) for ID-Checklist violations\n" "\t--nonascii\tDisable warnings for non-ascii characters\n" "\t--submitcheck\tOnly output errors and warnings related to 1id-guidelines\n" "\t--status doctype Assume the given intended document type\n" "" +} + +# ---------------------------------------------------------------------- +# warn() +# +function warn(str, indented) +{ + if (option_warn) { + print fold(" " warnmark " " str, " ", columns) + if (indented) { + print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) + print fold(" '" indented "' )", " ", columns) + } + print "" + warnings++ + } +} + +# ---------------------------------------------------------------------- +# warnc() +# +# Warnings which are IESG checlist warnings, but not submission warnings +function warnc(str, indented) +{ + if (! option_submitcheck) { + warn(str, indented) + } +} + EOF $AWK -v statusdir="$statusdir" -v statusfile="$statusfile" -v obslist="$obslist" -v exclist="$exclist" -v today="$today" -f $program $* From 43f0cce5832dd64221ba7b72cf998e064bcea477 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Wed, 23 Oct 2024 11:32:18 -0500 Subject: [PATCH 2/8] fix: replace tab indents with two spaces --- idnits | 5260 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 2630 insertions(+), 2630 deletions(-) diff --git a/idnits b/idnits index 717a71d..c954bea 100755 --- a/idnits +++ b/idnits @@ -248,1149 +248,1149 @@ checknits() { cat << 'EOF' > $program BEGIN { - option_verbose = 0 - option_warn = 1 - option_nonascii = 0 - split(ENVIRON["CHECKNITS"], argv, FS) - columns = ENVIRON["COLUMNS"] - if (! columns) { - columns = 78 - } - if (columns > 80) { - columns = 80 - } - if (columns < 16) { - columns = 16 - } - if (columns < 73) { - bpcols = columns - } else { - bpcols = 73 - } - indentation = 8 - errmark = "**" - flawmark = "~~" - warnmark = "==" - infomark = "--" - notemark = " " - for (i in argv) { - # Deprecated - if (argv[i] == "--rfc3667") { - printf "\nOption %s does nothing any more\n", argv[i] - argv[i] = "" - } - if (argv[i] == "--no3667") { - printf "\nOption %s does nothing any more\n", argv[i] - argv[i] = "" - } - if (argv[i] == "--rfc2026") { - printf "\nOption %s does nothing any more\n", argv[i] - argv[i] = "" - } - if (argv[i] == "--nowarn") { - option_warn = 0 - argv[i] = "" - } - if (argv[i] == "--filename") { - option_filename = argv[i + 1] - argv[i] = "" - argv[i + 1] = "" - } - if (argv[i] == "--debug") { - option_debug = 1 - argv[i] = "" - } - if (argv[i] == "--nitcount") { - option_nitcount = 1 - argv[i] = "" - } - if (argv[i] == "--pass1") { - option_pass1 = 1 - argv[i] = "" - } - if (argv[i] == "--verbose") { - option_verbose++ - argv[i] = "" - } - if (argv[i] == "--list-matches") { - option_list_matches = 1 - argv[i] = "" - } - if (argv[i] == "--year") { - option_year = argv[i + 1] - argv[i] = "" - argv[i + 1] = "" - } - if (argv[i] == "--checklistwarn") { - option_checklistwarn++ - argv[i] = "" - } - if (argv[i] == "--submitcheck") { - option_submitcheck++ - argv[i] = "" - } - if (argv[i] == "--status") { - option_status = argv[i + 1] - argv[i] = "" - argv[i + 1] = "" - } - if (argv[i] == "--nonascii") { - option_nonascii = 1 - argv[i] = "" - } - if (argv[i] == "--ascii") { - option_nonascii = 0 - argv[i] = "" - } - if (argv[i] == "--") { - argv[i] = "" - } - if (argv[i] ~ "^-.+") { - printf "\nUnknown option: %s\n\n", argv[i] - usage() - exit 1 - } - if (argv[i] ~ "^--.+") { - printf "\nUnknown option: %s\n\n", argv[i] - usage() - exit 1 - } - } - option_pass2 = ! option_pass1 - split("SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US", controlchar, FS) - for (i in controlchar) { - controlchar[sprintf("%c", i + 0)] = controlchar[i] - delete controlchar[i] - } - split("January February March April May June July August September October November December", monthnames, FS) - for (i in monthnames) { - mn = monthnames[i] - month[mn] = i - month[substr(mn, 1, 3)] = i - } - doc_date = 0 - # Extract a list of hyphenated words from the document, and build an array of valid fragments - if (length(option_filename)) { - cmd = sprintf("cat %s | sed 's/[^A-Za-z0-9_-]/\\n/g' | sort | uniq | egrep -- '-' | egrep -v -- '-$' | egrep '^[A-Za-z0-9]'", option_filename) - while ((cmd | getline) > 0) { - word = $0 - frag = "" - for (;;) { - if (length(word) == 0) { - break - } - pos = index(word, "-") - if (pos == 0) { - break - } - frag = frag substr(word, 1, pos) - hyphenfrags[frag] - has_hyphenlist = 1 - word = substr(word, pos + 1) - } - } - } - # get current year - if (option_year > 1990) { - year = option_year - } else if (("date +'%Y'" | getline year) <= 0) { - year = "[0-9]+" - } - # establish the format we expect references to have, for later use - has_refs = 0 - one_ref_format = "(([0-9A-Z-]|I-?D.)[0-9A-Za-z-]*( [0-9A-Z-]+)?|(IEEE|ieee)[A-Za-z0-9.-]+|(ITU ?|ITU-T ?|G\\.)[A-Za-z0-9.-]+)" - reference_format = "\\[" one_ref_format "(, ?" one_ref_format ")*\\]" - abnf_rule_format = "^ +([A-Za-z0-9-]+ *=|;).*" - imap_rule_format = "^ *S: (\\*|[A-Za-z0-9]+) (OK|NO|BAD|PREAUTH|BYE) \\[[-A-Za-z]+\\]" - code_start_format = "()" - code_end_format = "()" - inline_code_format = "(/\\*|\\*/|^ *#)" - # read obsoleted RFC information from file - if (obslist) { - while ((getline < obslist) > 0) { - oldrfc = $1 - $1 = "" - obsoleted[oldrfc] = $0 - } - } else { - obsoleted[""] = "" - } - # read the rfc status information from file - if (statusfile) { - while ((getline < statusfile) > 0) { - rfcstatus = rfcstatus $0 - } - } else { - rfcstatus = "" - } - # read exception RFC information from file - if (exclist) { - while ((getline < exclist) > 0) { - exception[$1] = $1 - } - } else { - exception[""] = "" - } - status2code["bcp"] = "B" - status2code["best current"] = "B" - status2code["best current practice"] = "B" - status2code["experimental"] = "E" - status2code["experimental track"] = "E" - status2code["informational"] = "I" - status2code["ps"] = "P" - status2code["proposed standard"] = "P" - status2code["proposed standards"] = "P" - status2code["standards track"] = "P" - status2code["standard track"] = "P" - status2code["ds"] = "D" - status2code["draft standard"] = "D" - status2code["standard"] = "S" - status2code["full standard"] = "S" - status2code["historic"] = "H" - status2code["not issued"] = "N" - code2status["O"] = "Obsolete" - code2status["U"] = "Unknown state" - code2status["E"] = "Experimental" - code2status["I"] = "Informational" - code2status["B"] = "Best Current Practice" - code2status["P"] = "Proposed Standard" - code2status["D"] = "Draft Standard" - code2status["S"] = "Full Standard" - code2status["H"] = "Historic" - code2status["N"] = "Not Issued" - warncodes["H"] = "N" - warncodes["E"] = "N O" - warncodes["I"] = "N O" - warncodes["B"] = "N E I O U H" - warncodes["P"] = "N E I O U H" - warncodes["D"] = "N E I O U H P" - warncodes["S"] = "N E I P U H P D" - split("B P D S", ietfstreamcodes, FS) - has[""] # make sure this exists as a global variable here - seen_ref[""] - miss_ref[""] - # ------------------------------------------------------------------ - # 3978 and 3979 section texts - # - bp["any_text"] = ".*" - bp["rfc3667_3_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of (S|s)ection 3 of( | \\])RFC( |.?)(3667|3667\\])\\.$" - bp["rfc3667_5_1"] = "By submitting this Internet-Draft, (I|we) certify that any applicable " "patent or other IPR claims of which (I am|we are) aware have been disclosed,( or " "will be disclosed,)? and any of which (I|we) become aware will be disclosed, " "in accordance with RFC 3668.$" - bp["rfc3978_5_1"] = "By submitting this Internet-Draft, each author represents that any " "applicable patent or other IPR claims of which he or she is aware " "have been or will be disclosed, and any of which he or she becomes " "aware will be disclosed, in accordance with Section 6 of BCP 79.$" - bp["rfc3978_5_1_a"] = "By submitting this Internet-Draft, (each|the) author represents that any " "applicable patent or other IPR claims of which (he or she|he|she) is aware " "have been or will be disclosed, and any of which (he or she|he|she) becomes? " "aware will be disclosed, in accordance with( (S|s)ection 6 of)? (BCP 79|RFC 3979|RFC 3668).$" - bp["rfc3978_5_2a"] = "This document may not be modified, and derivative works of it may " "not be created, except to publish it as an RFC and to translate it " "into languages other than English\\.$" - bp["rfc3978_5_2ax"] = "This document may not be modified, and derivative works of it may " "not be created, except to publish it as an RFC and to translate it " "into languages other than English other than to extract section " "[0-9.]+ as-is for separate use\\.$" - bp["rfc3978_5_2b"] = "This document may not be modified, and derivative works of it may " "not be created\\.$" - bp["rfc3978_5_2bx"] = "This document may not be modified, and derivative works of it may " "not be created other than to extract section [0-9.]+ as-is for separate use.$" - bp["rfc3978_5_3"] = "This document may only be posted in an Internet-Draft.$" - bp["rfc3978_5_4_p1"] = "Copyright \\(C\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?.$" - bp["rfc3978_5_4_p1_u4748"] = "Copyright \\(C\\) The IETF Trust \\(?[0-9][0-9][0-9][0-9]\\)?.$" - bp["rfc3978_5_4_p1_e"] = ".+Copyright \\(C\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?\\..+" - bp["rfc3978_5_4_p1_u4748_e"] = ".+Copyright \\(C\\) The IETF Trust \\(?[0-9][0-9][0-9][0-9]\\)?\\..+" - bp["rfc3978_5_4_p1_now"] = sprintf("Copyright \\(C\\) The Internet Society \\(?%s\\)?", year) - bp["rfc3978_5_4_p1_u4748_now"] = sprintf("Copyright \\(C\\) The IETF Trust \\(?%s\\)?", year) - bp["trust-16-oct-2008_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors", year) - bp["trust-12-feb-2009_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors", year) - bp["trust-12-sep-2009_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors.", year) - bp["trust-28-dec-2009_6_b_i_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors.", year) - # ---------------------------------------------------------------------------------------------- - bp["rfc3978_5_4_p2"] = "This document is subject to the rights, licenses and restrictions contained in BCP " "78, and except as set forth therein, the authors retain all their rights.$" - bp["rfc3978_5_5"] = "This document and the information contained herein are provided " "on an \"AS IS\" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE " "REPRESENTS OR IS SPONSORED BY \\(IF ANY\\), THE INTERNET SOCIETY AND " "THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, " "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT " "THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR " "ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" - bp["rfc3978_5_5_u4748"] = "This document and the information contained herein are provided " "on an \"AS IS\" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE " "REPRESENTS OR IS SPONSORED BY \\(IF ANY\\), THE INTERNET SOCIETY, THE IETF TRUST AND " "THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, " "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT " "THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR " "ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" - bp["rfc3979_5_p1"] = "The IETF takes no position regarding the validity or scope of any " "Intellectual Property Rights or other rights that might be claimed " "to pertain to the implementation or use of the technology " "described in this document or the extent to which any license " "under such rights might or might not be available; nor does it " "represent that it has made any independent effort to identify any " "such rights. Information on the procedures with respect to rights " "in RFC documents can be found in BCP 78 and BCP 79.$" - bp["rfc3979_5_p2"] = "Copies of IPR disclosures made to the IETF Secretariat and any " "assurances of licenses to be made available, or the result of an " "attempt made to obtain a general license or permission for the use " "of such proprietary rights by implementers or users of this " "specification can be obtained from the IETF on-line IPR repository " "at https?://www.ietf.org/ipr.$" - bp["rfc3979_5_p3"] = "The IETF invites any interested party to bring to its attention " "any copyrights, patents or patent applications, or other " "proprietary rights that may cover technology that may be required " "to implement this standard. Please address the information to the " "IETF at ietf-ipr@ietf.org.$" - # ---------------------------------------------------------------------------------------------- - bp["trust-16-oct-2008_6_a"] = "This Internet-Draft is submitted to IETF in full " "conformance with the provisions of BCP 78 and BCP 79\\.$" - bp["trust-16-oct-2008_6_b_p2"] = "Copyright \\(c\\) [0-9][0-9][0-9][0-9] IETF Trust and " "the persons identified as the document authors\\. All rights reserved\\.$" - bp["trust-16-oct-2008_6_b_p3"] = "This document is subject to BCP 78 and the " "IETF Trust's Legal Provisions Relating to IETF Documents " "\\(http://trustee.ietf.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document. " "Please review these documents " "carefully, as they describe your rights and restrictions with respect to " "this document\\.$" - bp["trust-16-oct-2008_6_c_i"] = "This document may not be modified, and derivative " "works of it may not be created, except to format it for publication " "as an RFC and to translate it into languages other than English\\.$" - # ---------------------------------------------------------------------------------------------- - bp["trust-12-feb-2009_6_a"] = bp["trust-16-oct-2008_6_a"] - bp["trust-12-feb-2009_6_b_p2"] = bp["trust-16-oct-2008_6_b_p2"] - bp["trust-12-feb-2009_6_b_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal " "Provisions Relating to IETF Documents in effect on the date of " "publication of this document \\(http://trustee.ietf.org/license-inf(o|o/)\\)\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" - bp["trust-12-feb-2009_6_c_i"] = "This document may not be modified, and derivative " "works of it may not be created, except to format it for publication " "as an RFC or to translate it into languages other than English\\.$" - bp["trust-12-feb-2009_6_c_ii"] = "This document may not be modified, and " "derivative works of it may not be created, and it may not be published " "except as an Internet-Draft\\.$" - bp["trust-12-feb-2009_6_c_iii"] = "This document may contain material from IETF Documents or IETF " "Contributions published or made publicly available before November " "10, 2008\\. The person\\(s\\) controlling the copyright in some of this " "material may not have granted the IETF Trust the right to allow " "modifications of such material outside the IETF Standards Process\\. " "Without obtaining an adequate license from the person\\(s\\) " "controlling the copyright in such materials, this document may not " "be modified outside the IETF Standards Process, and derivative " "works of it may not be created outside the IETF Standards Process, " "except to format it for publication as an RFC or to translate it " "into languages other than English\\.$" - # ---------------------------------------------------------------------------------------------- - bp["trust-12-sep-2009_6_a"] = bp["trust-12-feb-2009_6_a"] - bp["trust-12-sep-2009_6_b_p2"] = bp["trust-12-feb-2009_6_b_p2"] - bp["trust-12-sep-2009_6_c_i"] = bp["trust-12-feb-2009_6_c_i"] - bp["trust-12-sep-2009_6_c_ii"] = bp["trust-12-feb-2009_6_c_ii"] - bp["trust-12-sep-2009_6_c_iii"] = bp["trust-12-feb-2009_6_c_iii"] - bp["trust-12-sep-2009_6_b_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal " "Provisions Relating to IETF Documents \\(https?://trustee.ietf.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "(Simplified|Revised) BSD License text as described in Section 4.e of the " "Trust Legal Provisions and are provided without warranty as described " "in the BSD License\\.$" - # ---------------------------------------------------------------------------------------------- - bp["trust-28-dec-2009_6_b_i_p2"] = bp["trust-12-sep-2009_6_b_p2"] - bp["trust-28-dec-2009_6_c_i"] = bp["trust-12-sep-2009_6_c_i"] - bp["trust-28-dec-2009_6_c_ii"] = bp["trust-12-sep-2009_6_c_ii"] - bp["trust-28-dec-2009_6_c_iii"] = bp["trust-12-sep-2009_6_c_iii"] - bp["trust-28-dec-2009_6_a"] = "This Internet-Draft is submitted in full " "conformance with the provisions of BCP 78 and BCP 79\\.$" - # This applies to the IETF stream - bp["trust-28-dec-2009_6_b_i_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "(Simplified|Revised) BSD License text as described in Section 4.e of the " "Trust Legal Provisions and are provided without warranty as described " "in the (Simplified|Revised) BSD License\\.$" - # This applies to non-IETF streams - bp["trust-28-dec-2009_6_b_ii_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" - # ---------------------------------------------------------------------------------------------- - bp["rfc2026_10_4A"] = "The IETF takes no position regarding the validity or scope of " "any intellectual property or other rights that might be claimed " "to pertain to the implementation or use of the technology " "described in this document or the extent to which any license " "under such rights might or might not be available; neither does " "it represent that it has made any effort to identify any such " "rights. Information on the IETF's procedures with respect to " "rights in standards-track and standards-related documentation " "can be found in BCP-11. Copies of claims of rights made " "available for publication and any assurances of licenses to " "be made available, or the result of an attempt made " "to obtain a general license or permission for the use of such " "proprietary rights by implement[oe]rs or users of this " "specification can be obtained from the IETF Secretariat.$" - bp["rfc2026_10_4B"] = "The IETF invites any interested party to bring to its " "attention any copyrights, patents or patent applications, or " "other proprietary rights which may cover technology that may be " "required to practice this standard. Please address the " "information to the IETF Executive Director.$" - bp["rfc2026_10_4C_p1"] = "Copyright \\([Cc]\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?. All Rights " "Reserved.$" - bp["rfc2026_10_4C_p2"] = "This document and translations of it may be copied and " "furnished to others, and derivative works that comment on or " "otherwise explain it or assist in its implementation may be " "prepared, copied, published and distributed, in whole or in " "part, without restriction of any kind, provided that the above " "copyright notice and this paragraph are included on all such " "copies and derivative works. However, this document itself may " "not be modified in any way, such as by removing the copyright " "notice or references to the Internet Society or other Internet " "organizations, except as needed for the purpose of developing " "Internet standards in which case the procedures for copyrights " "defined in the Internet Standards process must be followed, or " "as required to translate it into languages other than English.$" - bp["rfc2026_10_4C_p3"] = "The limited permissions granted above are perpetual and will " "not be revoked by the Internet Society or its successors or " "assign(ee)?s.$" - bp["rfc2026_10_4C_p4"] = "This document and the information contained herein is provided " "on an \"AS IS\" basis and THE INTERNET SOCIETY AND THE INTERNET " "ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR " "IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE " "OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY " "IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" - bp["rfc2026_10_4D"] = "The IETF has been notified of intellectual property rights " "claimed in regard to some or all of the specification contained " "in this document. For more information consult the online list " "of claimed rights.$" - bp["rfc2026_claim"] = "This document is an Internet-Draft and is in full conformance " "with all provisions of Section 10 of( | \\])RFC( |.?)(2026|2026\\])\\." - bp["rfc2026_lax_claim"] = "This document is an Internet-Draft and is in full conformance " "with all provisions of Section 10 of( | \\])RFC( |.?)(2026|2026\\])( ?\\[[0-9]+\\].*)?." - bp["rfc2026b_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of Section 10 of( | \\])RFC( |.?)(2026|2026\\])\\." - bp["rfc2026b_lax_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of Section 10 of( | \\])RFC( |.?)(2026|2026\\])( ?\\[[0-9]+\\].*)?." - bp["rfc3978_3_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of (S|s)ection 3 of( | \\])RFC( |.?)(3978|3978\\])\\.$" - bp["rfc2119_p2"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", " "\"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\",( | \"NOT RECOMMENDED\", )\"MAY\", " "and \"OPTIONAL\" in this document are to be interpreted as described in" "( | \\[| BCP 14, | BCP 14, \\[)RFC( |.?)2119(\\.|.*\\.|\\].*\\.)$" - bp["rfc2119_p2a"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", " "\"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\",( | \"NOT RECOMMENDED\", )\"MAY\", " "and \"OPTIONAL\" in this document are to be interpreted as described in " "(['\"]?Key words for use in RFCs to Indicate Requirement Levels['\"]? )?" "\\[[0-9A-Z-][0-9A-Za-z-]* ?[0-9A-Z-]*\\].*\\.$" - # This is from RFC 8174 which updates 2119: - bp["rfc8174_p11"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL " "NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"NOT RECOMMENDED\", " "\"MAY\", and \"OPTIONAL\" in this document are to be interpreted as " "described in BCP 14 \\[RFC2119\\] ?\\[RFC8174\\] when, and only when, they " "appear in all capitals, as shown here." - bp["1id_guidelines_p1"] = "Internet-Drafts are working documents of the Internet Engineering " "Task Force \\(IETF\\), its areas, and its working groups. Note that other " "groups may also distribute working documents as Internet-Drafts.$" - bp["1id_guidelines_p1a"] = "Internet-Drafts are working documents of the Internet Engineering " "Task Force \\(IETF\\). Note that other groups may also distribute " "working documents as Internet-Drafts. The list of current " "Internet-Drafts is at https?://datatracker.ietf.org/drafts/current/? ?\\.$" - bp["1id_guidelines_p2"] = "Internet-Drafts are draft documents valid for a maximum of six months " "and may be updated, replaced, or obsoleted by other documents at any " "time. It is inappropriate to use Internet-Drafts as reference " "material or to cite them other than as \"?work in progress(\\.\"|\"?\\.)$" - bp["1id_guidelines_p2a"] = "Internet-Drafts are draft documents valid for a maximum of six months " "and may be updated, replaced, or obsoleted by other documents at any " "time. It is inappropriate to use Internet-Drafts as reference " "material or to cite them other than as \"?work in progress(\\.\"|\"?\\.)$" - bp["1id_guidelines_p3"] = "The list of current Internet-Drafts can be accessed at " "https?://www.ietf.org/1id-abstracts.html$" - bp["1id_guidelines_p3a"] = "The list of current Internet-Drafts can be accessed at:? " "https?:// *www.ietf.org/ *(ietf/)?1id-abstracts.(txt|html) ?\\.?$" - bp["1id_guidelines_p4"] = "The list of Internet-Draft Shadow Directories can be accessed at " "https?://www.ietf.org/shadow.html$" - bp["1id_guidelines_p4a"] = "The list of Internet-Draft Shadow Directories can be accessed at:? " "https?:// *www.ietf.org/ *shadow.html ?\\.?$" - bad["MUST not"] = "Using lowercase 'not' together with uppercase 'MUST', " "'SHALL', 'SHOULD', or 'RECOMMENDED' is not an " "accepted usage according to RFC 2119. Please use uppercase 'NOT' " "together with RFC 2119 keywords (if that is what you mean)." - bad["SHALL not"] = bad["MUST not"] - bad["SHOULD not"] = bad["MUST not"] - bad["not RECOMMENDED"] = bad["MUST not"] - bad["MAY NOT"] = "The expression 'MAY NOT', while looking like RFC 2119 requirements " "text, is not defined in RFC 2119, and should not be used. Consider " "using 'MUST NOT' instead (if that is what you mean)." + option_verbose = 0 + option_warn = 1 + option_nonascii = 0 + split(ENVIRON["CHECKNITS"], argv, FS) + columns = ENVIRON["COLUMNS"] + if (! columns) { + columns = 78 + } + if (columns > 80) { + columns = 80 + } + if (columns < 16) { + columns = 16 + } + if (columns < 73) { + bpcols = columns + } else { + bpcols = 73 + } + indentation = 8 + errmark = "**" + flawmark = "~~" + warnmark = "==" + infomark = "--" + notemark = " " + for (i in argv) { + # Deprecated + if (argv[i] == "--rfc3667") { + printf "\nOption %s does nothing any more\n", argv[i] + argv[i] = "" + } + if (argv[i] == "--no3667") { + printf "\nOption %s does nothing any more\n", argv[i] + argv[i] = "" + } + if (argv[i] == "--rfc2026") { + printf "\nOption %s does nothing any more\n", argv[i] + argv[i] = "" + } + if (argv[i] == "--nowarn") { + option_warn = 0 + argv[i] = "" + } + if (argv[i] == "--filename") { + option_filename = argv[i + 1] + argv[i] = "" + argv[i + 1] = "" + } + if (argv[i] == "--debug") { + option_debug = 1 + argv[i] = "" + } + if (argv[i] == "--nitcount") { + option_nitcount = 1 + argv[i] = "" + } + if (argv[i] == "--pass1") { + option_pass1 = 1 + argv[i] = "" + } + if (argv[i] == "--verbose") { + option_verbose++ + argv[i] = "" + } + if (argv[i] == "--list-matches") { + option_list_matches = 1 + argv[i] = "" + } + if (argv[i] == "--year") { + option_year = argv[i + 1] + argv[i] = "" + argv[i + 1] = "" + } + if (argv[i] == "--checklistwarn") { + option_checklistwarn++ + argv[i] = "" + } + if (argv[i] == "--submitcheck") { + option_submitcheck++ + argv[i] = "" + } + if (argv[i] == "--status") { + option_status = argv[i + 1] + argv[i] = "" + argv[i + 1] = "" + } + if (argv[i] == "--nonascii") { + option_nonascii = 1 + argv[i] = "" + } + if (argv[i] == "--ascii") { + option_nonascii = 0 + argv[i] = "" + } + if (argv[i] == "--") { + argv[i] = "" + } + if (argv[i] ~ "^-.+") { + printf "\nUnknown option: %s\n\n", argv[i] + usage() + exit 1 + } + if (argv[i] ~ "^--.+") { + printf "\nUnknown option: %s\n\n", argv[i] + usage() + exit 1 + } + } + option_pass2 = ! option_pass1 + split("SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US", controlchar, FS) + for (i in controlchar) { + controlchar[sprintf("%c", i + 0)] = controlchar[i] + delete controlchar[i] + } + split("January February March April May June July August September October November December", monthnames, FS) + for (i in monthnames) { + mn = monthnames[i] + month[mn] = i + month[substr(mn, 1, 3)] = i + } + doc_date = 0 + # Extract a list of hyphenated words from the document, and build an array of valid fragments + if (length(option_filename)) { + cmd = sprintf("cat %s | sed 's/[^A-Za-z0-9_-]/\\n/g' | sort | uniq | egrep -- '-' | egrep -v -- '-$' | egrep '^[A-Za-z0-9]'", option_filename) + while ((cmd | getline) > 0) { + word = $0 + frag = "" + for (;;) { + if (length(word) == 0) { + break + } + pos = index(word, "-") + if (pos == 0) { + break + } + frag = frag substr(word, 1, pos) + hyphenfrags[frag] + has_hyphenlist = 1 + word = substr(word, pos + 1) + } + } + } + # get current year + if (option_year > 1990) { + year = option_year + } else if (("date +'%Y'" | getline year) <= 0) { + year = "[0-9]+" + } + # establish the format we expect references to have, for later use + has_refs = 0 + one_ref_format = "(([0-9A-Z-]|I-?D.)[0-9A-Za-z-]*( [0-9A-Z-]+)?|(IEEE|ieee)[A-Za-z0-9.-]+|(ITU ?|ITU-T ?|G\\.)[A-Za-z0-9.-]+)" + reference_format = "\\[" one_ref_format "(, ?" one_ref_format ")*\\]" + abnf_rule_format = "^ +([A-Za-z0-9-]+ *=|;).*" + imap_rule_format = "^ *S: (\\*|[A-Za-z0-9]+) (OK|NO|BAD|PREAUTH|BYE) \\[[-A-Za-z]+\\]" + code_start_format = "()" + code_end_format = "()" + inline_code_format = "(/\\*|\\*/|^ *#)" + # read obsoleted RFC information from file + if (obslist) { + while ((getline < obslist) > 0) { + oldrfc = $1 + $1 = "" + obsoleted[oldrfc] = $0 + } + } else { + obsoleted[""] = "" + } + # read the rfc status information from file + if (statusfile) { + while ((getline < statusfile) > 0) { + rfcstatus = rfcstatus $0 + } + } else { + rfcstatus = "" + } + # read exception RFC information from file + if (exclist) { + while ((getline < exclist) > 0) { + exception[$1] = $1 + } + } else { + exception[""] = "" + } + status2code["bcp"] = "B" + status2code["best current"] = "B" + status2code["best current practice"] = "B" + status2code["experimental"] = "E" + status2code["experimental track"] = "E" + status2code["informational"] = "I" + status2code["ps"] = "P" + status2code["proposed standard"] = "P" + status2code["proposed standards"] = "P" + status2code["standards track"] = "P" + status2code["standard track"] = "P" + status2code["ds"] = "D" + status2code["draft standard"] = "D" + status2code["standard"] = "S" + status2code["full standard"] = "S" + status2code["historic"] = "H" + status2code["not issued"] = "N" + code2status["O"] = "Obsolete" + code2status["U"] = "Unknown state" + code2status["E"] = "Experimental" + code2status["I"] = "Informational" + code2status["B"] = "Best Current Practice" + code2status["P"] = "Proposed Standard" + code2status["D"] = "Draft Standard" + code2status["S"] = "Full Standard" + code2status["H"] = "Historic" + code2status["N"] = "Not Issued" + warncodes["H"] = "N" + warncodes["E"] = "N O" + warncodes["I"] = "N O" + warncodes["B"] = "N E I O U H" + warncodes["P"] = "N E I O U H" + warncodes["D"] = "N E I O U H P" + warncodes["S"] = "N E I P U H P D" + split("B P D S", ietfstreamcodes, FS) + has[""] # make sure this exists as a global variable here + seen_ref[""] + miss_ref[""] + # ------------------------------------------------------------------ + # 3978 and 3979 section texts + # + bp["any_text"] = ".*" + bp["rfc3667_3_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of (S|s)ection 3 of( | \\])RFC( |.?)(3667|3667\\])\\.$" + bp["rfc3667_5_1"] = "By submitting this Internet-Draft, (I|we) certify that any applicable " "patent or other IPR claims of which (I am|we are) aware have been disclosed,( or " "will be disclosed,)? and any of which (I|we) become aware will be disclosed, " "in accordance with RFC 3668.$" + bp["rfc3978_5_1"] = "By submitting this Internet-Draft, each author represents that any " "applicable patent or other IPR claims of which he or she is aware " "have been or will be disclosed, and any of which he or she becomes " "aware will be disclosed, in accordance with Section 6 of BCP 79.$" + bp["rfc3978_5_1_a"] = "By submitting this Internet-Draft, (each|the) author represents that any " "applicable patent or other IPR claims of which (he or she|he|she) is aware " "have been or will be disclosed, and any of which (he or she|he|she) becomes? " "aware will be disclosed, in accordance with( (S|s)ection 6 of)? (BCP 79|RFC 3979|RFC 3668).$" + bp["rfc3978_5_2a"] = "This document may not be modified, and derivative works of it may " "not be created, except to publish it as an RFC and to translate it " "into languages other than English\\.$" + bp["rfc3978_5_2ax"] = "This document may not be modified, and derivative works of it may " "not be created, except to publish it as an RFC and to translate it " "into languages other than English other than to extract section " "[0-9.]+ as-is for separate use\\.$" + bp["rfc3978_5_2b"] = "This document may not be modified, and derivative works of it may " "not be created\\.$" + bp["rfc3978_5_2bx"] = "This document may not be modified, and derivative works of it may " "not be created other than to extract section [0-9.]+ as-is for separate use.$" + bp["rfc3978_5_3"] = "This document may only be posted in an Internet-Draft.$" + bp["rfc3978_5_4_p1"] = "Copyright \\(C\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?.$" + bp["rfc3978_5_4_p1_u4748"] = "Copyright \\(C\\) The IETF Trust \\(?[0-9][0-9][0-9][0-9]\\)?.$" + bp["rfc3978_5_4_p1_e"] = ".+Copyright \\(C\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?\\..+" + bp["rfc3978_5_4_p1_u4748_e"] = ".+Copyright \\(C\\) The IETF Trust \\(?[0-9][0-9][0-9][0-9]\\)?\\..+" + bp["rfc3978_5_4_p1_now"] = sprintf("Copyright \\(C\\) The Internet Society \\(?%s\\)?", year) + bp["rfc3978_5_4_p1_u4748_now"] = sprintf("Copyright \\(C\\) The IETF Trust \\(?%s\\)?", year) + bp["trust-16-oct-2008_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors", year) + bp["trust-12-feb-2009_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors", year) + bp["trust-12-sep-2009_6_b_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors.", year) + bp["trust-28-dec-2009_6_b_i_p2_now"] = sprintf("Copyright \\(c\\) %s IETF Trust and " "the persons identified as the document authors.", year) + # ---------------------------------------------------------------------------------------------- + bp["rfc3978_5_4_p2"] = "This document is subject to the rights, licenses and restrictions contained in BCP " "78, and except as set forth therein, the authors retain all their rights.$" + bp["rfc3978_5_5"] = "This document and the information contained herein are provided " "on an \"AS IS\" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE " "REPRESENTS OR IS SPONSORED BY \\(IF ANY\\), THE INTERNET SOCIETY AND " "THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, " "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT " "THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR " "ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" + bp["rfc3978_5_5_u4748"] = "This document and the information contained herein are provided " "on an \"AS IS\" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE " "REPRESENTS OR IS SPONSORED BY \\(IF ANY\\), THE INTERNET SOCIETY, THE IETF TRUST AND " "THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, " "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT " "THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR " "ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" + bp["rfc3979_5_p1"] = "The IETF takes no position regarding the validity or scope of any " "Intellectual Property Rights or other rights that might be claimed " "to pertain to the implementation or use of the technology " "described in this document or the extent to which any license " "under such rights might or might not be available; nor does it " "represent that it has made any independent effort to identify any " "such rights. Information on the procedures with respect to rights " "in RFC documents can be found in BCP 78 and BCP 79.$" + bp["rfc3979_5_p2"] = "Copies of IPR disclosures made to the IETF Secretariat and any " "assurances of licenses to be made available, or the result of an " "attempt made to obtain a general license or permission for the use " "of such proprietary rights by implementers or users of this " "specification can be obtained from the IETF on-line IPR repository " "at https?://www.ietf.org/ipr.$" + bp["rfc3979_5_p3"] = "The IETF invites any interested party to bring to its attention " "any copyrights, patents or patent applications, or other " "proprietary rights that may cover technology that may be required " "to implement this standard. Please address the information to the " "IETF at ietf-ipr@ietf.org.$" + # ---------------------------------------------------------------------------------------------- + bp["trust-16-oct-2008_6_a"] = "This Internet-Draft is submitted to IETF in full " "conformance with the provisions of BCP 78 and BCP 79\\.$" + bp["trust-16-oct-2008_6_b_p2"] = "Copyright \\(c\\) [0-9][0-9][0-9][0-9] IETF Trust and " "the persons identified as the document authors\\. All rights reserved\\.$" + bp["trust-16-oct-2008_6_b_p3"] = "This document is subject to BCP 78 and the " "IETF Trust's Legal Provisions Relating to IETF Documents " "\\(http://trustee.ietf.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document. " "Please review these documents " "carefully, as they describe your rights and restrictions with respect to " "this document\\.$" + bp["trust-16-oct-2008_6_c_i"] = "This document may not be modified, and derivative " "works of it may not be created, except to format it for publication " "as an RFC and to translate it into languages other than English\\.$" + # ---------------------------------------------------------------------------------------------- + bp["trust-12-feb-2009_6_a"] = bp["trust-16-oct-2008_6_a"] + bp["trust-12-feb-2009_6_b_p2"] = bp["trust-16-oct-2008_6_b_p2"] + bp["trust-12-feb-2009_6_b_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal " "Provisions Relating to IETF Documents in effect on the date of " "publication of this document \\(http://trustee.ietf.org/license-inf(o|o/)\\)\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" + bp["trust-12-feb-2009_6_c_i"] = "This document may not be modified, and derivative " "works of it may not be created, except to format it for publication " "as an RFC or to translate it into languages other than English\\.$" + bp["trust-12-feb-2009_6_c_ii"] = "This document may not be modified, and " "derivative works of it may not be created, and it may not be published " "except as an Internet-Draft\\.$" + bp["trust-12-feb-2009_6_c_iii"] = "This document may contain material from IETF Documents or IETF " "Contributions published or made publicly available before November " "10, 2008\\. The person\\(s\\) controlling the copyright in some of this " "material may not have granted the IETF Trust the right to allow " "modifications of such material outside the IETF Standards Process\\. " "Without obtaining an adequate license from the person\\(s\\) " "controlling the copyright in such materials, this document may not " "be modified outside the IETF Standards Process, and derivative " "works of it may not be created outside the IETF Standards Process, " "except to format it for publication as an RFC or to translate it " "into languages other than English\\.$" + # ---------------------------------------------------------------------------------------------- + bp["trust-12-sep-2009_6_a"] = bp["trust-12-feb-2009_6_a"] + bp["trust-12-sep-2009_6_b_p2"] = bp["trust-12-feb-2009_6_b_p2"] + bp["trust-12-sep-2009_6_c_i"] = bp["trust-12-feb-2009_6_c_i"] + bp["trust-12-sep-2009_6_c_ii"] = bp["trust-12-feb-2009_6_c_ii"] + bp["trust-12-sep-2009_6_c_iii"] = bp["trust-12-feb-2009_6_c_iii"] + bp["trust-12-sep-2009_6_b_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal " "Provisions Relating to IETF Documents \\(https?://trustee.ietf.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "(Simplified|Revised) BSD License text as described in Section 4.e of the " "Trust Legal Provisions and are provided without warranty as described " "in the BSD License\\.$" + # ---------------------------------------------------------------------------------------------- + bp["trust-28-dec-2009_6_b_i_p2"] = bp["trust-12-sep-2009_6_b_p2"] + bp["trust-28-dec-2009_6_c_i"] = bp["trust-12-sep-2009_6_c_i"] + bp["trust-28-dec-2009_6_c_ii"] = bp["trust-12-sep-2009_6_c_ii"] + bp["trust-28-dec-2009_6_c_iii"] = bp["trust-12-sep-2009_6_c_iii"] + bp["trust-28-dec-2009_6_a"] = "This Internet-Draft is submitted in full " "conformance with the provisions of BCP 78 and BCP 79\\.$" + # This applies to the IETF stream + bp["trust-28-dec-2009_6_b_i_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "(Simplified|Revised) BSD License text as described in Section 4.e of the " "Trust Legal Provisions and are provided without warranty as described " "in the (Simplified|Revised) BSD License\\.$" + # This applies to non-IETF streams + bp["trust-28-dec-2009_6_b_ii_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" + # ---------------------------------------------------------------------------------------------- + bp["rfc2026_10_4A"] = "The IETF takes no position regarding the validity or scope of " "any intellectual property or other rights that might be claimed " "to pertain to the implementation or use of the technology " "described in this document or the extent to which any license " "under such rights might or might not be available; neither does " "it represent that it has made any effort to identify any such " "rights. Information on the IETF's procedures with respect to " "rights in standards-track and standards-related documentation " "can be found in BCP-11. Copies of claims of rights made " "available for publication and any assurances of licenses to " "be made available, or the result of an attempt made " "to obtain a general license or permission for the use of such " "proprietary rights by implement[oe]rs or users of this " "specification can be obtained from the IETF Secretariat.$" + bp["rfc2026_10_4B"] = "The IETF invites any interested party to bring to its " "attention any copyrights, patents or patent applications, or " "other proprietary rights which may cover technology that may be " "required to practice this standard. Please address the " "information to the IETF Executive Director.$" + bp["rfc2026_10_4C_p1"] = "Copyright \\([Cc]\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?. All Rights " "Reserved.$" + bp["rfc2026_10_4C_p2"] = "This document and translations of it may be copied and " "furnished to others, and derivative works that comment on or " "otherwise explain it or assist in its implementation may be " "prepared, copied, published and distributed, in whole or in " "part, without restriction of any kind, provided that the above " "copyright notice and this paragraph are included on all such " "copies and derivative works. However, this document itself may " "not be modified in any way, such as by removing the copyright " "notice or references to the Internet Society or other Internet " "organizations, except as needed for the purpose of developing " "Internet standards in which case the procedures for copyrights " "defined in the Internet Standards process must be followed, or " "as required to translate it into languages other than English.$" + bp["rfc2026_10_4C_p3"] = "The limited permissions granted above are perpetual and will " "not be revoked by the Internet Society or its successors or " "assign(ee)?s.$" + bp["rfc2026_10_4C_p4"] = "This document and the information contained herein is provided " "on an \"AS IS\" basis and THE INTERNET SOCIETY AND THE INTERNET " "ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR " "IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE " "OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY " "IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A " "PARTICULAR PURPOSE.$" + bp["rfc2026_10_4D"] = "The IETF has been notified of intellectual property rights " "claimed in regard to some or all of the specification contained " "in this document. For more information consult the online list " "of claimed rights.$" + bp["rfc2026_claim"] = "This document is an Internet-Draft and is in full conformance " "with all provisions of Section 10 of( | \\])RFC( |.?)(2026|2026\\])\\." + bp["rfc2026_lax_claim"] = "This document is an Internet-Draft and is in full conformance " "with all provisions of Section 10 of( | \\])RFC( |.?)(2026|2026\\])( ?\\[[0-9]+\\].*)?." + bp["rfc2026b_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of Section 10 of( | \\])RFC( |.?)(2026|2026\\])\\." + bp["rfc2026b_lax_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of Section 10 of( | \\])RFC( |.?)(2026|2026\\])( ?\\[[0-9]+\\].*)?." + bp["rfc3978_3_claim"] = "This document is an Internet-Draft and is subject to all provisions " "of (S|s)ection 3 of( | \\])RFC( |.?)(3978|3978\\])\\.$" + bp["rfc2119_p2"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", " "\"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\",( | \"NOT RECOMMENDED\", )\"MAY\", " "and \"OPTIONAL\" in this document are to be interpreted as described in" "( | \\[| BCP 14, | BCP 14, \\[)RFC( |.?)2119(\\.|.*\\.|\\].*\\.)$" + bp["rfc2119_p2a"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", " "\"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\",( | \"NOT RECOMMENDED\", )\"MAY\", " "and \"OPTIONAL\" in this document are to be interpreted as described in " "(['\"]?Key words for use in RFCs to Indicate Requirement Levels['\"]? )?" "\\[[0-9A-Z-][0-9A-Za-z-]* ?[0-9A-Z-]*\\].*\\.$" + # This is from RFC 8174 which updates 2119: + bp["rfc8174_p11"] = "The key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL " "NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"NOT RECOMMENDED\", " "\"MAY\", and \"OPTIONAL\" in this document are to be interpreted as " "described in BCP 14 \\[RFC2119\\] ?\\[RFC8174\\] when, and only when, they " "appear in all capitals, as shown here." + bp["1id_guidelines_p1"] = "Internet-Drafts are working documents of the Internet Engineering " "Task Force \\(IETF\\), its areas, and its working groups. Note that other " "groups may also distribute working documents as Internet-Drafts.$" + bp["1id_guidelines_p1a"] = "Internet-Drafts are working documents of the Internet Engineering " "Task Force \\(IETF\\). Note that other groups may also distribute " "working documents as Internet-Drafts. The list of current " "Internet-Drafts is at https?://datatracker.ietf.org/drafts/current/? ?\\.$" + bp["1id_guidelines_p2"] = "Internet-Drafts are draft documents valid for a maximum of six months " "and may be updated, replaced, or obsoleted by other documents at any " "time. It is inappropriate to use Internet-Drafts as reference " "material or to cite them other than as \"?work in progress(\\.\"|\"?\\.)$" + bp["1id_guidelines_p2a"] = "Internet-Drafts are draft documents valid for a maximum of six months " "and may be updated, replaced, or obsoleted by other documents at any " "time. It is inappropriate to use Internet-Drafts as reference " "material or to cite them other than as \"?work in progress(\\.\"|\"?\\.)$" + bp["1id_guidelines_p3"] = "The list of current Internet-Drafts can be accessed at " "https?://www.ietf.org/1id-abstracts.html$" + bp["1id_guidelines_p3a"] = "The list of current Internet-Drafts can be accessed at:? " "https?:// *www.ietf.org/ *(ietf/)?1id-abstracts.(txt|html) ?\\.?$" + bp["1id_guidelines_p4"] = "The list of Internet-Draft Shadow Directories can be accessed at " "https?://www.ietf.org/shadow.html$" + bp["1id_guidelines_p4a"] = "The list of Internet-Draft Shadow Directories can be accessed at:? " "https?:// *www.ietf.org/ *shadow.html ?\\.?$" + bad["MUST not"] = "Using lowercase 'not' together with uppercase 'MUST', " "'SHALL', 'SHOULD', or 'RECOMMENDED' is not an " "accepted usage according to RFC 2119. Please use uppercase 'NOT' " "together with RFC 2119 keywords (if that is what you mean)." + bad["SHALL not"] = bad["MUST not"] + bad["SHOULD not"] = bad["MUST not"] + bad["not RECOMMENDED"] = bad["MUST not"] + bad["MAY NOT"] = "The expression 'MAY NOT', while looking like RFC 2119 requirements " "text, is not defined in RFC 2119, and should not be used. Consider " "using 'MUST NOT' instead (if that is what you mean)." } # ---------------------------------------------------------------------- # Pattern / actions: # /^This Internet-Draft(, draft-.*)? has been deleted./ { - if (option_pass2) { - printf " Skipping this file; it looks like a tombstone file to me.\n" - } - skip_file = 1 + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 } /^This +document has been replaced by/ { - if (option_pass2) { - printf " Skipping this file; it looks like a tombstone file to me.\n" - } - skip_file = 1 + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 } /^This Internet-Draft(, draft-.*)? was published as/ { - if (option_pass2) { - printf " Skipping this file; it looks like a tombstone file to me.\n" - } - skip_file = 1 + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 } /^A new Request for Comments is now available/ { - if (option_pass2) { - printf " Skipping this file; it looks like a tombstone file to me.\n" - } - skip_file = 1 + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 } /^RFC [0-9]+ was never issued./ { - if (option_pass2) { - printf " Skipping this file; it looks like a tombstone file to me.\n" - } - skip_file = 1 + if (option_pass2) { + printf " Skipping this file; it looks like a tombstone file to me.\n" + } + skip_file = 1 } /.*/ { - check_line() + check_line() } # Pagecount /-\+- Pagecount: [0-9]+ -\+-/ { - pagecount = $3 + 0 - next + pagecount = $3 + 0 + next } /-\+- Firstpagelength: [0-9]+ -\+-/ { - firstpagelength = $3 + 0 - next + firstpagelength = $3 + 0 + next } /-\+- Maxpagelength: [0-9]+ -\+-/ { - maxpagelength = $3 + 0 - next + maxpagelength = $3 + 0 + next } /-\+- Longestpage: [0-9]+ -\+-/ { - longestpage = $3 + 0 - next + longestpage = $3 + 0 + next } /-\+- Longpagecount: [0-9]+ -\+-/ { - longpagecount = $3 + 0 - next + longpagecount = $3 + 0 + next } /-\+- Formfeedcount: [0-9]+ -\+-/ { - formfeedcount = $3 + 0 - next + formfeedcount = $3 + 0 + next } /-\+- Expiration: [0-9]+ -\+-/ { - has_expiration = $3 + 0 - next + has_expiration = $3 + 0 + next } /-\+- NoNroffPostproc: [0-9]+ -\+-/ { - missing_nroff_postprocessing = $3 + 0 - next + missing_nroff_postprocessing = $3 + 0 + next } # If the draft begins with 'PK' it some software will think it's a zip file. Mention this. /^PK/ && FNR == 1 { - has_pk_mark = 1 + has_pk_mark = 1 } /^BM/ && FNR == 1 { - has_bm_mark = 1 + has_bm_mark = 1 } # Check for required sections # Nawk doesn't understand IGNORECASE = 0, so we have to explicitly convert. # Also normalise the indentation /\. ?\. ?\. ?\. ?\. *[0-9]+$/ { - if (! has_intro) { - has_toc = 1 - in_toc = 1 - } - next + if (! has_intro) { + has_toc = 1 + in_toc = 1 + } + next } { - normalized = tolower($0) - if (indentation) { - normalized = substr(normalized, indentation) - #if (option_verbose > 2 && option_pass1) printf " normalized: '%s'\n", normalized; - } + normalized = tolower($0) + if (indentation) { + normalized = substr(normalized, indentation) + #if (option_verbose > 2 && option_pass1) printf " normalized: '%s'\n", normalized; + } } /::= +BEGIN *$/ { - in_mib = 1 + in_mib = 1 } /^ +END *$/ { - in_mib = 0 + in_mib = 0 } normalized ~ /^internet[ -]draft/ { - if (FNR < 15) { - has_id_indication = 1 - } else { - has_late_id_indication = 1 - } + if (FNR < 15) { + has_id_indication = 1 + } else { + has_late_id_indication = 1 + } } normalized ~ /^expires:?.*20[0-9][0-9]/ { - has_expiration = FNR + has_expiration = FNR } normalized ~ /[12][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/ { - match($0, /[12][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/) - datestr = substr($0, RSTART, RLENGTH) - if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { - split(datestr, part, /-/) - m = part[2] - d = part[3] - y = part[1] - isodate = sprintf("%s-%s-%s", y, m, d) - new_date = jdn(isodate) - if (new_date > doc_date) { - doc_date = new_date - date_lit = datestr - iso_date = isodate - date_skew = 3 - } - } + match($0, /[12][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/) + datestr = substr($0, RSTART, RLENGTH) + if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { + split(datestr, part, /-/) + m = part[2] + d = part[3] + y = part[1] + isodate = sprintf("%s-%s-%s", y, m, d) + new_date = jdn(isodate) + if (new_date > doc_date) { + doc_date = new_date + date_lit = datestr + iso_date = isodate + date_skew = 3 + } + } } normalized ~ /[adfjmnos][a-z]+ [0-9]+, [12][0-9][0-9][0-9]$/ { - match($0, /[ADFJMNOS][a-z]+ [0-9]+, [12][0-9][0-9][0-9]$/) - datestr = substr($0, RSTART, RLENGTH) - if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { - split(datestr, part, /[ ,]+/) - m = month[part[1]] - d = part[2] - y = part[3] - isodate = sprintf("%s-%s-%s", y, m, d) - new_date = jdn(isodate) - if (new_date > doc_date) { - doc_date = new_date - date_lit = datestr - iso_date = isodate - date_skew = 3 - } - } + match($0, /[ADFJMNOS][a-z]+ [0-9]+, [12][0-9][0-9][0-9]$/) + datestr = substr($0, RSTART, RLENGTH) + if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { + split(datestr, part, /[ ,]+/) + m = month[part[1]] + d = part[2] + y = part[3] + isodate = sprintf("%s-%s-%s", y, m, d) + new_date = jdn(isodate) + if (new_date > doc_date) { + doc_date = new_date + date_lit = datestr + iso_date = isodate + date_skew = 3 + } + } } normalized ~ /([0-9]+ )?[adfjmnos][a-z]+ [12][0-9][0-9][0-9]$/ { - is_docdate = 0 - if (match($0, /[0-9]+ [ADFJMNOS][a-z]+ [12][0-9][0-9][0-9]$/)) { - datestr = substr($0, RSTART, RLENGTH) - if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { - is_docdate = 1 - split(datestr, part, /[ ,]+/) - m = month[part[2]] - d = part[1] - y = part[3] - date_skew = 3 - } - } else { - match($0, /[ADFJMNOS][a-z]+ [12][0-9][0-9][0-9]$/) - datestr = substr($0, RSTART, RLENGTH) - if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { - is_docdate = 1 - split(datestr, part, /[ ,]+/) - m = month[part[1]] - d = 15 - y = part[2] - date_skew = 16 - } - } - if (is_docdate) { - isodate = sprintf("%s-%s-%s", y, m, d) - new_date = jdn(isodate) - if (new_date > doc_date) { - doc_date = new_date - date_lit = datestr - iso_date = isodate - } - } + is_docdate = 0 + if (match($0, /[0-9]+ [ADFJMNOS][a-z]+ [12][0-9][0-9][0-9]$/)) { + datestr = substr($0, RSTART, RLENGTH) + if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { + is_docdate = 1 + split(datestr, part, /[ ,]+/) + m = month[part[2]] + d = part[1] + y = part[3] + date_skew = 3 + } + } else { + match($0, /[ADFJMNOS][a-z]+ [12][0-9][0-9][0-9]$/) + datestr = substr($0, RSTART, RLENGTH) + if ((FNR < 30) && ($0 !~ ("(Expires|Expiration [Dd]ate): *" datestr))) { + is_docdate = 1 + split(datestr, part, /[ ,]+/) + m = month[part[1]] + d = 15 + y = part[2] + date_skew = 16 + } + } + if (is_docdate) { + isodate = sprintf("%s-%s-%s", y, m, d) + new_date = jdn(isodate) + if (new_date > doc_date) { + doc_date = new_date + date_lit = datestr + iso_date = isodate + } + } } normalized ~ /^([0123.]+ +)?table of contents:?( *\(.+\))?$/ { - has_toc = 1 - in_toc = 1 + has_toc = 1 + in_toc = 1 } normalized ~ /^[ \t]*contents$/ { - if (! has_intro) { - has_toc = 1 - in_toc = 1 - } + if (! has_intro) { + has_toc = 1 + in_toc = 1 + } } normalized ~ /^([0123.]+ )? ? ? ? ? ?introduction[ \t]*.*/ { - has_intro = 1 + has_intro = 1 } normalized ~ /^ +([0123.]+ )? ? ? ? ? ?introduction[ \t]*.*/ { - indented_intro = $0 + indented_intro = $0 } normalized ~ /^([0123.]+ )? ? ? ? ? ?overview[ \t]*.*/ { - has_intro = 1 + has_intro = 1 } normalized ~ /^ +([0123.]+ )? ? ? ? ? ?overview[ \t]*.*/ { - indented_intro = $0 + indented_intro = $0 } normalized ~ /^([0123.]+ )? ? ? ? ? ?rationale[ \t]*.*/ { - has_intro = 1 + has_intro = 1 } normalized ~ /^ +([0123.]+ )? ? ? ? ? ?rationale[ \t]*.*/ { - indented_intro = $0 + indented_intro = $0 } normalized ~ /^([0123.]+ )? ? ? ? ? ?scope[ \t]*.*/ { - has_intro = 1 + has_intro = 1 } normalized ~ /^ +([0123.]+ )? ? ? ? ? ?scope[ \t]*.*/ { - indented_intro = $0 + indented_intro = $0 } normalized ~ /^([0123.]+ )? ? ? ? ? ?(historical )?background[ \t]*.*/ { - has_intro = 1 + has_intro = 1 } normalized ~ /^ +([0123.]+ )? ? ? ? ? ?(historical )?background[ \t]*.*/ { - indented_intro = $0 + indented_intro = $0 } normalized ~ /^([0-9.]+ )? ? ? ? ? ?security considerations?[ \t]*.*/ { - has_security = 1 + has_security = 1 } normalized ~ /^ +([0-9.]+ )? ? ? ? ? ?security considerations?[ \t]*.*/ { - indented_security = $0 + indented_security = $0 } normalized ~ /^([0-9.]+ )? ? ? ? ? ?security$/ { - has_security = 1 + has_security = 1 } normalized ~ /^ +([0-9.]+ )? ? ? ? ? ?security$/ { - indented_security = $0 + indented_security = $0 } normalized ~ /^(appendix )?([0-9a-z.]+ )? ? ? ? ? ?iana considerations?[ \t]*.*/ { - has_iana = 1 + has_iana = 1 } normalized ~ /^ +([0-9a-z.]+ )? ? ? ? ? ?iana considerations?[ \t]*.*/ { - indented_iana = $0 + indented_iana = $0 } # New section. If we were in a reference section, we've now left it. normalized ~ /^[0-9.]+ +/ { - in_refs = 0 - in_abnf = 0 - in_imap = 0 - in_abstract = 0 - in_code = 0 - sections[$1] = substr($0, length($1)) + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 + sections[$1] = substr($0, length($1)) } normalized ~ /^status of (this )?memo/ { - in_refs = 0 - in_abnf = 0 - in_imap = 0 - in_abstract = 0 - in_code = 0 + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 } normalized ~ /^conventions used / { - in_refs = 0 - in_abnf = 0 - in_imap = 0 - in_abstract = 0 - in_code = 0 + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 } normalized ~ /^requirements language/ { - in_refs = 0 - in_abnf = 0 - in_imap = 0 - in_abstract = 0 - in_code = 0 + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 } normalized ~ /^table of contents/ { - in_refs = 0 - in_abnf = 0 - in_imap = 0 - in_abstract = 0 - in_code = 0 + in_refs = 0 + in_abnf = 0 + in_imap = 0 + in_abstract = 0 + in_code = 0 } normalized ~ /^([0123.]+ )? *abstract$/ { - has_abstract = 1 - in_abstract = 1 + has_abstract = 1 + in_abstract = 1 } normalized ~ /^ +([0123.]+ )? *abstract$/ { - indented_abstract = $0 - in_abstract = 1 + indented_abstract = $0 + in_abstract = 1 } normalized ~ /^appendix/ { - if (has_refs) { - has_appendix = 1 - } - in_refs = 0 - nnnote("Appendix start: " $0) + if (has_refs) { + has_appendix = 1 + } + in_refs = 0 + nnnote("Appendix start: " $0) } normalized ~ /^ +appendix/ { - if (has_refs) { - indented_appendix = $0 - } + if (has_refs) { + indented_appendix = $0 + } } normalized ~ /(^| )abnf([ .]|$)/ { - abnf_mentioned = 1 + abnf_mentioned = 1 } normalized ~ abnf_rule_format { - in_abnf++ + in_abnf++ } $0 ~ imap_rule_format { - in_imap++ + in_imap++ } # The imap rule format has some parts specifically in uppercase -- can't use 'normalized' normalized ~ /^ *$/ { - in_abnf = 0 - in_imap = 0 + in_abnf = 0 + in_imap = 0 } $0 ~ code_start_format { - in_code = 1 - nnote("Code start at " FNR ": " $0) + in_code = 1 + nnote("Code start at " FNR ": " $0) } $0 ~ code_end_format { - in_code = 0 - nnote("Code end at " FNR ": " $0) + in_code = 0 + nnote("Code end at " FNR ": " $0) } $0 ~ inline_code_format { - if (! in_code) { - code_comment_found = 1 - nnote("Possible code comment in line: " $0) - } + if (! in_code) { + code_comment_found = 1 + nnote("Possible code comment in line: " $0) + } } normalized ~ /^([0-9]+[.]?0? )? ? ? ? ? ?references$/ { - if (has_intro || has_security || has_iana) { - has_refs = 1 - in_refs = 1 - in_normref = 1 - } + if (has_intro || has_security || has_iana) { + has_refs = 1 + in_refs = 1 + in_normref = 1 + } } normalized ~ /^ +([0-9]+[.]?0? )? ? ? ? ? ?references$/ { - if (has_intro || has_security || has_iana) { - indented_refs = $0 - } + if (has_intro || has_security || has_iana) { + indented_refs = $0 + } } normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?normative references?$/ { - if (has_intro || has_security || has_iana) { - has_splitrefs = 1 - has_refs = 1 - in_refs = 1 - in_normref = 1 - } + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + has_refs = 1 + in_refs = 1 + in_normref = 1 + } } normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informative references?$/ { - if (has_intro || has_security || has_iana) { - has_splitrefs = 1 - has_refs = 1 - in_refs = 1 - in_normref = 0 - } + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + has_refs = 1 + in_refs = 1 + in_normref = 0 + } } normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informational references?$/ { - if (has_intro || has_security || has_iana) { - has_splitrefs = 1 - has_refs = 1 - in_refs = 1 - in_normref = 0 - } + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + has_refs = 1 + in_refs = 1 + in_normref = 0 + } } normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?non-normative references?$/ { - if (has_intro || has_security || has_iana) { - has_splitrefs = 1 - has_refs = 1 - in_refs = 1 - in_normref = 0 - } + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + has_refs = 1 + in_refs = 1 + in_normref = 0 + } } normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?references[^a-z]+normative\)?$/ { - if (has_intro || has_security || has_iana) { - has_splitrefs = 1 - in_refs = 1 - in_normref = 1 - } + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + in_refs = 1 + in_normref = 1 + } } normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?references[^a-z]+informative\)?$/ { - if (has_intro || has_security || has_iana) { - has_splitrefs = 1 - in_refs = 1 - in_normref = 0 - } + if (has_intro || has_security || has_iana) { + has_splitrefs = 1 + in_refs = 1 + in_normref = 0 + } } normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?normative$/ { - if (has_refs) { - has_splitrefs = 1 - in_refs = 1 - in_normref = 1 - } + if (has_refs) { + has_splitrefs = 1 + in_refs = 1 + in_normref = 1 + } } normalized ~ /^ *([0-9.]+ )? ? ? ? ? ?informative$/ { - if (has_refs) { - has_splitrefs = 1 - in_refs = 1 - in_normref = 0 - } + if (has_refs) { + has_splitrefs = 1 + in_refs = 1 + in_normref = 0 + } } normalized ~ /^[0-9a-z.]* *((author|editor)(\047s|s\047) +(and +)?)+address(es)?/ { - has_addr = 1 + has_addr = 1 } normalized ~ /^[0-9a-z.]* *author information$/ { - has_addr = 1 + has_addr = 1 } normalized ~ /^[0-9a-z.]* *(author|editor)(\047s|s\047) contact information$/ { - has_addr = 1 + has_addr = 1 } normalized ~ /^[0-9A-Z.]* *contact information$/ { - has_addr = 1 + has_addr = 1 } normalized ~ /^[0-9A-Z.]* *(author|editor)s?:?$/ { - has_addr = 1 + has_addr = 1 } # RFC 3978 / 2026 compliance /^[ \t0-9.]*This document may only be posted in an Internet-Draft.$/ { - has["rfc3978_5_3"] = FNR + has["rfc3978_5_3"] = FNR } { - gsub(/ +/, " ", normalized) + gsub(/ +/, " ", normalized) } normalized ~ /by submitting this internet-draft/ { - para = get_para() - almost = almost_boilerplate["rfc3978_5_1"] - # Order is significant here -- try the longer text before subsets of it - if (match_para(para, "rfc3978_5_1", "rfc3978_5_2ax") || match_para(para, "rfc3978_5_1", "rfc3978_5_2a") || match_para(para, "rfc3978_5_1", "rfc3978_5_2bx") || match_para(para, "rfc3978_5_1", "rfc3978_5_2b") || match_para(para, "rfc3978_5_1") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2ax") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2a") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2bx") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2b") || match_para(para, "rfc3978_5_1_a") || match_para(para, "rfc3667_5_1", "rfc3978_5_2ax") || match_para(para, "rfc3667_5_1", "rfc3978_5_2a") || match_para(para, "rfc3667_5_1", "rfc3978_5_2bx") || match_para(para, "rfc3667_5_1", "rfc3978_5_2b") || match_para(para, "rfc3667_5_1")) { - almost_boilerplate["rfc3978_5_1"] = almost - } + para = get_para() + almost = almost_boilerplate["rfc3978_5_1"] + # Order is significant here -- try the longer text before subsets of it + if (match_para(para, "rfc3978_5_1", "rfc3978_5_2ax") || match_para(para, "rfc3978_5_1", "rfc3978_5_2a") || match_para(para, "rfc3978_5_1", "rfc3978_5_2bx") || match_para(para, "rfc3978_5_1", "rfc3978_5_2b") || match_para(para, "rfc3978_5_1") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2ax") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2a") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2bx") || match_para(para, "rfc3978_5_1_a", "rfc3978_5_2b") || match_para(para, "rfc3978_5_1_a") || match_para(para, "rfc3667_5_1", "rfc3978_5_2ax") || match_para(para, "rfc3667_5_1", "rfc3978_5_2a") || match_para(para, "rfc3667_5_1", "rfc3978_5_2bx") || match_para(para, "rfc3667_5_1", "rfc3978_5_2b") || match_para(para, "rfc3667_5_1")) { + almost_boilerplate["rfc3978_5_1"] = almost + } } normalized ~ /this document may not be modified/ { - para = get_para() - match_para(para, "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_c_ii") || match_para(para, "rfc3978_5_2a") || match_para(para, "rfc3978_5_2ax") || match_para(para, "rfc3978_5_2b") || match_para(para, "rfc3978_5_2bx") + para = get_para() + match_para(para, "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_c_ii") || match_para(para, "rfc3978_5_2a") || match_para(para, "rfc3978_5_2ax") || match_para(para, "rfc3978_5_2b") || match_para(para, "rfc3978_5_2bx") } normalized ~ /copyright ?\(c\) ?the / { - if (! in_mib) { - some_copyright = FNR - para = get_para() - has_some_year = match_para(para, "rfc3978_5_4_p1", "rfc3978_5_4_p2", "rfc3978_5_5") - has_some_year = match_para(para, "rfc3978_5_4_p1_u4748", "rfc3978_5_4_p2", "rfc3978_5_5_u4748") || has_some_year - has_this_year = match_para(para, "rfc3978_5_4_p1_now") - has_this_year = match_para(para, "rfc3978_5_4_p1_u4748_now") || has_this_year - if (! has_some_year) { - match_para(para, "rfc3978_5_4_p1_e") - match_para(para, "rfc3978_5_4_p1_u4748_e") - } - match_para(para, "rfc2026_10_4C_p1", "rfc2026_10_4C_p2", "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") - if (has_some_year && ! has_this_year) { - has["rfc3978_5_4_p1_old"] = FNR - } - } + if (! in_mib) { + some_copyright = FNR + para = get_para() + has_some_year = match_para(para, "rfc3978_5_4_p1", "rfc3978_5_4_p2", "rfc3978_5_5") + has_some_year = match_para(para, "rfc3978_5_4_p1_u4748", "rfc3978_5_4_p2", "rfc3978_5_5_u4748") || has_some_year + has_this_year = match_para(para, "rfc3978_5_4_p1_now") + has_this_year = match_para(para, "rfc3978_5_4_p1_u4748_now") || has_this_year + if (! has_some_year) { + match_para(para, "rfc3978_5_4_p1_e") + match_para(para, "rfc3978_5_4_p1_u4748_e") + } + match_para(para, "rfc2026_10_4C_p1", "rfc2026_10_4C_p2", "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") + if (has_some_year && ! has_this_year) { + has["rfc3978_5_4_p1_old"] = FNR + } + } } normalized ~ /this document is subject to the rights/ { - para = get_para() - match_para(para, "rfc3978_5_4_p2") + para = get_para() + match_para(para, "rfc3978_5_4_p2") } normalized ~ /this document and the information/ { - para = get_para() - match_para(para, "rfc3978_5_5") - match_para(para, "rfc3978_5_5_u4748") - match_para(para, "rfc2026_10_4C_p4") + para = get_para() + match_para(para, "rfc3978_5_5") + match_para(para, "rfc3978_5_5_u4748") + match_para(para, "rfc2026_10_4C_p4") } normalized ~ /the ietf takes no position regarding/ { - para = get_para() - match_para(para, "rfc3979_5_p1", "rfc3979_5_p2", "rfc3979_5_p3") - match_para(para, "rfc2026_10_4A") + para = get_para() + match_para(para, "rfc3979_5_p1", "rfc3979_5_p2", "rfc3979_5_p3") + match_para(para, "rfc2026_10_4A") } normalized ~ /copies of ipr disclosures made to the/ { - para = get_para() - match_para(para, "rfc3979_5_p2", "rfc3979_5_p3") + para = get_para() + match_para(para, "rfc3979_5_p2", "rfc3979_5_p3") } normalized ~ /the ietf invites any interested party/ { - para = get_para() - match_para(para, "rfc3979_5_p3") - match_para(para, "rfc2026_10_4B") + para = get_para() + match_para(para, "rfc3979_5_p3") + match_para(para, "rfc2026_10_4B") } normalized ~ /this document and translations of it/ { - para = get_para() - match_para(para, "rfc2026_10_4C_p2", "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") + para = get_para() + match_para(para, "rfc2026_10_4C_p2", "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") } normalized ~ /the limited permissions granted above/ { - para = get_para() - match_para(para, "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") + para = get_para() + match_para(para, "rfc2026_10_4C_p3", "rfc2026_10_4C_p4") } normalized ~ /the ietf has been notified of intellectual/ { - para = get_para() - match_para(para, "rfc2026_10_4D") + para = get_para() + match_para(para, "rfc2026_10_4D") } normalized ~ /this document is an internet-draft and is/ { - para = get_para() - match_para(para, "rfc2026_lax_claim") - match_para(para, "rfc2026b_lax_claim") - ref_in_heading_nit = (has["rfc2026_lax_claim"] || has["rfc2026_lax_claim"]) && ! match_para(para, "rfc2026_claim") && ! match_para(para, "rfc2026b_claim") - match_para(para, "rfc3667_3_claim", "rfc3667_5_1") - match_para(para, "rfc3667_3_claim", "rfc3978_5_1_a") - match_para(para, "rfc3978_3_claim", "rfc3667_5_1") - match_para(para, "rfc3978_3_claim", "rfc3978_5_1") - match_para(para, "rfc3978_3_claim", "rfc3978_5_1_a") - if (match(para, reference_format)) { - update_references(para, FNR) - } + para = get_para() + match_para(para, "rfc2026_lax_claim") + match_para(para, "rfc2026b_lax_claim") + ref_in_heading_nit = (has["rfc2026_lax_claim"] || has["rfc2026_lax_claim"]) && ! match_para(para, "rfc2026_claim") && ! match_para(para, "rfc2026b_claim") + match_para(para, "rfc3667_3_claim", "rfc3667_5_1") + match_para(para, "rfc3667_3_claim", "rfc3978_5_1_a") + match_para(para, "rfc3978_3_claim", "rfc3667_5_1") + match_para(para, "rfc3978_3_claim", "rfc3978_5_1") + match_para(para, "rfc3978_3_claim", "rfc3978_5_1_a") + if (match(para, reference_format)) { + update_references(para, FNR) + } } # IETF Trust Provisions boilerplate normalized ~ /this internet-draft is submitted to ietf in/ { - para = get_para() - match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_i") - match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_ii") - match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_iii") - match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_i") - match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_ii") - match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_iii") + para = get_para() + match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_i") + match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_ii") + match_para(para, "trust-12-sep-2009_6_a", "trust-12-sep-2009_6_c_iii") + match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_i") + match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_ii") + match_para(para, "trust-12-sep-2009_6_a", "trust-28-dec-2009_6_c_iii") } normalized ~ /this internet-draft is submitted in full/ { - para = get_para() - match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1a") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_ii") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_iii") + para = get_para() + match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1a") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_ii") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_iii") } normalized ~ /copyright \(c\) [0-9]+ ietf trust and/ { - if (! in_mib) { - some_copyright = FNR - para = get_para() - has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_i_p3") - has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_ii_p3") - has_this_year = match_para(para, "trust-28-dec-2009_6_b_i_p2_now") - } + if (! in_mib) { + some_copyright = FNR + para = get_para() + has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_i_p3") + has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_ii_p3") + has_this_year = match_para(para, "trust-28-dec-2009_6_b_i_p2_now") + } } normalized ~ /this document is subject to bcp 78/ { - para = get_para() - match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_i") - match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_ii") - match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_iii") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_i") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_ii") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_iii") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_i") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_ii") - match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_iii") - match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_i") - match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_ii") - match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_iii") - match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_i") - match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_ii") - match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_iii") + para = get_para() + match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_i") + match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_ii") + match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_iii") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_i") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_ii") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-12-sep-2009_6_c_iii") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_i") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_ii") + match_para(para, "trust-12-sep-2009_6_b_p3", "trust-28-dec-2009_6_c_iii") + match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_i") + match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_ii") + match_para(para, "trust-28-dec-2009_6_b_i_p3", "trust-28-dec-2009_6_c_iii") + match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_i") + match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_ii") + match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_iii") } normalized ~ /this document may contain material from ietf/ { - para = get_para() - match_para(para, "trust-12-sep-2009_6_c_iii") - match_para(para, "trust-28-dec-2009_6_c_iii") + para = get_para() + match_para(para, "trust-12-sep-2009_6_c_iii") + match_para(para, "trust-28-dec-2009_6_c_iii") } # RFC 2119 compliance normalized ~ /(the key ?words|in this document, several words are used)/ { - para = get_para() - if (match_para(para, "rfc2119_p2") || match_para(para, "rfc2119_p2a") || match_para(para, "rfc8174_p11")) { - if (match(para, /NOT RECOMMENDED/)) { - rfc2119_p2_not_recommended++ - } - } - if (match(para, reference_format)) { - reftag = substr(para, RSTART + 1, RLENGTH - 2) - reftag2119 = reftag - update_references(para, FNR) - } + para = get_para() + if (match_para(para, "rfc2119_p2") || match_para(para, "rfc2119_p2a") || match_para(para, "rfc8174_p11")) { + if (match(para, /NOT RECOMMENDED/)) { + rfc2119_p2_not_recommended++ + } + } + if (match(para, reference_format)) { + reftag = substr(para, RSTART + 1, RLENGTH - 2) + reftag2119 = reftag + update_references(para, FNR) + } } #/^[ \t0-9.]*Table Of [Cc]ontents?:?$/ { has_toc = 1; misspelled_toc = 1} /^[ \t0-9.]*(Author|Editor)([^\047]s|s[^\047]) [Aa]ddress(es)?$/ { - has_addr = 1 - misspelled_addr = 1 + has_addr = 1 + misspelled_addr = 1 } /^[ \t0-9.]*(Authors?|Editors?) +[Aa]ddress(es)?$/ { - has_addr = 1 - misspelled_addr = 1 + has_addr = 1 + misspelled_addr = 1 } # 1id_guidelines.txt compliance normalized ~ /internet-drafts are working documents of/ { - para = get_para() - match_para(para, "1id_guidelines_p1", "1id_guidelines_p2", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p1", "1id_guidelines_p2a", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p1a", "1id_guidelines_p2") || match_para(para, "1id_guidelines_p1a", "1id_guidelines_p2a") + para = get_para() + match_para(para, "1id_guidelines_p1", "1id_guidelines_p2", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p1", "1id_guidelines_p2a", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p1a", "1id_guidelines_p2") || match_para(para, "1id_guidelines_p1a", "1id_guidelines_p2a") } normalized ~ /internet-drafts are draft documents valid for/ { - para = get_para() - match_para(para, "1id_guidelines_p2", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p2a") + para = get_para() + match_para(para, "1id_guidelines_p2", "1id_guidelines_p3a", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p2a") } normalized ~ /the list of current internet-drafts can be/ { - para = get_para() - match_para(para, "1id_guidelines_p3", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p3a", "1id_guidelines_p4a") + para = get_para() + match_para(para, "1id_guidelines_p3", "1id_guidelines_p4a") || match_para(para, "1id_guidelines_p3a", "1id_guidelines_p4a") } normalized ~ /the list of internet-draft shadow directories/ { - para = get_para() - match_para(para, "1id_guidelines_p4") || match_para(para, "1id_guidelines_p4a") + para = get_para() + match_para(para, "1id_guidelines_p4") || match_para(para, "1id_guidelines_p4a") } normalized ~ /^obsoletes: / { - if (FNR < 10) { - c = split($0, obsoletelist, /[, ]+/) - docs = "" - for (i = 2; i < c; i++) { - header_obsoletes = 1 - word = obsoletelist[i] - if (word ~ /^[0-9]+/) { - docs = docs "RFC" word " " - } - if (word ~ /^draft-/) { - docs = docs word " " - } - if (word ~ /^[0-9]+$/) { - obsoletes[word] = FNR - } else if (word ~ /[Rr][Ff][Cc]/) { - obsoletes_junk = FNR - } else { - break - } - } - if (docs) { - gsub(/ $/, "", docs) - } - obsoletes_docs = docs - } + if (FNR < 10) { + c = split($0, obsoletelist, /[, ]+/) + docs = "" + for (i = 2; i < c; i++) { + header_obsoletes = 1 + word = obsoletelist[i] + if (word ~ /^[0-9]+/) { + docs = docs "RFC" word " " + } + if (word ~ /^draft-/) { + docs = docs word " " + } + if (word ~ /^[0-9]+$/) { + obsoletes[word] = FNR + } else if (word ~ /[Rr][Ff][Cc]/) { + obsoletes_junk = FNR + } else { + break + } + } + if (docs) { + gsub(/ $/, "", docs) + } + obsoletes_docs = docs + } } normalized ~ /^updates: / { - if (FNR < 10) { - c = split($0, updatelist, /[, ]+/) - docs = "" - for (i = 2; i < c; i++) { - header_updates = 1 - word = updatelist[i] - if (word ~ /^[0-9]+/) { - docs = docs "RFC" word " " - } - if (word ~ /^draft-/) { - docs = docs word " " - } - if (word ~ /^[0-9]+$/) { - updates[word] = FNR - } else if (word ~ /[Rr][Ff][Cc]/) { - updates_junk = FNR - } else { - break - } - } - if (docs) { - gsub(/ $/, "", docs) - } - updates_docs = docs - } + if (FNR < 10) { + c = split($0, updatelist, /[, ]+/) + docs = "" + for (i = 2; i < c; i++) { + header_updates = 1 + word = updatelist[i] + if (word ~ /^[0-9]+/) { + docs = docs "RFC" word " " + } + if (word ~ /^draft-/) { + docs = docs word " " + } + if (word ~ /^[0-9]+$/) { + updates[word] = FNR + } else if (word ~ /[Rr][Ff][Cc]/) { + updates_junk = FNR + } else { + break + } + } + if (docs) { + gsub(/ $/, "", docs) + } + updates_docs = docs + } } /draft-/ { - if (! has_intro && ! has_abstract && ! has_refs && ! has_appendix && ! has_docname) { - if ($0 ~ /Updates: *draft-/) { - updates[$2] - } else if ($0 ~ /Obsoletes: *draft-/) { - obsoletes[$2] - } else { - match($0, /draft-[a-z0-9-]*/) - good_docname = substr($0, RSTART, RLENGTH) - match($0, /draft-[^ \t>]*/) - full_docname = substr($0, RSTART, RLENGTH) - has_docname = 1 - } - } + if (! has_intro && ! has_abstract && ! has_refs && ! has_appendix && ! has_docname) { + if ($0 ~ /Updates: *draft-/) { + updates[$2] + } else if ($0 ~ /Obsoletes: *draft-/) { + obsoletes[$2] + } else { + match($0, /draft-[a-z0-9-]*/) + good_docname = substr($0, RSTART, RLENGTH) + match($0, /draft-[^ \t>]*/) + full_docname = substr($0, RSTART, RLENGTH) + has_docname = 1 + } + } } # References and downref checking normalized ~ /(intended status|category):/ { - if (! has_intro && ! has_abstract && ! has_refs && ! has_appendix && ! has_status_of_memo) { - sta = tolower($0) - sub(/^.*(intended status|category): */, "", sta) - sub(/ .*$/, "", sta) - if (length(intended_status) == 0) { - intended_status = sta - intended_status_text = $0 - sub(/ .*$/, "", intended_status_text) - } - } + if (! has_intro && ! has_abstract && ! has_refs && ! has_appendix && ! has_status_of_memo) { + sta = tolower($0) + sub(/^.*(intended status|category): */, "", sta) + sub(/ .*$/, "", sta) + if (length(intended_status) == 0) { + intended_status = sta + intended_status_text = $0 + sub(/ .*$/, "", intended_status_text) + } + } } $0 ~ reference_format { - if (in_refs) { - refpos = FNR - reftext = strip($0) - while (((getline) > 0) && (text = strip($0)) != "") { - check_line() - if ($0 ~ reference_format) { - # start of a new reference without intervening blank line - update_references(reftext, refpos) - refpos = FNR - reftext = text - } else if (reftext ~ /-$/) { - reftext = reftext text - } else { - reftext = reftext " " text - } - } - update_references(reftext, refpos) - } else { - if ((! abnf_mentioned || ! in_abnf) && ! in_imap && ! in_code) { - update_references($0, FNR) - } - if ((abnf_mentioned && in_abnf) && ($0 ~ (";.*" reference_format))) { - update_references($0, FNR) - } - } + if (in_refs) { + refpos = FNR + reftext = strip($0) + while (((getline) > 0) && (text = strip($0)) != "") { + check_line() + if ($0 ~ reference_format) { + # start of a new reference without intervening blank line + update_references(reftext, refpos) + refpos = FNR + reftext = text + } else if (reftext ~ /-$/) { + reftext = reftext text + } else { + reftext = reftext " " text + } + } + update_references(reftext, refpos) + } else { + if ((! abnf_mentioned || ! in_abnf) && ! in_imap && ! in_code) { + update_references($0, FNR) + } + if ((abnf_mentioned && in_abnf) && ($0 ~ (";.*" reference_format))) { + update_references($0, FNR) + } + } } /\[[0-9A-Z-]+- *$/ { - incomplete_ref_line = strip($0) - incomplete_ref_pos = FNR + incomplete_ref_line = strip($0) + incomplete_ref_pos = FNR } /^ *[0-9A-Z-]+\]/ { - if (incomplete_ref_pos + 1 == FNR) { - update_references(incomplete_ref_line strip($0), incomplete_ref_pos) - } + if (incomplete_ref_pos + 1 == FNR) { + update_references(incomplete_ref_line strip($0), incomplete_ref_pos) + } } { - text = strip($0) - if (text == "") { - if (para) { - check_para(para) - } - para = "" - } else if (para ~ /-$/) { - para = para text - } else { - para = para " " text - } + text = strip($0) + if (text == "") { + if (para) { + check_para(para) + } + para = "" + } else if (para ~ /-$/) { + para = para text + } else { + para = para " " text + } } END { - report(option_filename) - if (errors || longlines || hyphens || spacing || nonascii || controlchars) { - print "" - } - if (errors < 256) { - exit errors - } else { - exit 255 - } + report(option_filename) + if (errors || longlines || hyphens || spacing || nonascii || controlchars) { + print "" + } + if (errors < 256) { + exit errors + } else { + exit 255 + } } @@ -1399,511 +1399,511 @@ END { # function announce(str) { - ### print "" - print "" - print fold(" " str, " ", columns) - print " " substr("----------------------------------------------------------------------------", 1, columns - 2) - print "" + ### print "" + print "" + print fold(" " str, " ", columns) + print " " substr("----------------------------------------------------------------------------", 1, columns - 2) + print "" } function check_downref(tag, warnlist, rfcnum, draftname, code, status, doc) { - if (tag in ref_text) { - ref = ref_text[tag] - } else { - ref = tag - } - gsub(/ +/, " ", ref) - if (option_verbose > 2) { - note("Reference text: " ref) - } - if (ref ~ /[, ([](draft-|I-D\.)/) { - draftname = get_draftname(ref) - draftrev = get_draftrev(ref) - doc = draftname - get_state(draftname, state) - if (state["downloaded"] != today) { - download_state = " (However, the state information for " draftname " is not up-to-date. The last update was " state["downloaded"] ")" - } - ## Refactoring needed. We probably need a check_reference() rather than check_downref(), - ## with the published and current-version checks below being done as part of the general - ## reference checking, rather than inside the downref check. - if ("rfcnum" in state) { - warnc(sprintf("Outdated reference: %s has been published as RFC %s", draftname, state["rfcnum"])) - } else if (draftrev && ("rev" in state) && (draftrev != state["rev"])) { - if (draftrev + 0 < state["rev"] + 0) { - warnc(sprintf("Outdated reference: A later version (-%s) exists of %s-%s", state["rev"], draftname, draftrev)) - } else { - comment(sprintf("Unexpected draft version: The latest known version of %s is -%s, but you're referring to -%s.%s", draftname, state["rev"], draftrev, download_state)) - } - } - } else if (ref ~ /(RFC|rfc|Request [Ff]or Comments)( \([^\)]*\)|-)? ?[0-9][0-9]+/) { - rfcnum = get_rfcnum(ref) - doc = "RFC" rfcnum - } - if (doc && doc in seen_ref && ! (seen_ref[doc] in miss_ref)) { - comment(sprintf("Duplicate reference: %s, mentioned in '%s', was also mentioned in '%s'.", doc, tag, seen_ref[doc])) - } - seen_ref[doc] = tag - if (rfcnum) { - code = substr(rfcstatus, rfcnum, 1) - } - if (draftname) { - code = get_draftcode(draftname, state) - } - if (rfcnum && code == "O") { - if (tag in ref_norm) { - referr("Obsolete normative reference", rfcnum, tag) - } else if (! (tag in ref_def)) { - referr("Obsolete undefined reference", rfcnum, tag) - } else { - refcomment("Obsolete informational reference (is this intentional?)", rfcnum, tag) - } - } else if (tag in ref_norm) { - if (rfcnum) { - if (code in warnlist) { - if (rfcnum in exception) { - referr(sprintf("Downref: Normative reference to an %s RFC", code2status[code]), rfcnum, tag, "\n(Excemption has been granted for downref to this document in the past, see https://trac.tools.ietf.org/group/iesg/trac/wiki/DownrefRegistry)") - } else { - referr(sprintf("Downref: Normative reference to an %s RFC", code2status[code]), rfcnum, tag) - } - } - } else if ("U" in warnlist) { - if (ref ~ /[, ([](draft-|I-D\.)/) { - if (code) { - if (code in warnlist) { - errc(sprintf("Downref: Normative reference to an %s draft: %s (ref. '%s')", code2status[code], draftname, tag)) - } - } else { - if (state["deststatus"] == "None") { - statmsg = " (No intended status found in state file of " draftname ")" - } else { - statmsg = "" - } - comment(sprintf("Possible downref: Normative reference to a draft: ref. '%s' %s", tag, statmsg)) - } - } else { - comment(sprintf("Possible downref: Non-RFC (?) normative reference: ref. '%s'", tag)) - } - } - } else if (! (tag in ref_def)) { - # Comment out this -- the warning for a missing reference is enough for a first pass. - # if (rfcnum) { - # if (code in warnlist) { - # refcomment(sprintf("Possible downref: Undefined reference to an %s RFC", code2status[code]), rfcnum, tag); - # } - # } else if ("U" in warnlist) { - # if (ref ~ /[, ([](draft-|I-D\.)/) { - # if (code) { - # if (code in warnlist) { - # warnc(sprintf("Possible downref: Undefined reference to an %s draft: %s (ref. '%s')", code2status[code], draftname, tag)); - # } - # } else { - # warnc(sprintf("Possible downref: Undefined reference to a draft: ref. '%s'", tag)); - # if (state["deststatus"] == "None") { - # note("(No intended status found in state file of " draftname ")"); - # } - # } - # } else { - # comment(sprintf("Possible downref: Undefined Non-RFC (?) reference : ref. '%s'", tag)); - # } - # } - } + if (tag in ref_text) { + ref = ref_text[tag] + } else { + ref = tag + } + gsub(/ +/, " ", ref) + if (option_verbose > 2) { + note("Reference text: " ref) + } + if (ref ~ /[, ([](draft-|I-D\.)/) { + draftname = get_draftname(ref) + draftrev = get_draftrev(ref) + doc = draftname + get_state(draftname, state) + if (state["downloaded"] != today) { + download_state = " (However, the state information for " draftname " is not up-to-date. The last update was " state["downloaded"] ")" + } + ## Refactoring needed. We probably need a check_reference() rather than check_downref(), + ## with the published and current-version checks below being done as part of the general + ## reference checking, rather than inside the downref check. + if ("rfcnum" in state) { + warnc(sprintf("Outdated reference: %s has been published as RFC %s", draftname, state["rfcnum"])) + } else if (draftrev && ("rev" in state) && (draftrev != state["rev"])) { + if (draftrev + 0 < state["rev"] + 0) { + warnc(sprintf("Outdated reference: A later version (-%s) exists of %s-%s", state["rev"], draftname, draftrev)) + } else { + comment(sprintf("Unexpected draft version: The latest known version of %s is -%s, but you're referring to -%s.%s", draftname, state["rev"], draftrev, download_state)) + } + } + } else if (ref ~ /(RFC|rfc|Request [Ff]or Comments)( \([^\)]*\)|-)? ?[0-9][0-9]+/) { + rfcnum = get_rfcnum(ref) + doc = "RFC" rfcnum + } + if (doc && doc in seen_ref && ! (seen_ref[doc] in miss_ref)) { + comment(sprintf("Duplicate reference: %s, mentioned in '%s', was also mentioned in '%s'.", doc, tag, seen_ref[doc])) + } + seen_ref[doc] = tag + if (rfcnum) { + code = substr(rfcstatus, rfcnum, 1) + } + if (draftname) { + code = get_draftcode(draftname, state) + } + if (rfcnum && code == "O") { + if (tag in ref_norm) { + referr("Obsolete normative reference", rfcnum, tag) + } else if (! (tag in ref_def)) { + referr("Obsolete undefined reference", rfcnum, tag) + } else { + refcomment("Obsolete informational reference (is this intentional?)", rfcnum, tag) + } + } else if (tag in ref_norm) { + if (rfcnum) { + if (code in warnlist) { + if (rfcnum in exception) { + referr(sprintf("Downref: Normative reference to an %s RFC", code2status[code]), rfcnum, tag, "\n(Excemption has been granted for downref to this document in the past, see https://trac.tools.ietf.org/group/iesg/trac/wiki/DownrefRegistry)") + } else { + referr(sprintf("Downref: Normative reference to an %s RFC", code2status[code]), rfcnum, tag) + } + } + } else if ("U" in warnlist) { + if (ref ~ /[, ([](draft-|I-D\.)/) { + if (code) { + if (code in warnlist) { + errc(sprintf("Downref: Normative reference to an %s draft: %s (ref. '%s')", code2status[code], draftname, tag)) + } + } else { + if (state["deststatus"] == "None") { + statmsg = " (No intended status found in state file of " draftname ")" + } else { + statmsg = "" + } + comment(sprintf("Possible downref: Normative reference to a draft: ref. '%s' %s", tag, statmsg)) + } + } else { + comment(sprintf("Possible downref: Non-RFC (?) normative reference: ref. '%s'", tag)) + } + } + } else if (! (tag in ref_def)) { + # Comment out this -- the warning for a missing reference is enough for a first pass. + # if (rfcnum) { + # if (code in warnlist) { + # refcomment(sprintf("Possible downref: Undefined reference to an %s RFC", code2status[code]), rfcnum, tag); + # } + # } else if ("U" in warnlist) { + # if (ref ~ /[, ([](draft-|I-D\.)/) { + # if (code) { + # if (code in warnlist) { + # warnc(sprintf("Possible downref: Undefined reference to an %s draft: %s (ref. '%s')", code2status[code], draftname, tag)); + # } + # } else { + # warnc(sprintf("Possible downref: Undefined reference to a draft: ref. '%s'", tag)); + # if (state["deststatus"] == "None") { + # note("(No intended status found in state file of " draftname ")"); + # } + # } + # } else { + # comment(sprintf("Possible downref: Undefined Non-RFC (?) reference : ref. '%s'", tag)); + # } + # } + } } function check_line() { - got_input = 1 - gsub(/\r/, "", $0) - sub(/[\n\t ]+$/, "", $0) - thiscolumn = match($0, /[^ ]/) - if (thiscolumn && thiscolumn < indentation) { - indentation = thiscolumn - # 1.1.a Max column 72 - } - if (length($0) > 72 && ! skip_file) { - if (match($0, "[^\001-\177]")) { - printf "%s(%d): Line appears to be too long, but this could be caused by non-ascii characters in UTF-8 encoding\n", FILENAME, FNR - } else { - if (option_verbose && option_pass1) { - printf "%s(%d): Line is too long: the offending characters are '%s'\n", FILENAME, FNR, substr($0, 73) - } - longlines++ - if (length($0) - 72 > excesslength) { - excesslength = length($0) - 72 - } - } - } - # 1.1.b Ragged right - if (! skip_file && ! match($0, /^ *Internet.Draft/) && ! match($0, /^ *INTERNET.DRAFT/) && match($0, /[A-Za-z][a-z] ? ?[a-z]/)) { - if (option_verbose && option_pass1) { - printf "%s(%d): Line has weird spacing: '...%s...'\n", FILENAME, FNR, substr($0, RSTART - 5, 14) - } - spacing++ - sp_line[spacing] = $0 - linenum[spacing] = FNR - extract[spacing] = substr($0, RSTART - 5, 14) - } - # 1.1.c No hyphenation for line-breaks - if ($0 ~ /[A-Za-z0-9_]-$/ && ! skip_file && ! has_refs && has_hyphenlist) { - word = $0 - sub(/^.*[^A-Za-z0-9_-]/, "", word) - if (! word in hyphenfrags) { - if (option_verbose && option_pass1) { - printf "%s(%d): Line seems to end with a hyphenated word.\n", FILENAME, FNR - if (option_verbose > 1 && option_pass1) { - printf " --> %s\n", $0 - } - } - hyphens++ - } - } - # 1.1.e ASCII-only - # The test really should go from \200 to \377 - but the awk implementation - # on *BSD seems to have used \377 internally as a sentinel or something... - if (match($0, "[^\001-\177]") && ! skip_file) { - if (option_verbose && option_pass1) { - printf "%s(%d): Found non-ascii character (%s) in position %d.\n", FILENAME, FNR, substr($0, RSTART, 1), RSTART - if (option_verbose > 1 && option_pass1) { - printf " --> %s\n", $0 - printf " %*s\n", RSTART, "^" - } - } - nonascii++ - } - # 1.1.e no control characer except CR NL FF - # nawk can't handle octal escapes inside character classes, it seems. Sigh. - # if (match($0, /[\001-\011\013\016-\037]/) && ! skip_file) ... - if (match($0, /(\001|\002|\003|\004|\005|\006|\007|\010|\011|\013|\016|\017|\020|\021|\022|\023|\024|\025|\026|\027|\030|\031|\032|\033|\034|\035|\036|\037)/) && ! skip_file) { - if (option_verbose && option_pass1) { - printf "%s(%d): Found control character %s in position %d.\n", FILENAME, FNR, controlchar[substr($0, RSTART, 1)], RSTART - if (option_verbose > 1 && option_pass1) { - printf " --> %s\n", $0 - printf " %*s\n", RSTART, "^" - } - } - controlchars++ - } - # 1.1.f Do not number the Abstract section - if ($0 ~ /^[ \t]*Abstract[ \t]*$/) { - abstract_seen = 1 - } - if ($0 ~ /^[ \t]*[0-9][.0-9 \t]*Abstract[ \t]*$/ && (! abstract_seen) && ! skip_file && option_pass2) { - errg("The Abstract section seems to be numbered") - abstract_seen = 1 - } - # 1.1.f Do not number the "Status of Memo" section - if ($0 ~ /^[ \t]*Status of (This )?Memo[ \t]*$/) { - has_status_of_memo = 1 - } - if ($0 ~ /^[ \t]*[0-9][.0-9 \t]*Status of (This )?Memo[ \t]*$/ && (! has_status_of_memo) && ! skip_file && option_pass2) { - errg("The Status of Memo section seems to be numbered") - has_status_of_memo = 1 - } - # RFC 2119 language - if (! match($0, "IN NO EVENT SHALL") && ! match($0, "SHALL THE COPYRIGHT") && match($0, /[ \t](MUST|REQUIRED|SHALL|SHOULD|RECOMMENDED|MAY|OPTIONAL)([ \t\.,]|$)/)) { - keywords++ - rfc2119line[keywords] = FNR - rstart = RSTART - 16 - rlength = 38 - if (rstart + rlength > length($0)) { - rstart = length($0) - rlength + 1 - } - if (rstart < 1) { - rstart = 1 - } - if (! (FNR in line)) { - line[FNR] = substr($0, rstart, rlength) - } - if (option_verbose > 1 && option_pass1) { - printf "%s(%d): RFC 2119 keyword: %s.\n", FILENAME, FNR, $0 - } - # Keywords: - # - # MUST MUST NOT - # SHALL SHALL NOT - # SHOULD SHOULD NOT - # RECOMMENDED NOT RECOMMENDED - # REQUIRED - # MAY - # OPTIONAL - - # Find uppercase words before or after our keywords, and check if the combination is defined - l = $0 - sub(/\t/, " ", l) - notkwds["MAY NOT"] - notkwds["NOT REQUIRED"] - notkwds["NOT OPTIONAL"] - for (combo in notkwds) { - if (l ~ combo) { - rfc2119undefined[combo] - if (option_verbose > 1 && option_pass1) { - printf "%s(%d): Undefined keyword combination: '%s'.\n", FILENAME, FNR, combo - } - } - } - } - # ID-Checklist section 3.6: Example domain names - if (has_intro && ! has_refs && (match($0, /[ \t]([A-Z0-9_-]+\.)+[A-Z0-9_-]+\.[A-Z]+/) || match($0, /[ \t]([a-z0-9_-]+\.)+[a-z0-9_-]+\.[a-z]+/))) { - FQDN = substr($0, RSTART + 1, RLENGTH - 1) - FQDN1 = substr($0, RSTART + 1, RLENGTH) - addrstart = RSTART - fqdn = tolower(FQDN) - fqdn1 = tolower(FQDN1) - if (fqdn !~ /([a-z0-9_-]+\.)+example(.(com|org|net))?$/ && fqdn !~ /([a-z0-9_-]+\.)+(urn|uri|in-addr)\.arpa?$/ && fqdn !~ /www.ietf.org/ && fqdn !~ /[0-9]+\.[0-9]+\./ && fqdn !~ /.\..\../ && fqdn1 !~ /.*@$/) { - if (option_verbose && option_pass1) { - printf "%s(%d): Found possible FQDN '%s' in position %d; this doesn't match " "RFC 2606's suggested \".example\" or \".example.(com|org|net)\".\n", FILENAME, FNR, FQDN, addrstart - if (option_verbose > 1 && option_pass1) { - printf " --> %s\n", $0 - printf " %*s\n", addrstart, "^" - } - } - badfqdns++ - } - } - # ID-Checklist section 3.6 A: Example numeric IPv4 addresses - if (has_intro && ! in_refs && match($0, /[ \t][0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)+/)) { - IPv4addr = substr($0, RSTART + 1, RLENGTH - 1) - if (IPv4addr ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { - addrstart = RSTART + 1 - split(IPv4addr, part, FS) - for (i = 1; i <= 4; i++) { - if (part[i] + 0 > bigpart) { - bigpart = part[i] + 0 - } - } - if (IPv4addr ~ /^192\.0\.2\.[0-9]+$/) { - ipv4_example_addr++ - } - if (IPv4addr !~ /^192\.0\.2\.[0-9]+$/ && IPv4addr !~ /198\.51\.100\.[0-9]+$/ && IPv4addr !~ /203\.0\.113\.[0-9]+$/ && IPv4addr !~ /233\.252\.0\.[0-9]+$/ && IPv4addr !~ /^0\.0\.0\.0$/ && IPv4addr !~ /^255\.255\.255\.255$/ && ! (IPv4addr in sections) && bigpart < 256 && ! match($0, "([Ss]ections?|[Cc]lause)[ \t]" IPv4addr)) { - if (option_verbose && option_pass1) { - printf "%s(%d): Found possible IPv4 address '%s' in position %d; this doesn't match " "the suggested documentation address ranges specified in RFC 6890 (or successor): " "blocks 192.0.2.0/24 (TEST-NET-1), 198.51.100.0/24 " "(TEST-NET-2), and 203.0.113.0/24 (TEST-NET-3); " "or the 233.252.0.0/24 (MCAST-TEST-NET) example multicast " "address range specified in RFC 5771.\n", FILENAME, FNR, IPv4addr, addrstart - if (option_verbose > 1 && option_pass1) { - printf " --> %s\n", $0 - printf " %*s\n", addrstart, "^" - } - } - if (IPv4addr ~ /^192\.168\.[0-9]+\.[0-9]+$/ || IPv4addr ~ /^10\.[0-9]\.[0-9]+\.[0-9]+$/ || IPv4addr ~ /^172\.(1[6-9]|2[0-9]|3[01])\.[0-9]+\.[0-9]+$/) { - privipv4addr++ - } else if (IPv4addr ~ /^2(2[4-9]|3[0-9])\.[0-9]+\.[0-9]+\.[0-9]+$/ && IPv4addr !~ /233\.252\.0\.[0-9]+$/) { - mcastipv4addr++ - } else { - badipv4addr++ - } - } - } - } + got_input = 1 + gsub(/\r/, "", $0) + sub(/[\n\t ]+$/, "", $0) + thiscolumn = match($0, /[^ ]/) + if (thiscolumn && thiscolumn < indentation) { + indentation = thiscolumn + # 1.1.a Max column 72 + } + if (length($0) > 72 && ! skip_file) { + if (match($0, "[^\001-\177]")) { + printf "%s(%d): Line appears to be too long, but this could be caused by non-ascii characters in UTF-8 encoding\n", FILENAME, FNR + } else { + if (option_verbose && option_pass1) { + printf "%s(%d): Line is too long: the offending characters are '%s'\n", FILENAME, FNR, substr($0, 73) + } + longlines++ + if (length($0) - 72 > excesslength) { + excesslength = length($0) - 72 + } + } + } + # 1.1.b Ragged right + if (! skip_file && ! match($0, /^ *Internet.Draft/) && ! match($0, /^ *INTERNET.DRAFT/) && match($0, /[A-Za-z][a-z] ? ?[a-z]/)) { + if (option_verbose && option_pass1) { + printf "%s(%d): Line has weird spacing: '...%s...'\n", FILENAME, FNR, substr($0, RSTART - 5, 14) + } + spacing++ + sp_line[spacing] = $0 + linenum[spacing] = FNR + extract[spacing] = substr($0, RSTART - 5, 14) + } + # 1.1.c No hyphenation for line-breaks + if ($0 ~ /[A-Za-z0-9_]-$/ && ! skip_file && ! has_refs && has_hyphenlist) { + word = $0 + sub(/^.*[^A-Za-z0-9_-]/, "", word) + if (! word in hyphenfrags) { + if (option_verbose && option_pass1) { + printf "%s(%d): Line seems to end with a hyphenated word.\n", FILENAME, FNR + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + } + } + hyphens++ + } + } + # 1.1.e ASCII-only + # The test really should go from \200 to \377 - but the awk implementation + # on *BSD seems to have used \377 internally as a sentinel or something... + if (match($0, "[^\001-\177]") && ! skip_file) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found non-ascii character (%s) in position %d.\n", FILENAME, FNR, substr($0, RSTART, 1), RSTART + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + printf " %*s\n", RSTART, "^" + } + } + nonascii++ + } + # 1.1.e no control characer except CR NL FF + # nawk can't handle octal escapes inside character classes, it seems. Sigh. + # if (match($0, /[\001-\011\013\016-\037]/) && ! skip_file) ... + if (match($0, /(\001|\002|\003|\004|\005|\006|\007|\010|\011|\013|\016|\017|\020|\021|\022|\023|\024|\025|\026|\027|\030|\031|\032|\033|\034|\035|\036|\037)/) && ! skip_file) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found control character %s in position %d.\n", FILENAME, FNR, controlchar[substr($0, RSTART, 1)], RSTART + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + printf " %*s\n", RSTART, "^" + } + } + controlchars++ + } + # 1.1.f Do not number the Abstract section + if ($0 ~ /^[ \t]*Abstract[ \t]*$/) { + abstract_seen = 1 + } + if ($0 ~ /^[ \t]*[0-9][.0-9 \t]*Abstract[ \t]*$/ && (! abstract_seen) && ! skip_file && option_pass2) { + errg("The Abstract section seems to be numbered") + abstract_seen = 1 + } + # 1.1.f Do not number the "Status of Memo" section + if ($0 ~ /^[ \t]*Status of (This )?Memo[ \t]*$/) { + has_status_of_memo = 1 + } + if ($0 ~ /^[ \t]*[0-9][.0-9 \t]*Status of (This )?Memo[ \t]*$/ && (! has_status_of_memo) && ! skip_file && option_pass2) { + errg("The Status of Memo section seems to be numbered") + has_status_of_memo = 1 + } + # RFC 2119 language + if (! match($0, "IN NO EVENT SHALL") && ! match($0, "SHALL THE COPYRIGHT") && match($0, /[ \t](MUST|REQUIRED|SHALL|SHOULD|RECOMMENDED|MAY|OPTIONAL)([ \t\.,]|$)/)) { + keywords++ + rfc2119line[keywords] = FNR + rstart = RSTART - 16 + rlength = 38 + if (rstart + rlength > length($0)) { + rstart = length($0) - rlength + 1 + } + if (rstart < 1) { + rstart = 1 + } + if (! (FNR in line)) { + line[FNR] = substr($0, rstart, rlength) + } + if (option_verbose > 1 && option_pass1) { + printf "%s(%d): RFC 2119 keyword: %s.\n", FILENAME, FNR, $0 + } + # Keywords: + # + # MUST MUST NOT + # SHALL SHALL NOT + # SHOULD SHOULD NOT + # RECOMMENDED NOT RECOMMENDED + # REQUIRED + # MAY + # OPTIONAL + + # Find uppercase words before or after our keywords, and check if the combination is defined + l = $0 + sub(/\t/, " ", l) + notkwds["MAY NOT"] + notkwds["NOT REQUIRED"] + notkwds["NOT OPTIONAL"] + for (combo in notkwds) { + if (l ~ combo) { + rfc2119undefined[combo] + if (option_verbose > 1 && option_pass1) { + printf "%s(%d): Undefined keyword combination: '%s'.\n", FILENAME, FNR, combo + } + } + } + } + # ID-Checklist section 3.6: Example domain names + if (has_intro && ! has_refs && (match($0, /[ \t]([A-Z0-9_-]+\.)+[A-Z0-9_-]+\.[A-Z]+/) || match($0, /[ \t]([a-z0-9_-]+\.)+[a-z0-9_-]+\.[a-z]+/))) { + FQDN = substr($0, RSTART + 1, RLENGTH - 1) + FQDN1 = substr($0, RSTART + 1, RLENGTH) + addrstart = RSTART + fqdn = tolower(FQDN) + fqdn1 = tolower(FQDN1) + if (fqdn !~ /([a-z0-9_-]+\.)+example(.(com|org|net))?$/ && fqdn !~ /([a-z0-9_-]+\.)+(urn|uri|in-addr)\.arpa?$/ && fqdn !~ /www.ietf.org/ && fqdn !~ /[0-9]+\.[0-9]+\./ && fqdn !~ /.\..\../ && fqdn1 !~ /.*@$/) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found possible FQDN '%s' in position %d; this doesn't match " "RFC 2606's suggested \".example\" or \".example.(com|org|net)\".\n", FILENAME, FNR, FQDN, addrstart + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + printf " %*s\n", addrstart, "^" + } + } + badfqdns++ + } + } + # ID-Checklist section 3.6 A: Example numeric IPv4 addresses + if (has_intro && ! in_refs && match($0, /[ \t][0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)+/)) { + IPv4addr = substr($0, RSTART + 1, RLENGTH - 1) + if (IPv4addr ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { + addrstart = RSTART + 1 + split(IPv4addr, part, FS) + for (i = 1; i <= 4; i++) { + if (part[i] + 0 > bigpart) { + bigpart = part[i] + 0 + } + } + if (IPv4addr ~ /^192\.0\.2\.[0-9]+$/) { + ipv4_example_addr++ + } + if (IPv4addr !~ /^192\.0\.2\.[0-9]+$/ && IPv4addr !~ /198\.51\.100\.[0-9]+$/ && IPv4addr !~ /203\.0\.113\.[0-9]+$/ && IPv4addr !~ /233\.252\.0\.[0-9]+$/ && IPv4addr !~ /^0\.0\.0\.0$/ && IPv4addr !~ /^255\.255\.255\.255$/ && ! (IPv4addr in sections) && bigpart < 256 && ! match($0, "([Ss]ections?|[Cc]lause)[ \t]" IPv4addr)) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found possible IPv4 address '%s' in position %d; this doesn't match " "the suggested documentation address ranges specified in RFC 6890 (or successor): " "blocks 192.0.2.0/24 (TEST-NET-1), 198.51.100.0/24 " "(TEST-NET-2), and 203.0.113.0/24 (TEST-NET-3); " "or the 233.252.0.0/24 (MCAST-TEST-NET) example multicast " "address range specified in RFC 5771.\n", FILENAME, FNR, IPv4addr, addrstart + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", $0 + printf " %*s\n", addrstart, "^" + } + } + if (IPv4addr ~ /^192\.168\.[0-9]+\.[0-9]+$/ || IPv4addr ~ /^10\.[0-9]\.[0-9]+\.[0-9]+$/ || IPv4addr ~ /^172\.(1[6-9]|2[0-9]|3[01])\.[0-9]+\.[0-9]+$/) { + privipv4addr++ + } else if (IPv4addr ~ /^2(2[4-9]|3[0-9])\.[0-9]+\.[0-9]+\.[0-9]+$/ && IPv4addr !~ /233\.252\.0\.[0-9]+$/) { + mcastipv4addr++ + } else { + badipv4addr++ + } + } + } + } } function check_para(para) { - # Checking various things that need to be checked after assembling a full paragraph; - # in particular, word combinations can't be reliably checked line-by-line as they - # may be split across a line break. - for (pattern in bad) { - xpat = "[^-A-Za-z0-9_]" pattern "[^-A-Za-z0-9_]" - if (para ~ xpat) { - found_bad_pat[FNR] = pattern - found_bad_para[FNR] = para - } - } - if (match(para, /NOT RECOMMENDED/)) { - has_not_recommended++ - } - # ID-Checklist section 3.6 B: Example numeric IPv6 addresses - if (has_intro && ! in_refs && match(para, /[ \t\[][0-9A-Fa-f]+:[0-9A-Fa-f]+(:[0-9A-Fa-f]*)+(EUI64)?/)) { - if (para ~ /.+EUI64/) { - IPv6addr = substr(para, RSTART + 1, RLENGTH - 6) "0" - } else { - IPv6addr = substr(para, RSTART + 1, RLENGTH - 1) - } - addrstart = RSTART + 1 - if (IPv6addr ~ /^2001:0?[Dd][Bb]8(:[0-9A-Fa-f]*)+$/) { - if (is_ipv6(IPv6addr)) { - ipv6_example_addr++ - } - } else if (is_ipv6(IPv6addr)) { - if (option_verbose && option_pass1) { - printf "%s(%d): Found possible IPv6 address '%s' in position %d in the paragraph; this doesn't match " "RFC 3849's suggested 2001:DB8::/32 address range or RFC 4193's Unique Local Address range FC00::/7.\n", FILENAME, FNR, IPv6addr, addrstart - if (option_verbose > 1 && option_pass1) { - printf " --> %s\n", para - printf " %*s\n", addrstart, "^" - } - } - if (IPv6addr ~ /^[Ff][CcDd][0-9A-Fa-f]?[0-9A-Fa-f]?(:[0-9A-Fa-f]*)+$/) { - ulpv6addr++ - } else if (IPv6addr ~ /^[Ff][Ee][89ABab][0-9A-Fa-f](:[0-9A-Fa-f]*)+$/) { - lldipv6addr++ - } else { - badipv6addr++ - } - # TODO: Permit IPv6 addresses with embedded IPv4 example addresses. The prefixes which - # may have such are (from David Thaler 2010-08-20 19:45 +0000): - # - # The list of relevant IPv4-embedded IPv6 address formats I'm currently aware of is: - # - # 6to4 (RFC 3056 section 2): - # 2002:<4 bytes of IPv4 address>::/48 - # - # Teredo (RFC 4380 section 4): - # 2001:0:<4 bytes of IPv4 address>::/64 - # - # IPv6/IPv4 Translation Address (https://tools.ietf.org/html/draft-ietf-behave-address-format-10#section-2.2 table 2): - # 64:ff9b::<4 bytes of IPv4 address> - # - # IPv4-Compatible IPv6 Address (RFC 4291 section 2.5.5.1): - # ::<4 bytes of IPv4 address> - # - # IPv4-Mapped IPv6 Address (RFC 4291 section 2.5.5.2): - # ::FFFF:<4 bytes of IPv4 address> - # - # IPv4-Translatable (aka IPv4-Translated) IPv6 Address (RFC 2765 section 2.1): - # ::FFFF:0:<4 bytes of IPv4 address> - # - # And two other relevant cases of *multicast* address spaces with well-known prefixes - # and embedded IPv4 or IPv6 *unicast* address prefixes: - # - # Unicast-Prefix-Based IPv6 Multicast Address (RFC 3306 section 4): - # FF3x:::: - # So since 2001:DB8::/32 is a doc prefix, then - # FF3x:20:2001:DB8::/64 would be a multicast range for documentation. - # And by changing the "20" hex to anything larger is also ok of course. - # - # Embedded RP (RFC 3956) section 3 modifies the above to also allow FF7x... in addition to FF3x... - # - # Unicast-Prefix-Based IPv4 Multicast Address (https://tools.ietf.org/html/draft-ietf-mboned-ipv4-uni-based-mcast-06 section 3, in RFC editors queue): - # . - # Where it's still waiting for IANA to assign the TBD byte out of the multicast range (so stay tuned). - # So the multicast addresss - # TBD.192.0.2 - # TBD.198.51.100 - # TBD.203.0.113 - # would automatically be for documentation purposes once TBD is assigned. - } - # TODO: Warn for violations of RFC 5952: - # - # RFC 5952 IPv6 Text Representation August 2010 - # - # 4. A Recommendation for IPv6 Text Representation - # - # A recommendation for a canonical text representation format of IPv6 - # addresses is presented in this section. The recommendation in this - # document is one that complies fully with [RFC4291], is implemented by - # various operating systems, and is human friendly. The recommendation - # in this section SHOULD be followed by systems when generating an - # address to be represented as text, but all implementations MUST - # accept and be able to handle any legitimate [RFC4291] format. It is - # advised that humans also follow these recommendations when spelling - # an address. - # - # 4.1. Handling Leading Zeros in a 16-Bit Field - # - # Leading zeros MUST be suppressed. For example, 2001:0db8::0001 is - # not acceptable and must be represented as 2001:db8::1. A single 16- - # bit 0000 field MUST be represented as 0. - # - # 4.2. "::" Usage - # - # 4.2.1. Shorten as Much as Possible - # - # The use of the symbol "::" MUST be used to its maximum capability. - # For example, 2001:db8:0:0:0:0:2:1 must be shortened to 2001:db8::2:1. - # Likewise, 2001:db8::0:1 is not acceptable, because the symbol "::" - # could have been used to produce a shorter representation 2001:db8::1. - # - # 4.2.2. Handling One 16-Bit 0 Field - # - # The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field. - # For example, the representation 2001:db8:0:1:1:1:1:1 is correct, but - # 2001:db8::1:1:1:1:1 is not correct. - # - # 4.2.3. Choice in Placement of "::" - # - # When there is an alternative choice in the placement of a "::", the - # longest run of consecutive 16-bit 0 fields MUST be shortened (i.e., - # the sequence with three consecutive zero fields is shortened in 2001: - # 0:0:1:0:0:0:1). When the length of the consecutive 16-bit 0 fields - # are equal (i.e., 2001:db8:0:0:1:0:0:1), the first sequence of zero - # bits MUST be shortened. For example, 2001:db8::1:0:0:1 is correct - # representation. - # - # 4.3. Lowercase - # - # The characters "a", "b", "c", "d", "e", and "f" in an IPv6 address - # MUST be represented in lowercase. - } - if (in_abstract && para !~ /^[ \t]*Abstract[ \t]*$/) { - lcpara = tolower(para) - if (match(lcpara, /obsoletes ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { - findall(lcpara, "obsoletes ((\\[?rfcs? ?)?[0-9]+\\]?(, )?)+", lst) - for (i in lst) { - txt = lst[i] - findall(txt, "(rfc ?)?[0-9]+", rfcs) - for (j in rfcs) { - r = rfcs[j] - if (! (r ~ /rfc/)) { - r = "rfc" r - } - sub(/ /, "", r) - sub(/rfc/, "RFC", r) - abstract_obsoletes = abstract_obsoletes " " r - } - } - } - # Accept 'replaces' as a synonym of 'obsoletes' in the abstract text - if (match(lcpara, /replaces ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { - findall(lcpara, "replaces ((\\[?rfcs? ?)?[0-9]+\\]?(, )?)+", lst) - for (i in lst) { - txt = lst[i] - findall(txt, "(rfc ?)?[0-9]+", rfcs) - for (j in rfcs) { - r = rfcs[j] - if (! (r ~ /rfc/)) { - r = "rfc" r - } - sub(/ /, "", r) - sub(/rfc/, "RFC", r) - abstract_obsoletes = abstract_obsoletes " " r - } - } - } - if (match(lcpara, /updates ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { - findall(lcpara, "updates ((\\[?rfcs? ?)?[0-9]+\\]?(, | and )?)+", lst) - for (i in lst) { - txt = lst[i] - findall(txt, "(rfc ?)?[0-9]+", rfcs) - for (j in rfcs) { - r = rfcs[j] - if (! (r ~ /rfc/)) { - r = "rfc" r - } - sub(/ /, "", r) - sub(/rfc/, "RFC", r) - abstract_updates = abstract_updates " " r - } - } - } - if (match(lcpara, /rfc ?[0-9]+/)) { - findall(lcpara, "rfc ?[0-9]+", rfcs) - for (j in rfcs) { - r = rfcs[j] - sub(/ /, "", r) - sub(/rfc/, "RFC", r) - abstract_mentions = abstract_mentions " " r - } - } - if (match(para, reference_format)) { - findall(para, reference_format, refs) - for (j in refs) { - r = refs[j] - sub(/ /, "", r) - sub(/rfc/, "RFC", r) - if (tolower(r) !~ /\[page ?[0-9]+\]/) { - abstract_references = abstract_references " " r - } - } - } - } + # Checking various things that need to be checked after assembling a full paragraph; + # in particular, word combinations can't be reliably checked line-by-line as they + # may be split across a line break. + for (pattern in bad) { + xpat = "[^-A-Za-z0-9_]" pattern "[^-A-Za-z0-9_]" + if (para ~ xpat) { + found_bad_pat[FNR] = pattern + found_bad_para[FNR] = para + } + } + if (match(para, /NOT RECOMMENDED/)) { + has_not_recommended++ + } + # ID-Checklist section 3.6 B: Example numeric IPv6 addresses + if (has_intro && ! in_refs && match(para, /[ \t\[][0-9A-Fa-f]+:[0-9A-Fa-f]+(:[0-9A-Fa-f]*)+(EUI64)?/)) { + if (para ~ /.+EUI64/) { + IPv6addr = substr(para, RSTART + 1, RLENGTH - 6) "0" + } else { + IPv6addr = substr(para, RSTART + 1, RLENGTH - 1) + } + addrstart = RSTART + 1 + if (IPv6addr ~ /^2001:0?[Dd][Bb]8(:[0-9A-Fa-f]*)+$/) { + if (is_ipv6(IPv6addr)) { + ipv6_example_addr++ + } + } else if (is_ipv6(IPv6addr)) { + if (option_verbose && option_pass1) { + printf "%s(%d): Found possible IPv6 address '%s' in position %d in the paragraph; this doesn't match " "RFC 3849's suggested 2001:DB8::/32 address range or RFC 4193's Unique Local Address range FC00::/7.\n", FILENAME, FNR, IPv6addr, addrstart + if (option_verbose > 1 && option_pass1) { + printf " --> %s\n", para + printf " %*s\n", addrstart, "^" + } + } + if (IPv6addr ~ /^[Ff][CcDd][0-9A-Fa-f]?[0-9A-Fa-f]?(:[0-9A-Fa-f]*)+$/) { + ulpv6addr++ + } else if (IPv6addr ~ /^[Ff][Ee][89ABab][0-9A-Fa-f](:[0-9A-Fa-f]*)+$/) { + lldipv6addr++ + } else { + badipv6addr++ + } + # TODO: Permit IPv6 addresses with embedded IPv4 example addresses. The prefixes which + # may have such are (from David Thaler 2010-08-20 19:45 +0000): + # + # The list of relevant IPv4-embedded IPv6 address formats I'm currently aware of is: + # + # 6to4 (RFC 3056 section 2): + # 2002:<4 bytes of IPv4 address>::/48 + # + # Teredo (RFC 4380 section 4): + # 2001:0:<4 bytes of IPv4 address>::/64 + # + # IPv6/IPv4 Translation Address (https://tools.ietf.org/html/draft-ietf-behave-address-format-10#section-2.2 table 2): + # 64:ff9b::<4 bytes of IPv4 address> + # + # IPv4-Compatible IPv6 Address (RFC 4291 section 2.5.5.1): + # ::<4 bytes of IPv4 address> + # + # IPv4-Mapped IPv6 Address (RFC 4291 section 2.5.5.2): + # ::FFFF:<4 bytes of IPv4 address> + # + # IPv4-Translatable (aka IPv4-Translated) IPv6 Address (RFC 2765 section 2.1): + # ::FFFF:0:<4 bytes of IPv4 address> + # + # And two other relevant cases of *multicast* address spaces with well-known prefixes + # and embedded IPv4 or IPv6 *unicast* address prefixes: + # + # Unicast-Prefix-Based IPv6 Multicast Address (RFC 3306 section 4): + # FF3x:::: + # So since 2001:DB8::/32 is a doc prefix, then + # FF3x:20:2001:DB8::/64 would be a multicast range for documentation. + # And by changing the "20" hex to anything larger is also ok of course. + # + # Embedded RP (RFC 3956) section 3 modifies the above to also allow FF7x... in addition to FF3x... + # + # Unicast-Prefix-Based IPv4 Multicast Address (https://tools.ietf.org/html/draft-ietf-mboned-ipv4-uni-based-mcast-06 section 3, in RFC editors queue): + # . + # Where it's still waiting for IANA to assign the TBD byte out of the multicast range (so stay tuned). + # So the multicast addresss + # TBD.192.0.2 + # TBD.198.51.100 + # TBD.203.0.113 + # would automatically be for documentation purposes once TBD is assigned. + } + # TODO: Warn for violations of RFC 5952: + # + # RFC 5952 IPv6 Text Representation August 2010 + # + # 4. A Recommendation for IPv6 Text Representation + # + # A recommendation for a canonical text representation format of IPv6 + # addresses is presented in this section. The recommendation in this + # document is one that complies fully with [RFC4291], is implemented by + # various operating systems, and is human friendly. The recommendation + # in this section SHOULD be followed by systems when generating an + # address to be represented as text, but all implementations MUST + # accept and be able to handle any legitimate [RFC4291] format. It is + # advised that humans also follow these recommendations when spelling + # an address. + # + # 4.1. Handling Leading Zeros in a 16-Bit Field + # + # Leading zeros MUST be suppressed. For example, 2001:0db8::0001 is + # not acceptable and must be represented as 2001:db8::1. A single 16- + # bit 0000 field MUST be represented as 0. + # + # 4.2. "::" Usage + # + # 4.2.1. Shorten as Much as Possible + # + # The use of the symbol "::" MUST be used to its maximum capability. + # For example, 2001:db8:0:0:0:0:2:1 must be shortened to 2001:db8::2:1. + # Likewise, 2001:db8::0:1 is not acceptable, because the symbol "::" + # could have been used to produce a shorter representation 2001:db8::1. + # + # 4.2.2. Handling One 16-Bit 0 Field + # + # The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field. + # For example, the representation 2001:db8:0:1:1:1:1:1 is correct, but + # 2001:db8::1:1:1:1:1 is not correct. + # + # 4.2.3. Choice in Placement of "::" + # + # When there is an alternative choice in the placement of a "::", the + # longest run of consecutive 16-bit 0 fields MUST be shortened (i.e., + # the sequence with three consecutive zero fields is shortened in 2001: + # 0:0:1:0:0:0:1). When the length of the consecutive 16-bit 0 fields + # are equal (i.e., 2001:db8:0:0:1:0:0:1), the first sequence of zero + # bits MUST be shortened. For example, 2001:db8::1:0:0:1 is correct + # representation. + # + # 4.3. Lowercase + # + # The characters "a", "b", "c", "d", "e", and "f" in an IPv6 address + # MUST be represented in lowercase. + } + if (in_abstract && para !~ /^[ \t]*Abstract[ \t]*$/) { + lcpara = tolower(para) + if (match(lcpara, /obsoletes ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { + findall(lcpara, "obsoletes ((\\[?rfcs? ?)?[0-9]+\\]?(, )?)+", lst) + for (i in lst) { + txt = lst[i] + findall(txt, "(rfc ?)?[0-9]+", rfcs) + for (j in rfcs) { + r = rfcs[j] + if (! (r ~ /rfc/)) { + r = "rfc" r + } + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + abstract_obsoletes = abstract_obsoletes " " r + } + } + } + # Accept 'replaces' as a synonym of 'obsoletes' in the abstract text + if (match(lcpara, /replaces ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { + findall(lcpara, "replaces ((\\[?rfcs? ?)?[0-9]+\\]?(, )?)+", lst) + for (i in lst) { + txt = lst[i] + findall(txt, "(rfc ?)?[0-9]+", rfcs) + for (j in rfcs) { + r = rfcs[j] + if (! (r ~ /rfc/)) { + r = "rfc" r + } + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + abstract_obsoletes = abstract_obsoletes " " r + } + } + } + if (match(lcpara, /updates ((\[?rfcs? ?)?[0-9]+\]?(, | and )?)+/)) { + findall(lcpara, "updates ((\\[?rfcs? ?)?[0-9]+\\]?(, | and )?)+", lst) + for (i in lst) { + txt = lst[i] + findall(txt, "(rfc ?)?[0-9]+", rfcs) + for (j in rfcs) { + r = rfcs[j] + if (! (r ~ /rfc/)) { + r = "rfc" r + } + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + abstract_updates = abstract_updates " " r + } + } + } + if (match(lcpara, /rfc ?[0-9]+/)) { + findall(lcpara, "rfc ?[0-9]+", rfcs) + for (j in rfcs) { + r = rfcs[j] + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + abstract_mentions = abstract_mentions " " r + } + } + if (match(para, reference_format)) { + findall(para, reference_format, refs) + for (j in refs) { + r = refs[j] + sub(/ /, "", r) + sub(/rfc/, "RFC", r) + if (tolower(r) !~ /\[page ?[0-9]+\]/) { + abstract_references = abstract_references " " r + } + } + } + } } # ---------------------------------------------------------------------- @@ -1911,10 +1911,10 @@ function check_para(para) # function checkmultibp(name) { - if (has[name] && almost_boilerplate[name]) { - warn(sprintf("In addition to %s boilerplate, a section with a similar start was also found:\n", expandname(name))) - showalmost(name) - } + if (has[name] && almost_boilerplate[name]) { + warn(sprintf("In addition to %s boilerplate, a section with a similar start was also found:\n", expandname(name))) + showalmost(name) + } } # ---------------------------------------------------------------------- @@ -1922,15 +1922,15 @@ function checkmultibp(name) # function comment(str, indented) { - if (option_warn) { - print fold(" " infomark " " str, " ", columns) - if (indented) { - print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) - print fold(" '" indented "' )", " ", columns) - } - print "" - comments++ - } + if (option_warn) { + print fold(" " infomark " " str, " ", columns) + if (indented) { + print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) + print fold(" '" indented "' )", " ", columns) + } + print "" + comments++ + } } # ---------------------------------------------------------------------- @@ -1938,13 +1938,13 @@ function comment(str, indented) # function err(str, indented) { - print fold(" " errmark " " str, " ", columns) - if (indented) { - print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) - print fold(" '" indented "' )", " ", columns) - } - print "" - errors++ + print fold(" " errmark " " str, " ", columns) + if (indented) { + print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) + print fold(" '" indented "' )", " ", columns) + } + print "" + errors++ } # ---------------------------------------------------------------------- @@ -1953,13 +1953,13 @@ function err(str, indented) # Errors which are IESG checklist errors, but not submission errors function errc(str, indented) { - if (! option_submitcheck) { - if (option_checklistwarn) { - warn(str, indented) - } else { - err(str, indented) - } - } + if (! option_submitcheck) { + if (option_checklistwarn) { + warn(str, indented) + } else { + err(str, indented) + } + } } # ---------------------------------------------------------------------- @@ -1967,11 +1967,11 @@ function errc(str, indented) # function errg(str, indented) { - if (option_guidelinewarn) { - warn(str, indented) - } else { - err(str, indented) - } + if (option_guidelinewarn) { + warn(str, indented) + } else { + err(str, indented) + } } # ---------------------------------------------------------------------- @@ -1980,11 +1980,11 @@ function errg(str, indented) # Errors which are only warnings in submission mode function errw(str, indented) { - if (option_submitcheck) { - warn(str, indented) - } else { - err(str, indented) - } + if (option_submitcheck) { + warn(str, indented) + } else { + err(str, indented) + } } # ---------------------------------------------------------------------- @@ -1992,21 +1992,21 @@ function errw(str, indented) # function expandname(name) { - sub(/_u/, ", updated by RFC ", name) - sub(/_p/, ", paragraph ", name) - sub(/_e/, " embedded", name) - if (name ~ /^rfc/ || name ~ /^trust-/) { - sub("_", ", Section ", name) - split("x ix viii vii vi v iv iii ii i", roman, FS) - for (i in roman) { - r = roman[i] - sub("_" r, "(" r ")", name) - } - gsub("_", ".", name) - sub("rfc", "RFC ", name) - sub("trust-", "IETF Trust Legal Provisions of ", name) - } - return name + sub(/_u/, ", updated by RFC ", name) + sub(/_p/, ", paragraph ", name) + sub(/_e/, " embedded", name) + if (name ~ /^rfc/ || name ~ /^trust-/) { + sub("_", ", Section ", name) + split("x ix viii vii vi v iv iii ii i", roman, FS) + for (i in roman) { + r = roman[i] + sub("_" r, "(" r ")", name) + } + gsub("_", ".", name) + sub("rfc", "RFC ", name) + sub("trust-", "IETF Trust Legal Provisions of ", name) + } + return name } # ---------------------------------------------------------------------- @@ -2014,13 +2014,13 @@ function expandname(name) # function findall(str, re, array, i) { - array[0] = str - while (match(str, re) > 0) { - i += 1 - array[i] = substr(str, RSTART, RLENGTH) - str = substr(str, RSTART + RLENGTH) - } - delete array[0] + array[0] = str + while (match(str, re) > 0) { + i += 1 + array[i] = substr(str, RSTART, RLENGTH) + str = substr(str, RSTART + RLENGTH) + } + delete array[0] } # ---------------------------------------------------------------------- @@ -2028,9 +2028,9 @@ function findall(str, re, array, i) # function flaw(str, indented) { - print fold(" " flawmark " " str, " ", columns) - print "" - flaws++ + print fold(" " flawmark " " str, " ", columns) + print "" + flaws++ } # ---------------------------------------------------------------------- @@ -2042,94 +2042,94 @@ function flaw(str, indented) # function fold(str, indent, cols, width, pos, lpos, npos) { - pos = 1 - #print "str: ", str; - #print "indent: ", indent; - #print "cols: ", cols; - insert = "\n" indent - width = cols - while (pos + width - 1 < length(str)) { - frag = substr(str, pos, width) - lpos = rindex(frag, " ") - npos = index(frag, "\n") - if (npos && npos < lpos) { - lpos = npos - } - if (! lpos) { - frag = substr(str, pos + width) - lpos = index(frag, " ") - if (lpos) { - lpos += width - } - } - if (lpos) { - #print "** before break :", "..." substr(str, pos+lpos-9, 8) - #print "** after break :", substr(str, pos+lpos, 8) "..." - str = substr(str, 1, pos + lpos - 2) insert substr(str, pos + lpos) - pos = pos + lpos + length(insert) - } else { - return str - } - width = cols - length(indent) - } - return str + pos = 1 + #print "str: ", str; + #print "indent: ", indent; + #print "cols: ", cols; + insert = "\n" indent + width = cols + while (pos + width - 1 < length(str)) { + frag = substr(str, pos, width) + lpos = rindex(frag, " ") + npos = index(frag, "\n") + if (npos && npos < lpos) { + lpos = npos + } + if (! lpos) { + frag = substr(str, pos + width) + lpos = index(frag, " ") + if (lpos) { + lpos += width + } + } + if (lpos) { + #print "** before break :", "..." substr(str, pos+lpos-9, 8) + #print "** after break :", substr(str, pos+lpos, 8) "..." + str = substr(str, 1, pos + lpos - 2) insert substr(str, pos + lpos) + pos = pos + lpos + length(insert) + } else { + return str + } + width = cols - length(indent) + } + return str } # ---------------------------------------------------------------------- function get_creation_date(doc, state, created, i) { - get_state(doc, state) - split("creationdate created submitted", keys, FS) - for (i in keys) { - key = keys[i] - if (key in state) { - created = state[key] - if (created == "None") { - created = "" - } - break - } - } - return created + get_state(doc, state) + split("creationdate created submitted", keys, FS) + for (i in keys) { + key = keys[i] + if (key in state) { + created = state[key] + if (created == "None") { + created = "" + } + break + } + } + return created } function get_draftcode(draftname, state, code) { - if (draftname) { - if ("deststatus" in state) { - status = tolower(state["deststatus"]) - if (status != "none") { - code = status2code[status] - } - } - } - return code + if (draftname) { + if ("deststatus" in state) { + status = tolower(state["deststatus"]) + if (status != "none") { + code = status2code[status] + } + } + } + return code } function get_draftname(ref, draftname) { - # print "** ref:", ref - if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9][^a-zA-Z0-9_-]/)) { - draftname = substr(ref, RSTART, RLENGTH - 4) - } else if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9]$/)) { - draftname = substr(ref, RSTART, RLENGTH - 3) - } else if (match(ref, /draft-[a-zA-Z0-9_-]+/)) { - draftname = substr(ref, RSTART, RLENGTH) - } else if (match(ref, /I-D\.[a-zA-Z0-9_-]+/)) { - draftname = "draft-" substr(ref, RSTART + 4, RLENGTH - 4) - } - # print "** doc:", draftname - return draftname + # print "** ref:", ref + if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9][^a-zA-Z0-9_-]/)) { + draftname = substr(ref, RSTART, RLENGTH - 4) + } else if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9]$/)) { + draftname = substr(ref, RSTART, RLENGTH - 3) + } else if (match(ref, /draft-[a-zA-Z0-9_-]+/)) { + draftname = substr(ref, RSTART, RLENGTH) + } else if (match(ref, /I-D\.[a-zA-Z0-9_-]+/)) { + draftname = "draft-" substr(ref, RSTART + 4, RLENGTH - 4) + } + # print "** doc:", draftname + return draftname } function get_draftrev(ref, draftrev) { - if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9]$/)) { - draftrev = substr(ref, RSTART + RLENGTH - 2, 2) - } else if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9][^a-zA-Z0-9_-]/)) { - draftrev = substr(ref, RSTART + RLENGTH - 3, 2) - } - return draftrev + if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9]$/)) { + draftrev = substr(ref, RSTART + RLENGTH - 2, 2) + } else if (match(ref, /draft-[a-zA-Z0-9_-]+-[0-9][0-9][^a-zA-Z0-9_-]/)) { + draftrev = substr(ref, RSTART + RLENGTH - 3, 2) + } + return draftrev } # ---------------------------------------------------------------------- @@ -2137,47 +2137,47 @@ function get_draftrev(ref, draftrev) # function get_para() { - para = strip($0) - while (((getline) > 0) && (text = strip($0)) != "") { - check_line() - if (para ~ /-$/) { - para = para text - } else if (para ~ /[A-Za-z0-9]\/$/ && text ~ /^[a-z0-9_-]+([)\/]|\.[a-z])/) { - para = para text - } else if (para ~ /[A-Za-z0-9]$/ && text ~ /^\/[a-z0-9_-]+([)\/]|\.[a-z])/) { - para = para text - } else if (para ~ /[0-9A-Fa-f]:$/ && text ~ /^[0-9A-Fa-f]+:/) { - para = para text - } else { - para = para " " text - } - } - return para + para = strip($0) + while (((getline) > 0) && (text = strip($0)) != "") { + check_line() + if (para ~ /-$/) { + para = para text + } else if (para ~ /[A-Za-z0-9]\/$/ && text ~ /^[a-z0-9_-]+([)\/]|\.[a-z])/) { + para = para text + } else if (para ~ /[A-Za-z0-9]$/ && text ~ /^\/[a-z0-9_-]+([)\/]|\.[a-z])/) { + para = para text + } else if (para ~ /[0-9A-Fa-f]:$/ && text ~ /^[0-9A-Fa-f]+:/) { + para = para text + } else { + para = para " " text + } + } + return para } function get_rfcnum(ref, num) { - for (;;) { - if (match(ref, /(RFC|rfc)[0-9][0-9]+/)) { - num = substr(ref, RSTART + 3, RLENGTH - 3) + 0 - } else if (match(ref, /(RFC|rfc)[ -][0-9][0-9]+/)) { - num = substr(ref, RSTART + 4, RLENGTH - 4) + 0 - } else if (match(ref, /(Request [Ff]or Comments) [0-9][0-9]+/)) { - num = substr(ref, RSTART + 21, RLENGTH - 21) + 0 - } else if (match(ref, /(Request [Ff]or Comments)( \([^\)]*\))? [0-9][0-9]+/)) { - num = substr(ref, RSTART + RLENGTH - 4, 4) + 0 - } else { - if (! num) { - note("Unexpected reference format, failed extracting the RFC number: " ref) - } - break - } - if (RSTART + RLENGTH <= 1) { - break - } - ref = substr(ref, RSTART + RLENGTH) - } - return num + for (;;) { + if (match(ref, /(RFC|rfc)[0-9][0-9]+/)) { + num = substr(ref, RSTART + 3, RLENGTH - 3) + 0 + } else if (match(ref, /(RFC|rfc)[ -][0-9][0-9]+/)) { + num = substr(ref, RSTART + 4, RLENGTH - 4) + 0 + } else if (match(ref, /(Request [Ff]or Comments) [0-9][0-9]+/)) { + num = substr(ref, RSTART + 21, RLENGTH - 21) + 0 + } else if (match(ref, /(Request [Ff]or Comments)( \([^\)]*\))? [0-9][0-9]+/)) { + num = substr(ref, RSTART + RLENGTH - 4, 4) + 0 + } else { + if (! num) { + note("Unexpected reference format, failed extracting the RFC number: " ref) + } + break + } + if (RSTART + RLENGTH <= 1) { + break + } + ref = substr(ref, RSTART + RLENGTH) + } + return num } # ---------------------------------------------------------------------- @@ -2185,75 +2185,75 @@ function get_rfcnum(ref, num) # function get_state(draft, state, quiet, count) { - for (key in state) { - delete state[key] - } - statefile = statusdir "/" draft ".state" - ## Not sure that this fallback handling is necessary. Keeping it commented out for now. - # if ( ( getline < statefile ) < 0 ) { - # close(statefile) - # note("... Trying to download missing state file for " draft " ...") - # command = "idnits --download '" draft " state' http://tools.ietf.org/draft/" draft "/state " statusdir "/" draft ".state 'Doc-tag: " draft "'" - # while ( (command | getline) > 0) print $0; - # } - while ((getline < statefile) > 0) { - if ($1 ~ /^Doc-/) { - count++ - key = substr($1, 5, length($1) - 5) - $1 = "" - value = strip($0) - sub(/;[^;]*$/, "", value) - state[key] = value - } - } - close(statefile) - datefile = statefile ".date" - if ((getline < datefile) > 0 && $0) { - state["downloaded"] = $0 - } else { - state["downloaded"] = "unsuccessful" - } - if (! count && ! quiet) { - comment("No information found for " draft " - is the name correct?") - } - return count + for (key in state) { + delete state[key] + } + statefile = statusdir "/" draft ".state" + ## Not sure that this fallback handling is necessary. Keeping it commented out for now. + # if ( ( getline < statefile ) < 0 ) { + # close(statefile) + # note("... Trying to download missing state file for " draft " ...") + # command = "idnits --download '" draft " state' http://tools.ietf.org/draft/" draft "/state " statusdir "/" draft ".state 'Doc-tag: " draft "'" + # while ( (command | getline) > 0) print $0; + # } + while ((getline < statefile) > 0) { + if ($1 ~ /^Doc-/) { + count++ + key = substr($1, 5, length($1) - 5) + $1 = "" + value = strip($0) + sub(/;[^;]*$/, "", value) + state[key] = value + } + } + close(statefile) + datefile = statefile ".date" + if ((getline < datefile) > 0 && $0) { + state["downloaded"] = $0 + } else { + state["downloaded"] = "unsuccessful" + } + if (! count && ! quiet) { + comment("No information found for " draft " - is the name correct?") + } + return count } function is_ipv6(addr) { - # We have to match either 8 parts separated by colons or fewer parts with one embedded '::' or fewer parts ending in '::': - if (addr ~ /^[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+$/ || addr ~ /([0-9A-Fa-f]+:)([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?:$/ || addr ~ /([0-9A-Fa-f]+:)([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?(:[0-9A-Fa-f]+)(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?$/) { - return 1 - } else { - return 0 - } + # We have to match either 8 parts separated by colons or fewer parts with one embedded '::' or fewer parts ending in '::': + if (addr ~ /^[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+:[0-9A-Fa-f]+$/ || addr ~ /([0-9A-Fa-f]+:)([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?:$/ || addr ~ /([0-9A-Fa-f]+:)([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?([0-9A-Fa-f]+:)?(:[0-9A-Fa-f]+)(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?(:[0-9A-Fa-f]+)?$/) { + return 1 + } else { + return 0 + } } # ---------------------------------------------------------------------- function jdn(date, part, year, month, day, a, y, m, d) { - split(date, part, "-") - year = part[1] - month = part[2] - sub(/^0/, "", month) - day = part[3] - sub(/^0/, "", day) - a = int((14 - month) / 12) - y = year + 4800 - a - m = month + 12 * a - 3 - d = day + int((153 * m + 2) / 5) + 365 * y + int(y / 4) - int(y / 100) + int(y / 400) - 32045 - return d + split(date, part, "-") + year = part[1] + month = part[2] + sub(/^0/, "", month) + day = part[3] + sub(/^0/, "", day) + a = int((14 - month) / 12) + y = year + 4800 - a + m = month + 12 * a - 3 + d = day + int((153 * m + 2) / 5) + 365 * y + int(y / 4) - int(y / 100) + int(y / 400) - 32045 + return d } # ---------------------------------------------------------------------- # list() function list(str, lst) { - split(str, lst, FS) - for (i in lst) { - lst[lst[i]] = i - delete lst[i] - } + split(str, lst, FS) + for (i in lst) { + lst[lst[i]] = i + delete lst[i] + } } # ---------------------------------------------------------------------- @@ -2261,27 +2261,27 @@ function list(str, lst) # function markdiff(p1, p2, prefixlen, para2, suffix, leading, point, temp) { - prefixlen = 0 - para2 = p2 - gsub(/\. +/, ". ", p1) - gsub(/\. +/, ". ", p2) - do { - if (substr(p1, 1, 1) == substr(p2, 1, 1)) { - p1 = substr(p1, 2) - p2 = substr(p2, 2) - } else { - break - } - prefixlen++ - } while (length(p1) && length(p2)) - prefix = substr(para2, 1, prefixlen) - suffix = substr(para2, prefixlen + 1) - leading = length(prefix) - rindex(prefix, "\n") - temp = substr(prefix, length(prefix) - leading) - spacefix = gsub(/\. +/, ". ", temp) - point = index(suffix, "\n") - marker = substr("........................................................................", 1, leading + spacefix) "^\n" - return (prefix substr(suffix, 1, point) marker substr(suffix, point + 1)) + prefixlen = 0 + para2 = p2 + gsub(/\. +/, ". ", p1) + gsub(/\. +/, ". ", p2) + do { + if (substr(p1, 1, 1) == substr(p2, 1, 1)) { + p1 = substr(p1, 2) + p2 = substr(p2, 2) + } else { + break + } + prefixlen++ + } while (length(p1) && length(p2)) + prefix = substr(para2, 1, prefixlen) + suffix = substr(para2, prefixlen + 1) + leading = length(prefix) - rindex(prefix, "\n") + temp = substr(prefix, length(prefix) - leading) + spacefix = gsub(/\. +/, ". ", temp) + point = index(suffix, "\n") + marker = substr("........................................................................", 1, leading + spacefix) "^\n" + return (prefix substr(suffix, 1, point) marker substr(suffix, point + 1)) } # ---------------------------------------------------------------------- @@ -2289,81 +2289,81 @@ function markdiff(p1, p2, prefixlen, para2, suffix, leading, point, temp) # function match_para(para, name1, name2, name3, name4) { - name[1] = name1 - name[2] = name2 - name[3] = name3 - name[4] = name4 - for (i = 1; i <= 4; i++) { - pat[i] = bp[name[i]] - } - orig = para - gsub(/ +/, " ", para) - pattern = "" - for (i = 1; i <= 4; i++) { - if (! pat[i]) { - almost_boilerplate[name[1]] = orig - if (option_debug && option_pass2) { - print "** End of patterns **" - } - return 0 - } - gsub(/. /, ". ?", pat[i]) - pattern = pattern pat[i] - if (option_debug && option_pass2) { - print "\n----", name[i], "----" - print "line", FNR, "\n" - print "" - print "'" para "'" - print "" - print "'" pattern "'" - print "" - if (para ~ pattern) { - print "** Matches **" - } else { - print "** No Match **" - } - } - if (para ~ pattern) { - for (j = 1; j <= i; j++) { - has[name[j]] = FNR - 1 - } - if (option_debug && option_pass2) { - print "** Exit **" - } - return 1 - } - sub(/ *\$?$/, " +", pattern) - if (para ~ pattern) { - if (option_debug && option_pass2) { - print "** Match with trailing text **" - } - for (j = 1; j <= i; j++) { - has[name[j]] = FNR - 1 - } - if (! pat[i + 1]) { - if (option_debug && option_pass2) { - print "** Exit: end of patterns **" - } - return 1 - } - } else { - if (option_debug && option_pass2) { - print "** Exit: No prefix match **" - } - for (k = 1; k < i; k++) { - pref = pat[k] - sub(/ *\$?$/, " +", pref) - sub(pref, "", orig) - } - stripped_orig = strip(orig) - if (index(substr(bp[name[i]], 1, 48), substr(stripped_orig, 1, 32))) { - almost_boilerplate[name[i]] = orig - } - return 0 - } - } - almost_boilerplate[name[1]] = orig - return 0 + name[1] = name1 + name[2] = name2 + name[3] = name3 + name[4] = name4 + for (i = 1; i <= 4; i++) { + pat[i] = bp[name[i]] + } + orig = para + gsub(/ +/, " ", para) + pattern = "" + for (i = 1; i <= 4; i++) { + if (! pat[i]) { + almost_boilerplate[name[1]] = orig + if (option_debug && option_pass2) { + print "** End of patterns **" + } + return 0 + } + gsub(/. /, ". ?", pat[i]) + pattern = pattern pat[i] + if (option_debug && option_pass2) { + print "\n----", name[i], "----" + print "line", FNR, "\n" + print "" + print "'" para "'" + print "" + print "'" pattern "'" + print "" + if (para ~ pattern) { + print "** Matches **" + } else { + print "** No Match **" + } + } + if (para ~ pattern) { + for (j = 1; j <= i; j++) { + has[name[j]] = FNR - 1 + } + if (option_debug && option_pass2) { + print "** Exit **" + } + return 1 + } + sub(/ *\$?$/, " +", pattern) + if (para ~ pattern) { + if (option_debug && option_pass2) { + print "** Match with trailing text **" + } + for (j = 1; j <= i; j++) { + has[name[j]] = FNR - 1 + } + if (! pat[i + 1]) { + if (option_debug && option_pass2) { + print "** Exit: end of patterns **" + } + return 1 + } + } else { + if (option_debug && option_pass2) { + print "** Exit: No prefix match **" + } + for (k = 1; k < i; k++) { + pref = pat[k] + sub(/ *\$?$/, " +", pref) + sub(pref, "", orig) + } + stripped_orig = strip(orig) + if (index(substr(bp[name[i]], 1, 48), substr(stripped_orig, 1, 32))) { + almost_boilerplate[name[i]] = orig + } + return 0 + } + } + almost_boilerplate[name[1]] = orig + return 0 } # ---------------------------------------------------------------------- @@ -2371,33 +2371,33 @@ function match_para(para, name1, name2, name3, name4) # function newandolderr(old, new) { - newname = expandname(new) - oldname = expandname(old) - str = sprintf("Found new %s boilerplate, which is fine, but *also* found old boilerplate from %s on line %s.", newname, oldname, has[old]) - err(str) - if (option_verbose && option_pass2) { - showsection(old, 1) - } + newname = expandname(new) + oldname = expandname(old) + str = sprintf("Found new %s boilerplate, which is fine, but *also* found old boilerplate from %s on line %s.", newname, oldname, has[old]) + err(str) + if (option_verbose && option_pass2) { + showsection(old, 1) + } } function nnnote(str) { - if (option_verbose >= 2) { - if (option_pass1) { - printf "%s(%d): %s.\n", FILENAME, FNR, str - } else { - print fold(" " notemark " " str, " ", columns) - } - } + if (option_verbose >= 2) { + if (option_pass1) { + printf "%s(%d): %s.\n", FILENAME, FNR, str + } else { + print fold(" " notemark " " str, " ", columns) + } + } } function nnote(str) { - if (option_verbose) { - if (option_pass1) { - printf "%s(%d): %s.\n", FILENAME, FNR, str - } - } + if (option_verbose) { + if (option_pass1) { + printf "%s(%d): %s.\n", FILENAME, FNR, str + } + } } # ---------------------------------------------------------------------- @@ -2405,11 +2405,11 @@ function nnote(str) # function note(str) { - if (option_pass1) { - printf "%s(%d): %s.\n", FILENAME, FNR, str - } else { - print fold(" " notemark " " str, " ", columns) - } + if (option_pass1) { + printf "%s(%d): %s.\n", FILENAME, FNR, str + } else { + print fold(" " notemark " " str, " ", columns) + } } # ---------------------------------------------------------------------- @@ -2417,18 +2417,18 @@ function note(str) # function oldandnewerr(old, new) { - if (! new in has) { - print "?? internal error, expected a table match on %s", new - exit - } - newname = expandname(new) - oldname = expandname(old) - str = sprintf("Found boilerplate matching %s (on line %s), which is fine, but *also* found old %s text on line %s.", newname, has[new], oldname, has[old]) - err(str) - if (option_verbose && option_pass2) { - showsection(old, 1) - showsection(new, 1) - } + if (! new in has) { + print "?? internal error, expected a table match on %s", new + exit + } + newname = expandname(new) + oldname = expandname(old) + str = sprintf("Found boilerplate matching %s (on line %s), which is fine, but *also* found old %s text on line %s.", newname, has[new], oldname, has[old]) + err(str) + if (option_verbose && option_pass2) { + showsection(old, 1) + showsection(new, 1) + } } # ---------------------------------------------------------------------- @@ -2436,27 +2436,27 @@ function oldandnewerr(old, new) # function olderr(old) { - oldname = expandname(old) - str = sprintf("Found old boilerplate from %s on line %s.", oldname, has[old]) - comment(str) - if (option_verbose && option_pass2) { - showsection(old, 1, "The obsolete ", " text") - } + oldname = expandname(old) + str = sprintf("Found old boilerplate from %s on line %s.", oldname, has[old]) + comment(str) + if (option_verbose && option_pass2) { + showsection(old, 1, "The obsolete ", " text") + } } function refcomment(msg, num, tag, info, numstr) { - numstr = sprintf("%d", num) - if (numstr in obsoleted) { - info = obsoleted[numstr] - gsub(" ", ", RFC ", info) - info = " (Obsoleted by " substr(info, 3) ")" - } - if (tag ~ numstr) { - comment(sprintf("%s: RFC %4d%s", msg, num, info)) - } else { - comment(sprintf("%s: RFC %4d (ref. '%s')%s", msg, num, tag, info)) - } + numstr = sprintf("%d", num) + if (numstr in obsoleted) { + info = obsoleted[numstr] + gsub(" ", ", RFC ", info) + info = " (Obsoleted by " substr(info, 3) ")" + } + if (tag ~ numstr) { + comment(sprintf("%s: RFC %4d%s", msg, num, info)) + } else { + comment(sprintf("%s: RFC %4d (ref. '%s')%s", msg, num, tag, info)) + } } # ---------------------------------------------------------------------- @@ -2464,17 +2464,17 @@ function refcomment(msg, num, tag, info, numstr) # function referr(msg, num, tag, comment, info, numstr) { - numstr = sprintf("%d", num) - if (numstr in obsoleted) { - info = obsoleted[numstr] - gsub(" ", ", RFC ", info) - info = " (Obsoleted by " substr(info, 3) ")" - } - if (tag ~ numstr) { - errc(sprintf("%s: RFC %4d%s%s", msg, num, info, comment)) - } else { - errc(sprintf("%s: RFC %4d (ref. '%s')%s%s", msg, num, tag, info, comment)) - } + numstr = sprintf("%d", num) + if (numstr in obsoleted) { + info = obsoleted[numstr] + gsub(" ", ", RFC ", info) + info = " (Obsoleted by " substr(info, 3) ")" + } + if (tag ~ numstr) { + errc(sprintf("%s: RFC %4d%s%s", msg, num, info, comment)) + } else { + errc(sprintf("%s: RFC %4d (ref. '%s')%s%s", msg, num, tag, info, comment)) + } } # ---------------------------------------------------------------------- @@ -2482,803 +2482,803 @@ function referr(msg, num, tag, comment, info, numstr) # function report(filename) { - if (skip_file) { - return - } - if (option_pass1) { - return - } - if (option_status) { - if (! (tolower(option_status) in status2code)) { - note(sprintf("Unexpected value in --status switch ('%s'), ignoring it. (Use one of 'informational', 'experimental', 'bcp', 'ps', 'ds', 'standard'.)", option_status)) - } else { - intended_status = tolower(option_status) - } - } - if (got_input) { - is_rfc = (filename ~ /[Rr][Ff][Cc][0-9]+\.txt$/) - draftname = full_docname - sub(/\.[a-z]+$/, "", draftname) - sub(/-[0-9][0-9]$/, "", draftname) - get_state(draftname, state, quiet = 1) - destcode = get_draftcode(draftname, state) - if (option_submitcheck) { - printf ("\n Showing Errors (" errmark "), Flaws (" flawmark "), Warnings (" warnmark "), and Comments (" infomark ").\n") - print (" Errors MUST be fixed before draft submission. Flaws SHOULD be fixed before draft submission.") - } - announce("Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info):") - errcount = errors - flawcount = flaws - warncount = warnings - commentcount = comments - # 12 Sep 2009 values below are valid during the post-28-dec-2009 transition - if (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"] || has["trust-28-dec-2009_6_b_i_p2"] || has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"]) { - # We have some text from the current Trust Provisions boilerplate. Check that we don't have older - # boilerplate, too. - for (bpname in bp) { - if (bpname ~ /^rfc2026/ || bpname ~ /^rfc3667/ || bpname ~ /^rfc3978/ || bpname ~ /^rfc3979/) { - if (has[bpname] && ! (bpname ~ "_now")) { - newandolderr(bpname, "IETF Trust Provisions of 12 Sep 2009") - } - } - } - if (! is_rfc) { - if (! (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"])) { - sectionerr("trust-28-dec-2009_6_a", "Notice of Compliance with BCP 78 and BCP 79 according to " "IETF Trust Provisions of 28 Dec 2009, Section 6.a " "or Provisions of 12 Sep 2009, Section 6.a") - } - } - if (! has["trust-28-dec-2009_6_b_i_p2"]) { - sectionerr("trust-28-dec-2009_6_b_i_p2", "IETF Trust Provisions of 28 Dec 2009, Section 6.b Copyright Notice") - } - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { - if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-12-sep-2009_6_b_p3"])) { - sectionerr("trust-28-dec-2009_6_b_i_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.i or Provisions of 12 Sep 2009 Section 6.b") - if (has["trust-28-dec-2009_6_b_ii_p3"]) { - comment("It seems you're using the 'non-IETF stream' Licence Notice instead") - } - } - } else if (full_docname ~ /^draft-(iab|irtf|rfced|rfc-editor)-/) { - if (! (has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { - sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") - if (has["trust-28-dec-2009_6_b_i_p3"]) { - comment("It seems you're using the 'IETF stream' Licence Notice instead") - } - } - } else if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { - sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") - } - # The following is just an informational note because we've emitted an error earlier: - if (has["trust-12-feb-2009_6_b_p3"]) { - note("(You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Feb 2009 rather than one of the newer Notices. " "See https://trustee.ietf.org/license-info/.)\n") - } - if (has["trust-12-sep-2009_6_b_p3"]) { - err("You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Sep 2009 rather than the newer Notice from 28 Dec 2009. " "(See https://trustee.ietf.org/license-info/)") - } - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { - if (has["trust-28-dec-2009_6_c_i"]) { - warn("The document has an IETF Trust Provisions of 28 Dec 2009, Section 6.c(i) Publication Limitation clause.") - } - if (has["trust-28-dec-2009_6_c_ii"]) { - err("The document has an IETF Trust Provisions, 28 Dec 2009, Section 6.c(ii) Publication Limitation clause.") - } - } else { - if (has["trust-28-dec-2009_6_c_i"]) { - comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(i) Publication Limitation clause.") - } - if (has["trust-28-dec-2009_6_c_ii"]) { - comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(ii) Publication " "Limitation clause. If this document is intended for submission to the IESG for " "publication, this constitutes an error.") - } - } - } else if ((has["rfc3667_5_1"] || has["rfc3978_5_1_a"] || has["rfc3978_5_1"] || has["rfc3978_5_2b"] || has["rfc3978_5_3"] || has["rfc3978_5_5"] || has["rfc3978_5_5_u4748"] || has["rfc3979_5_p1"] || has["rfc3979_5_p2"] || has["rfc3979_5_p3"])) { - err("It looks like you're using RFC 3978 boilerplate. You should update this to the " "boilerplate described in the IETF Trust License Policy document (see " "https://trustee.ietf.org/license-info), which is required now.") - if (has["rfc3667_5_1"]) { - olderr("rfc3667_5_1") - } - if (has["rfc3978_5_1_a"]) { - olderr("rfc3978_5_1_a") - } - if (has["rfc3978_5_1"]) { - olderr("rfc3978_5_1") - } - if (has["rfc3978_5_2b"]) { - olderr("rfc3978_5_2b") - } - if (has["rfc3978_5_3"]) { - olderr("rfc3978_5_3") - } - if (has["rfc3978_5_5"]) { - olderr("rfc3978_5_5") - } - if (has["rfc3978_5_5_u4748"]) { - olderr("rfc3978_5_5_u4748") - } - if (has["rfc3979_5_p1"]) { - olderr("rfc3979_5_p1") - } - if (has["rfc3979_5_p2"]) { - olderr("rfc3979_5_p2") - } - if (has["rfc3979_5_p3"]) { - olderr("rfc3979_5_p3") - } - # Ok, so we have some 3978/3979 boilerplate - make sure we don't *also* have some - # lingering old boilerplate... - if (has["rfc3978_5_1"]) { - if (has["rfc3667_5_1"]) { - oldandnewerr("rfc3667_5_1", "rfc3978_5_1") - } - } - if (has["rfc3978_5_4_p1"]) { - if (has["rfc2026_10_4C_p1"]) { - oldandnewerr("rfc2026_10_4C_p1", "rfc3978_5_4_p1") - } - } - if (has["rfc3978_5_4_p1_u4748"]) { - if (has["rfc2026_10_4C_p1"]) { - oldandnewerr("rfc2026_10_4C_p1", "rfc3978_5_4_p1_u4748") - } - } - if (has["rfc3978_5_4_p1_u4748"]) { - if (has["rfc3978_5_4_p1"]) { - oldandnewerr("rfc3978_5_4_p1", "rfc3978_5_4_p1_u4748") - } - } - if (has["rfc3978_5_4_p1_u4748_e"]) { - if (has["rfc3978_5_4_p1"]) { - oldandnewerr("rfc3978_5_4_p1", "rfc3978_5_4_p1_u4748_e") - } - } - if (has["rfc3978_5_4_p1_u4748"]) { - if (has["rfc3978_5_4_p1_e"]) { - oldandnewerr("rfc3978_5_4_p1_e", "rfc3978_5_4_p1_u4748") - } - } - if (has["rfc3978_5_5"]) { - if (has["rfc2026_10_4C_p4"]) { - oldandnewerr("rfc2026_10_4C_p4", "rfc3978_5_5") - } - } - if (has["rfc3978_5_5_u4748"]) { - if (has["rfc2026_10_4C_p4"]) { - oldandnewerr("rfc2026_10_4C_p4", "rfc3978_5_5_u4748") - } - } - if (has["rfc3978_5_5_u4748"]) { - if (has["rfc3978_5_5"]) { - oldandnewerr("rfc3978_5_5", "rfc3978_5_5_u4748") - } - } - if (has["rfc3979_5_p1"]) { - if (has["rfc2026_10_4A"]) { - oldandnewerr("rfc2026_10_4A", "rfc3979_5_p1") - } - } - if (has["rfc3979_5_p3"]) { - if (has["rfc2026_10_4B"]) { - oldandnewerr("rfc2026_10_4B", "rfc3979_5_p3") - } - } - if (has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) { - err("The document claims conformance with section 10 of RFC 2026, but uses " "some RFC 3978/3979 boilerplate. As RFC 3978/3979 replaces section 10 of " "RFC 2026, you should not claim conformance with it if you have changed " "to using RFC 3978/3979 boilerplate.") - } - if (! (has["rfc3978_5_1"]) && ! is_rfc) { - sectionerr("rfc3978_5_1", "RFC 3978 Section 5.1 IPR Disclosure Acknowledgement") - } - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { - if (has["rfc3978_5_2b"]) { - err("The document has an RFC 3978 Section 5.2(b) Derivative Works Limitation clause.") - } - if (has["rfc3978_5_3"]) { - err("The document has an RFC 3978 Section 5.3 Publication Limitation clause.") - } - } else { - if (has["rfc3978_5_2b"]) { - comment("The document has an RFC 3978 Section 5.2(b) Derivative Works Limitation clause. " "If this document is intended for submission to the IESG for publication, this " "constitutes an error.") - } - if (has["rfc3978_5_3"]) { - comment("The document has an RFC 3978 Section 5.3 Publication Limitation clause. " "If this document is intended for submission to the IESG for publication, this " "constitutes an error.") - } - } - if (! has["rfc3978_5_4_p1_u4748"]) { - if (has["rfc3978_5_4_p1"]) { - err("This document has an original RFC 3978 Section 5.4 Copyright Line, " "instead of the newer IETF Trust Copyright according " "to RFC 4748.") - } else { - sectionerr("rfc3978_5_4_p1_u4748", "RFC 3978 Section 5.4 (updated by RFC 4748) Copyright Line") - } - } - if (! has["rfc3978_5_4_p2"]) { - sectionerr("rfc3978_5_4_p2", "RFC 3978 Section 5.4 Reference to BCP 78") - } - if (! has["rfc3978_5_5_u4748"]) { - if (has["rfc3978_5_5"]) { - err("This document has an original RFC 3978 Section 5.5 Disclaimer, " "instead of the newer disclaimer which includes the IETF Trust according " "to RFC 4748.") - } else { - sectionerr("rfc3978_5_5_u4748", "RFC 3978 Section 5.5 (updated by RFC 4748) Disclaimer") - } - } - if (! has["rfc3979_5_p1"]) { - sectionerr("rfc3979_5_p1", "RFC 3979 Section 5, para. 1 IPR Disclosure Acknowledgement") - if (has["rfc2026_10_4A"]) { - note("( - It does however have an RFC 2026 Section 10.4(A) Disclaimer.)") - } - } - if (! has["rfc3979_5_p2"]) { - sectionerr("rfc3979_5_p2", "RFC 3979 Section 5, para. 2 IPR Disclosure Acknowledgement") - } - if (! has["rfc3979_5_p3"]) { - sectionerr("rfc3979_5_p3", "RFC 3979 Section 5, para. 3 IPR Disclosure Invitation") - if (has["rfc2026_10_4B"]) { - note("( - It does however have an RFC 2026 Section 10.4(B) IPR Disclosure Invitation.)") - } - } - if (has["rfc3667_3_claim"] || (has["rfc3667_5_1"] || has["rfc3978_5_1_a"]) && ! has["rfc3978_5_1"]) { - err("The document uses RFC 3667 boilerplate or RFC 3978-like " "boilerplate instead of verbatim RFC 3978 boilerplate. After 6 May 2005, " "submission of drafts without verbatim RFC 3978 boilerplate is not " "accepted.") - note("The following non-3978 patterns matched text found in the document. That text should be removed or replaced:\n") - if (has["rfc3667_3_claim"]) { - showsection("rfc3667_3_claim", 2) - } - if (has["rfc3667_5_1"]) { - showsection("rfc3667_5_1", 2) - } - if (has["rfc3978_5_1_a"] && ! has["rfc3978_5_1"]) { - showsection("rfc3978_5_1_a", 2) - } - } - if ((has["rfc3978_5_4_p1"] && has["rfc3978_5_4_p1_e"]) || (has["rfc3978_5_4_p1_u4748"] && has["rfc3978_5_4_p1_u4748_e"])) { - warn("In addition to a regular copyright notice, the document also has a " "copyright notice embedded in the text.") - } - } else if ((has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"] || has["rfc2026_10_4C_p2"] || has["rfc2026_10_4C_p3"] || has["rfc2026_10_4C_p4"])) { - if (option_verbose) { - print "" - if (has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) { - note(" [Claims RFC 2026 conformance...]") - } - if (has["rfc2026_10_4C_p1"]) { - note(" [Has RFC 2026 Sec. 10.4 para. 1...]") - } - if (has["rfc2026_10_4C_p2"]) { - note(" [Has RFC 2026 Sec. 10.4 para. 2...]") - } - if (has["rfc2026_10_4C_p3"]) { - note(" [Has RFC 2026 Sec. 10.4 para. 3...]") - } - if (has["rfc2026_10_4C_p4"]) { - note(" [Has RFC 2026 Sec. 10.4 para. 4...]") - } - print "" - } - err("Looks like you're using RFC 2026 boilerplate. This must be updated to follow RFC 3978/3979, as updated by RFC 4748.") - } else { - if (some_copyright) { - copyright_msg = " Found some kind of copyright notice around line " some_copyright " but it does not match any copyright boilerplate known by this tool." - } else { - copyright_msg = "" - } - err("Cannot find the required boilerplate sections (Copyright, IPR, etc.) in this document." copyright_msg) - note("Expected boilerplate is as follows today (" today ") according to https://trustee.ietf.org/license-info :\n") - showsection("trust-28-dec-2009_6_a") - showsection("trust-28-dec-2009_6_b_i_p2") - showsection("trust-28-dec-2009_6_b_i_p3") - } - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { - note("No issues found here.") - } - if (! is_rfc) { - announce("Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt:") - errcount = errors - flawcount = flaws - warncount = warnings - commentcount = comments - if (! has_id_indication) { - errg("Missing document type: Expected \"INTERNET-DRAFT\" in the upper left hand corner of the first page") - } - if (! has_expiration) { - errg("Missing expiration date. The document expiration date should appear on the first and last page.") - } - if (! (has["1id_guidelines_p1"] || has["1id_guidelines_p1a"])) { - sectionerr("1id_guidelines_p1", "1id_guidelines paragraph about Internet-Drafts being working documents") - } - if (! (has["1id_guidelines_p2"] || has["1id_guidelines_p2a"])) { - sectionerr("1id_guidelines_p2", "1id_guidelines paragraph about 6 months document validity") - } - if (! (has["1id_guidelines_p3"] || has["1id_guidelines_p3a"] || has["1id_guidelines_p1a"])) { - sectionerr("1id_guidelines_p3", "1id_guidelines paragraph about the list of current Internet-Drafts") - } - if (! (has["1id_guidelines_p4"] || has["1id_guidelines_p4a"] || has["1id_guidelines_p1a"])) { - sectionerr("1id_guidelines_p4", "1id_guidelines paragraph about the list of Shadow Directories") - } - if (has["1id_guidelines_p1a"] && has["1id_guidelines_p3"]) { - newandolderr("1id_guidelines_p3", "1id_guidelines_p1a") - } - if (has["1id_guidelines_p1a"] && has["1id_guidelines_p3a"]) { - newandolderr("1id_guidelines_p3a", "1id_guidelines_p1a") - } - if (has["1id_guidelines_p1a"] && has["1id_guidelines_p4"]) { - newandolderr("1id_guidelines_p4", "1id_guidelines_p1a") - } - if (has["1id_guidelines_p1a"] && has["1id_guidelines_p4a"]) { - newandolderr("1id_guidelines_p4a", "1id_guidelines_p1a") - } - if (has_docname) { - file_docname = option_filename - # Get rid of path and extension - sub(".*/", "", file_docname) - sub(/\.(txt|pdf|xml|doc|nr)$/, "", file_docname) - sub(".*/", "", full_docname) - sub(/\.(txt|pdf|xml|doc)$/, "", full_docname) - if (good_docname != full_docname || full_docname ~ /[^a-z0-9-]/) { - errg(sprintf("Bad filename characters: the document name given in the document, '%s', contains other characters than digits, lowercase letters and dash.", full_docname)) - } else if (file_docname ~ /[^a-z0-9-]/) { - errg(sprintf("Bad filename characters: the file name of the draft, '%s', contains other characters than digits, lowercase letters and dash.", file_docname)) - } - if (! match(full_docname, /.*-[0-9][0-9]$/)) { - errg(sprintf("Missing revision: the document name given in the document, '%s', does not give the document revision number", full_docname)) - } - doc_has_empty_source = 0 - if (match(full_docname, /^draft--/)) { - doc_has_empty_source = 1 - errg(sprintf("Empty name element: the document name given in the document, '%s', lacks the source element (it starts with 'draft--'). See https://www.ietf.org/id-info/1id-guidelines.txt, section 7, on how to construct a good document name.", full_docname)) - } - if (match(full_docname, /--[0-9][0-9]$/)) { - errg(sprintf("Negative revision number: the document name given in the document, '%s', seems to have a negative revision number (it ends with '--%s'). See https://www.ietf.org/id-info/1id-guidelines.txt, section 7, on how to construct a good document name.", full_docname, substr(full_docname, length(full_docname) - 1))) - } - if (! match(full_docname, /^draft-[^-]+-.+-[0-9][0-9](\.[a-z]+)?$/)) { - if (! doc_has_empty_source) { - flaw(sprintf("Missing draftname component: the document name given in the document, '%s', does not seem to contain all the document name components required ('draft' prefix, document source, document name, and revision) -- see https://www.ietf.org/id-info/guidelines#naming for more information.", full_docname)) - } - } - if (length(file_docname) > length(full_docname)) { - long_docname = file_docname - } else { - long_docname = full_docname - } - sub(/-[0-9][0-9]$/, "", long_docname) - if (length(long_docname) > 50) { - errg(sprintf("Too long document name: The document name (without revision number), '%s', is %d characters long, but may be at most 50 characters", long_docname, length(long_docname))) - } - if (file_docname && file_docname != full_docname) { - warn(sprintf("Mismatching filename: the document gives the document name as '%s', but the file name used is '%s'", full_docname, file_docname)) - } - } else { - errg("Expected the document's filename to be given on the first page, but didn't find any") - } - if (has["rfc3978_5_1"] > firstpagelength && ! is_rfc) { - errg("An " expandname("rfc3978_5_1") " paragraph was found, but not on the first page, as required.") - } - # According to the nits page we should be comparing to 15 here, but - # that may be without the boilerplate - and practice seems to permit - # also 16 pages including boilerplate, so... - if (! has_toc && ((pagecount > 16) || (FNR > 50 * 16))) { - errw("The document is more than 15 pages and seems to lack a Table of Contents.") - } - if (nonascii && ! option_nonascii) { - warn(sprintf("There %s %d instance%s of lines with non-ascii characters in the document.", (nonascii == 1 ? "is" : "are"), nonascii, (nonascii == 1 ? "" : "s"))) - } - if (length(intended_status) == 0) { - warn("No 'Intended status' indicated for this document; assuming Proposed Standard") - intended_status = "proposed standard" - } - if (maxpagelength > 58) { - warnc(sprintf("The page length should not exceed 58 lines per page, " "but there was %d longer page%s, the longest (page %d) being %d lines", longpagecount, (longpagecount == 1 ? "" : "s"), longestpage, maxpagelength)) - } - if (pagecount > formfeedcount + 1) { - warnc(sprintf("It seems as if not all pages are separated by form feeds - " "found %d form feeds but %d page%s", formfeedcount, pagecount, (pagecount == 1 ? "" : "s"))) - } - if (missing_nroff_postprocessing) { - comment(sprintf("Found %d instances of the string 'FORMFEED[Page...' -- is this a case of missing nroff postprocessing?", missing_nroff_postprocessing)) - } - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { - note("No issues found here.") - } - } - if (option_submitcheck) { - announce("Running in submission checking mode -- *not* checking nits according to https://www.ietf.org/id-info/checklist .") - } else { - announce("Checking nits according to https://www.ietf.org/id-info/checklist :") - errcount = errors - flawcount = flaws - warncount = warnings - commentcount = comments - if (! has_abstract) { - err("The document seems to lack an Abstract section.", indented_abstract) - } - if (! has_intro) { - errc("The document seems to lack an Introduction section.", indented_intro) - } - if (! has_security) { - errc("The document seems to lack a Security Considerations section.", indented_security) - } - if (is_rfc) { - if (! has_iana) { - comment("The document seems to lack an IANA Considerations section. ", indented_iana) - } - } else if (! has_iana) { - errc("The document seems to lack an IANA Considerations section. " "(See Section 2.2 of https://www.ietf.org/id-info/checklist for how " "to handle the case when there are no actions for IANA.)", indented_iana) - } - if (! has_addr) { - errc("The document seems to lack an Authors' Addresses Section.") - } - if (has_refs && ! has_splitrefs) { - errc("The document seems to lack separate sections for Informative/Normative References. " "All references will be assumed normative when checking for downward references.") - } - if (option_list_matches) { - print fold(" Boilerplate matches:", " ", columns) - for (n in has) { - if (n) { - note(sprintf("Found", n, "on line", has[n])) - } - } - print "" - } - if (spacing > 50) { - errc(sprintf("There %s %d instance%s of weird spacing in the document. " "Is it really formatted ragged-right, rather than justified?", (spacing == 1 ? "is" : "are"), spacing, (spacing == 1 ? "" : "s"))) - } - if (longlines) { - msg = sprintf("There %s %d instance%s of too long lines in the document, " "the longest one being %d character%s in excess of 72.", (longlines == 1 ? "is" : "are"), longlines, (longlines == 1 ? "" : "s"), excesslength, ((excesslength > 1) ? "s" : "")) - if (! option_submitcheck) { - errc(msg) - } else { - warn(msg) - } - } - if (controlchars) { - errc(sprintf("There %s %d instance%s of lines with control characters in the document.", (controlchars == 1 ? "is" : "are"), controlchars, (controlchars == 1 ? "" : "s"))) - } - if (abstract_references) { - list(abstract_references, ref_list) - ref_str = "" - for (i in ref_list) { - if (ref_str) { - ref_str = ref_str ", " - } - ref_str = ref_str i - } - errc("The abstract seems to contain references (" ref_str "), which it shouldn't. Please replace those with straight textual mentions of the documents in question.") - } - if (badfqdns) { - warnc(sprintf("There %s %d instance%s of lines with " "non-RFC2606-compliant FQDNs in the document.", (controlchars == 1 ? "is" : "are"), badfqdns, (badfqdns == 1 ? "" : "s"))) - } - if (badipv4addr) { - warnc(sprintf("There %s %d instance%s of lines with " "non-RFC6890-compliant IPv4 addresses in the document. " "If these are example addresses, they should be changed.", (controlchars == 1 ? "is" : "are"), badipv4addr, (badipv4addr == 1 ? "" : "s"))) - } - if (mcastipv4addr) { - warnc(sprintf("There %s %d instance%s of lines with " "multicast IPv4 addresses in the document. " "If these are generic example addresses, they should be changed " "to use the 233.252.0.x range defined in RFC 5771", (controlchars == 1 ? "is" : "are"), mcastipv4addr, (mcastipv4addr == 1 ? "" : "s"))) - } - if (privipv4addr) { - warnc(sprintf("There %s %d instance%s of lines with " "private range IPv4 addresses in the document. " "If these are generic example addresses, they should be changed " "to use any of the ranges defined in RFC 6890 (or successor): " "192.0.2.x, 198.51.100.x or 203.0.113.x.", (controlchars == 1 ? "is" : "are"), privipv4addr, (privipv4addr == 1 ? "" : "s"))) - } - if (badipv6addr) { - warnc(sprintf("There %s %d instance%s of lines with " "non-RFC3849-compliant IPv6 addresses in the document. " "If these are example addresses, they should be changed.", (controlchars == 1 ? "is" : "are"), badipv6addr, (badipv6addr == 1 ? "" : "s"))) - } - if (ulipv6addr) { - warnc(sprintf("There %s %d instance%s of lines with " "Unique Local Unicast IPv6 addresses (RFC 4193) in the document. " "If these are generic example addresses, they should be changed", "to use the 2001:DB8::/32 range defined in RFC 4291.", (controlchars == 1 ? "is" : "are"), ulipv6addr, (ulipv6addr == 1 ? "" : "s"))) - } - if (llipv6addr) { - warnc(sprintf("There %s %d instance%s of lines with " "Link Local Unicast IPv6 addresses (RFC 4291) in the document. " "If these are generic example addresses, they should be changed", "to use the 2001:DB8::/32 range defined in RFC 4291.", (controlchars == 1 ? "is" : "are"), llipv6addr, (llipv6addr == 1 ? "" : "s"))) - } - if (ipv4_example_addr && ! ipv6_example_addr) { - comment("The document has examples using IPv4 documentation addresses " "according to RFC6890, but does not use any IPv6 documentation " "addresses. Maybe there should be IPv6 examples, too?") - } - if (keywords && ! has["rfc2119_p2"] && ! has["rfc2119_p2a"] ! has["rfc8174_p11"]) { - # Check whether there is a reference to RFC 2119 at all - for (reftag in ref_text) { - if (ref_text[reftag] ~ /RFC[- ]?2119/) { - found_2119_ref = ref_def[reftag] - } - } - if (! found_2119_ref) { - sectionerr("rfc8174_p11", "both a reference to RFC 2119 and the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords", option_checklistwarn) - if (option_verbose <= 1) { - for (i = 1; i <= 5; i++) { - if (i in rfc2119line) { - fnr = rfc2119line[i] - printf " RFC 2119 keyword, line %d: '...%s...'\n", fnr, line[fnr] - } - } - if (keywords > 5) { - note(sprintf("(%d more instance%s...)", keywords - 5, (keywords - 5 == 1 ? "" : "s"))) - } - } - print ("") - } - } - if (obsoletes_junk) { - warnc("The 'Obsoletes: ' line in the draft header should list only the _numbers_ of the RFCs " "which will be obsoleted by this document (if approved); it should not include the word " "'RFC' in the list.") - } - if (updates_junk) { - warnc("The 'Updates: ' line in the draft header should list only the _numbers_ of the RFCs " "which will be updated by this document (if approved); it should not include the word " "'RFC' in the list.") - } - list(abstract_mentions, abstract_rfcs) - list(obsoletes_docs, obsoletes_list) - list(abstract_obsoletes, abs_obs_list) - for (doc in obsoletes_list) { - if (! (doc in abs_obs_list)) { - if (doc in abstract_rfcs) { - comment("The draft header indicates that this document obsoletes " doc ", but the abstract doesn't seem to directly say this. It does mention " doc " though, so this could be OK.") - } else { - comment("The draft header indicates that this document obsoletes " doc ", but the abstract doesn't seem to mention this, which it should.") - } - } - } - for (doc in abs_obs_list) { - if (! (doc in obsoletes_list)) { - comment("The abstract seems to indicate that this document obsoletes " doc ", but the header doesn't have an 'Obsoletes:' line to match this.") - } - } - list(updates_docs, updates_list) - list(abstract_updates, abs_upd_list) - for (doc in updates_list) { - if (! (doc in abs_upd_list)) { - if (doc in abstract_rfcs) { - comment("The draft header indicates that this document updates " doc ", but the abstract doesn't seem to directly say this. It does mention " doc " though, so this could be OK.") - } else { - comment("The draft header indicates that this document updates " doc ", but the abstract doesn't seem to mention this, which it should.") - } - } - } - for (doc in abs_upd_list) { - if (! (doc in updates_list)) { - comment("The abstract seems to indicate that this document updates " doc ", but the header doesn't have an 'Updates:' line to match this.") - } - } - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { - note("No issues found here.") - # -------------------------------------------------------------- - # Warnings - } - announce("Miscellaneous warnings:") - errcount = errors - flawcount = flaws - warncount = warnings - commentcount = comments - warnshere = warnings - if (has_pk_mark) { - comment("The first octets (the first characters of the first line) of this " "draft are 'PK', which can make Internet Explorer erroneously think " "that it is a zip file. It is recommended that you change this, for " "instance by inserting a blank line before the line starting with 'PK'.") - } - if (has_bm_mark) { - comment("The first octets (the first characters of the first line) of this " "draft are 'BM', which can make the draft submission tool erroneously think " "that it is an image .bmp file. It is recommended that you change this, for " "instance by inserting a blank line before the line starting with 'BM'.") - } - checkmultibp("rfc3978_5_1") - checkmultibp("rfc3978_5_2b") - checkmultibp("rfc3978_5_3") - checkmultibp("rfc3978_5_5") - checkmultibp("rfc3978_5_5_u4748") - checkmultibp("rfc3979_5_p1") - checkmultibp("rfc3979_5_p2") - checkmultibp("rfc3979_5_p3") - if ((has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) && (has["rfc2026_10_4C_p2"] || has["rfc2026_10_4C_p3"] || has["rfc2026_10_4C_p4"])) { - if (option_rfc2026) { - if (! has["rfc2026_10_4A"]) { - warn("The document seems to lack an RFC 2026 Section 10.4(A) Disclaimer.") - } - if (! has["rfc2026_10_4B"]) { - warn("The document seems to lack an RFC 2026 Section 10.4(B) IPR Disclosure Invitation.") - } - if (has["rfc2026_10_4D"]) { - warn("The document has an RFC 2026 Section 10.4(D) IPR Notice.") - } - } - } - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { - if (has["rfc3978_5_2a"]) { - warn("The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause.") - } - } else if (has["rfc3978_5_2a"]) { - note("The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause.") - } - if (has["rfc3978_5_4_p1"] && ! has["rfc3978_5_4_p1_now"]) { - warn("The copyright year in the RFC 3978 Section 5.4 Copyright Line does not match the current year") - } - if (has["rfc3978_5_4_p1_u4748"] && ! has["rfc3978_5_4_p1_u4748_now"]) { - warn("The copyright year in the IETF Trust Copyright Line does not match the current year") - } - if (has["trust-28-dec-2009_6_b_i_p2"] && ! has["trust-28-dec-2009_6_b_i_p2_now"]) { - warn("The copyright year in the IETF Trust and authors Copyright Line does not match the current year") - } - if (has["rfc3978_5_4_p1_old"] && has["rfc3978_5_4_p1_now"]) { - warn(sprintf("The copyright year in the RFC 3978 Section 5.4 Copyright around line %s does not match the year around line %s", has["rfc3978_5_4_p1_old"], has["rfc3978_5_4_p1_now"])) - } - if (has["rfc3978_5_4_p1_old"] && has["rfc3978_5_4_p1_u4748_now"]) { - warn(sprintf("The copyright year in the IETF Trust Copyright around line %s does not match the year around line %s", has["rfc3978_5_4_p1_old"], has["rfc3978_5_4_p1_u4748_now"])) - } - # if (has["rfc3978_5_4_p1"] > firstpagelength) { - # warn( "An " expandname("rfc3978_5_4_p1") " paragraph was found, but not on the first page, as suggested." ); - # } - # - # if (has["rfc3978_5_4_p1_u4748"] > firstpagelength) { - # warn( "An " expandname("rfc3978_5_4_p1_u4748") " paragraph was found, but not on the first page, as suggested." ); - # } - # - if (hyphens && ! is_rfc) { - warnc(sprintf("There %s %d instance%s of lines with hyphenated line breaks in the document.", (hyphens == 1 ? "is" : "are"), hyphens, (hyphens == 1 ? "" : "s"))) - } - if (misspelled_toc) { - warnc("The \"Table of Contents\" section title seems to be misspelled.") - } - if (misspelled_addr) { - warnc("The \"Author's Address\" (or \"Authors' Addresses\") section title is misspelled.") - } - if (! option_verbose && spacing) { - for (i = 1; i <= 5; i++) { - if (i in sp_line) { - warnc(sprintf("Line %d has weird spacing: '...%s...'", linenum[i], extract[i])) - } - } - if (spacing > 5) { - warnc(sprintf("(%d more instance%s...)", spacing - 5, (spacing - 5 == 1 ? "" : "s"))) - } - } - if (keywords && ! has["rfc2119_p2"] && ! has["rfc2119_p2a"] && ! has["rfc8174_p11"] && found_2119_ref) { - sectionwarn("rfc8174_p11", "the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords") - note("(The document does seem to have the reference to RFC 2119 which the ID-Checklist requires).") - } - if (keywords && ! has["rfc2119_p2"] && has["rfc2119_p2a"] && ! has["rfc8174_p11"]) { - # Require that the reference used in "rfc2119_p2a" actually mentions RFC 2119... - if (ref_text[reftag2119] !~ /RFC[- ]?2119/) { - errg(sprintf("The document contains RFC2119-like boilerplate, but doesn't seem to mention RFC 2119. The boilerplate contains a reference [%s], but that reference does not seem to mention RFC 2119 either.", reftag2119)) - } - } - if (has_not_recommended && (has["rfc2119_p2"] || has["rfc2119_p2a"] || has["rfc8174_p11"]) && ! rfc2119_p2_not_recommended) { - warnc("The document seems to use 'NOT RECOMMENDED' as an RFC 2119 keyword, but does not include the phrase in its RFC 2119 key words list.") - } - if (! keywords) { - if (has["rfc2119_p2"] || has["rfc2119_p2a"] || has["rfc8174_p11"]) { - warnc("The document doesn't use any RFC 2119 keywords, yet seems to have RFC 2119 boilerplate text.") - } else if (almost_boilerplate["rfc2119_p2"] || almost_boilerplate["rfc2119_p2a"] || almost_boilerplate["rfc8174_p11"]) { - warnc("The document doesn't use any RFC 2119 keywords, yet has text resembling RFC 2119 boilerplate text.") - } - } - for (combo in rfc2119undefined) { - comment("The exact meaning of the all-uppercase expression '" combo "' is not defined in RFC 2119. If it is intended as a requirements " "expression, it should be rewritten using one of the combinations " "defined in RFC 2119; otherwise it should not be all-uppercase.") - } - for (bad_line in found_bad_pat) { - pattern = found_bad_pat[bad_line] - para = found_bad_para[bad_line] - warn(bad[pattern] "\n\n Found '" strip(pattern) "' in this paragraph:\n\n " para) - } - if (! (intended_status in status2code)) { - warn(sprintf("Unrecognized Status in '%s', assuming Proposed Standard", intended_status_text)) - note("(Expected one of 'Standards Track', 'Full Standard', 'Draft Standard', 'Proposed Standard', 'Best Current Practice', 'Informational', 'Experimental', 'Informational', 'Historic'.)\n") - intended_status = "proposed standard" - } - # The 'RFC 5378 fix' announced around 5 Feb 2009 means that drafts first - # submitted before 10 Nov 2008 with a high probability should have an additional - # boilerplate paragraph excempting it from full 5378 compliance. On the other - # hand, a draft first submitted on or after 10 Nov 2008 should probably not have - # such a paragraph. - if (has_docname) { - docname = full_docname - } else { - docname = file_docname - } - sub(/-[0-9][0-9](\.txt)?$/, "", docname) - get_state(docname, docstate, 1) - if ("creationdate" in docstate) { - created = docstate["creationdate"] - } - if ("created" in docstate) { - created = docstate["created"] - } - for (i in obsoletes) { - if (i !~ /draft-/) { - continue - } - refcreated = get_creation_date("rfc" i) - if (refcreated && jdn(refcreated) < jdn(created) && jdn(refcreated) < jdn("2008-11-10")) { - created = refcreated - refcreated = "" - note(sprintf("(Using the creation date from RFC%i, obsoleted by this document, for RFC5378 checks: %s)\n", i, created)) - } - } - for (i in updates) { - if (i ~ /draft-/) { - continue - } - refcreated = get_creation_date("rfc" i) - if (refcreated && jdn(refcreated) < jdn(created) && jdn(refcreated) < jdn("2008-11-10")) { - created = refcreated - refcreated = "" - note(sprintf("(Using the creation date from RFC%i, updated by this document, for RFC5378 checks: %s)\n", i, created)) - } - } - # for (key in docstate) { - # printf("docstate[%s]: %s\n", key, docstate[key]); - # } - if (created ~ /[12][0-9][0-9][0-9]-[01][0-9]-[0123][0-9]/) { - if (jdn(created) < jdn("2008-11-10")) { - if (! has["trust-28-dec-2009_6_c_iii"]) { - sectioncomment("trust-28-dec-2009_6_c_iii", "disclaimer for pre-RFC5378 work, but may have content which was first " "submitted before 10 " "November 2008. If you have contacted all the original authors and they " "are all willing to grant the BCP78 rights to the IETF Trust, then this " "is fine, and you can ignore this comment. If not, you may need to add " "the pre-RFC5378 disclaimer. (See the Legal Provisions document at " "https://trustee.ietf.org/license-info for more information.)") - } else { - comment("The document seems to contain a disclaimer for pre-RFC5378 work, and " "may have content which was first submitted before 10 November 2008. " "The disclaimer is necessary when " "there are original authors that you have been unable to contact, or " "if some do not wish to grant the BCP78 rights to the IETF Trust. If " "you are able to get all authors (current and original) to grant those " "rights, you can and should remove the disclaimer; otherwise, the " "disclaimer is needed and you can ignore this comment. " "(See the Legal Provisions document at https://trustee.ietf.org/license-info " "for more information.)") - } - } else { # document created on or after 2008-11-10 - if (has["trust-28-dec-2009_6_c_iii"]) { - warn("The document seems to contain a disclaimer for pre-RFC5378 work, but was " "first submitted on or after 10 November 2008. The disclaimer is usually " "necessary only for documents that revise or obsolete older RFCs, and " "that take significant amounts of text from those RFCs. If you can " "contact all authors of the source material and they are willing to " "grant the BCP78 rights to the IETF Trust, you can and should remove " "the disclaimer. Otherwise, the disclaimer is needed and you can " "ignore this comment. (See the Legal Provisions document at " "https://trustee.ietf.org/license-info for more information.)") - } else { - # No comment for documents created after 2008-11-10 without a disclaimer - } - } - } else { - warn("Couldn't figure out when the document was first submitted -- there may comments " "or warnings related to the use of a disclaimer for pre-RFC5378 work that could " "not be issued because of this. Please check the Legal Provisions document at " "https://trustee.ietf.org/license-info to determine if you need the pre-RFC5378 " "disclaimer.") - } - if (doc_date) { - days_off = doc_date - jdn(today) - if (days_off > date_skew) { - comment(sprintf("The document date (%s) is %s days in the future. Is this intentional?", date_lit, days_off)) - } - if (days_off < -date_skew) { - comment(sprintf("The document date (%s) is %s days in the past. Is this intentional?", date_lit, -days_off)) - } - } else { - comment("Couldn't find a document date in the document -- date freshness check skipped.") - } - if (code_comment_found) { - comment("Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines.") - } - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { - note("No issues found here.") - } - announce("Checking references for intended status: " (code2status[status2code[intended_status]] ? code2status[status2code[intended_status]] : "None")) - errcount = errors - flawcount = flaws - warncount = warnings - commentcount = comments - warnshere = warnings - intended_code = status2code[intended_status] - split(warncodes[intended_code], warnlist, FS) - for (i in warnlist) { - warnlist[warnlist[i]] - } - std_codes["B"] - std_codes["P"] - std_codes["D"] - std_codes["S"] - if (intended_code in std_codes) { - note("(See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs)\n") - } - for (i = 1; i <= ref_use_count; i++) { - tag = ref_use_list[i] - if (! (tag in ref_def)) { - is_numeric = tag ~ /^[0-9]+$/ - if ((is_numeric && has_numeric_refs) || (! is_numeric && has_symbolic_refs)) { - warnc(sprintf("Missing Reference: '%s' is mentioned on line %s, but not defined", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) - miss_ref[tag] - check_downref(tag, warnlist) - } else if (has_numeric_refs || has_symbolic_refs) { - comment(sprintf("Looks like a reference, but probably isn't: '%s' on line %s", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) - } else { - comment(sprintf("Missing reference section? '%s' on line %s looks like a reference", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) - } - } - } - for (i = 1; i <= ref_def_count; i++) { - tag = ref_def_list[i] - if (! (tag in ref_use)) { - warnc(sprintf("Unused Reference: '%s' is defined on line %s, but no explicit reference was found in the text", tag, ref_def[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_def[tag]], 1, 68))) : "")) - } - } - for (i = 1; i <= ref_def_count; i++) { - tag = ref_def_list[i] - check_downref(tag, warnlist) - } - if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { - note("No issues found here.") - } - } - # -------------------------------------------------------------- - # Summary - if (errors == 0 && warnings == 0 && comments == 0) { - print "" - note("No nits found.") - } else { - print "" - note(sprintf("Summary: %d error%s (%s), %d flaw%s (%s), %d warning%s (%s), %d comment%s (%s).", errors, (errors == 1 ? "" : "s"), errmark, flaws, (flaws == 1 ? "" : "s"), flawmark, warnings, (warnings == 1 ? "" : "s"), warnmark, comments, (comments == 1 ? "" : "s"), infomark)) - if (! option_verbose && ! option_submitcheck) { - print "" - note("Run idnits with the --verbose option for more detailed information about the items above.") - } - } - } + if (skip_file) { + return + } + if (option_pass1) { + return + } + if (option_status) { + if (! (tolower(option_status) in status2code)) { + note(sprintf("Unexpected value in --status switch ('%s'), ignoring it. (Use one of 'informational', 'experimental', 'bcp', 'ps', 'ds', 'standard'.)", option_status)) + } else { + intended_status = tolower(option_status) + } + } + if (got_input) { + is_rfc = (filename ~ /[Rr][Ff][Cc][0-9]+\.txt$/) + draftname = full_docname + sub(/\.[a-z]+$/, "", draftname) + sub(/-[0-9][0-9]$/, "", draftname) + get_state(draftname, state, quiet = 1) + destcode = get_draftcode(draftname, state) + if (option_submitcheck) { + printf ("\n Showing Errors (" errmark "), Flaws (" flawmark "), Warnings (" warnmark "), and Comments (" infomark ").\n") + print (" Errors MUST be fixed before draft submission. Flaws SHOULD be fixed before draft submission.") + } + announce("Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info):") + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + # 12 Sep 2009 values below are valid during the post-28-dec-2009 transition + if (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"] || has["trust-28-dec-2009_6_b_i_p2"] || has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"]) { + # We have some text from the current Trust Provisions boilerplate. Check that we don't have older + # boilerplate, too. + for (bpname in bp) { + if (bpname ~ /^rfc2026/ || bpname ~ /^rfc3667/ || bpname ~ /^rfc3978/ || bpname ~ /^rfc3979/) { + if (has[bpname] && ! (bpname ~ "_now")) { + newandolderr(bpname, "IETF Trust Provisions of 12 Sep 2009") + } + } + } + if (! is_rfc) { + if (! (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"])) { + sectionerr("trust-28-dec-2009_6_a", "Notice of Compliance with BCP 78 and BCP 79 according to " "IETF Trust Provisions of 28 Dec 2009, Section 6.a " "or Provisions of 12 Sep 2009, Section 6.a") + } + } + if (! has["trust-28-dec-2009_6_b_i_p2"]) { + sectionerr("trust-28-dec-2009_6_b_i_p2", "IETF Trust Provisions of 28 Dec 2009, Section 6.b Copyright Notice") + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_i_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.i or Provisions of 12 Sep 2009 Section 6.b") + if (has["trust-28-dec-2009_6_b_ii_p3"]) { + comment("It seems you're using the 'non-IETF stream' Licence Notice instead") + } + } + } else if (full_docname ~ /^draft-(iab|irtf|rfced|rfc-editor)-/) { + if (! (has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") + if (has["trust-28-dec-2009_6_b_i_p3"]) { + comment("It seems you're using the 'IETF stream' Licence Notice instead") + } + } + } else if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") + } + # The following is just an informational note because we've emitted an error earlier: + if (has["trust-12-feb-2009_6_b_p3"]) { + note("(You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Feb 2009 rather than one of the newer Notices. " "See https://trustee.ietf.org/license-info/.)\n") + } + if (has["trust-12-sep-2009_6_b_p3"]) { + err("You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Sep 2009 rather than the newer Notice from 28 Dec 2009. " "(See https://trustee.ietf.org/license-info/)") + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (has["trust-28-dec-2009_6_c_i"]) { + warn("The document has an IETF Trust Provisions of 28 Dec 2009, Section 6.c(i) Publication Limitation clause.") + } + if (has["trust-28-dec-2009_6_c_ii"]) { + err("The document has an IETF Trust Provisions, 28 Dec 2009, Section 6.c(ii) Publication Limitation clause.") + } + } else { + if (has["trust-28-dec-2009_6_c_i"]) { + comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(i) Publication Limitation clause.") + } + if (has["trust-28-dec-2009_6_c_ii"]) { + comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(ii) Publication " "Limitation clause. If this document is intended for submission to the IESG for " "publication, this constitutes an error.") + } + } + } else if ((has["rfc3667_5_1"] || has["rfc3978_5_1_a"] || has["rfc3978_5_1"] || has["rfc3978_5_2b"] || has["rfc3978_5_3"] || has["rfc3978_5_5"] || has["rfc3978_5_5_u4748"] || has["rfc3979_5_p1"] || has["rfc3979_5_p2"] || has["rfc3979_5_p3"])) { + err("It looks like you're using RFC 3978 boilerplate. You should update this to the " "boilerplate described in the IETF Trust License Policy document (see " "https://trustee.ietf.org/license-info), which is required now.") + if (has["rfc3667_5_1"]) { + olderr("rfc3667_5_1") + } + if (has["rfc3978_5_1_a"]) { + olderr("rfc3978_5_1_a") + } + if (has["rfc3978_5_1"]) { + olderr("rfc3978_5_1") + } + if (has["rfc3978_5_2b"]) { + olderr("rfc3978_5_2b") + } + if (has["rfc3978_5_3"]) { + olderr("rfc3978_5_3") + } + if (has["rfc3978_5_5"]) { + olderr("rfc3978_5_5") + } + if (has["rfc3978_5_5_u4748"]) { + olderr("rfc3978_5_5_u4748") + } + if (has["rfc3979_5_p1"]) { + olderr("rfc3979_5_p1") + } + if (has["rfc3979_5_p2"]) { + olderr("rfc3979_5_p2") + } + if (has["rfc3979_5_p3"]) { + olderr("rfc3979_5_p3") + } + # Ok, so we have some 3978/3979 boilerplate - make sure we don't *also* have some + # lingering old boilerplate... + if (has["rfc3978_5_1"]) { + if (has["rfc3667_5_1"]) { + oldandnewerr("rfc3667_5_1", "rfc3978_5_1") + } + } + if (has["rfc3978_5_4_p1"]) { + if (has["rfc2026_10_4C_p1"]) { + oldandnewerr("rfc2026_10_4C_p1", "rfc3978_5_4_p1") + } + } + if (has["rfc3978_5_4_p1_u4748"]) { + if (has["rfc2026_10_4C_p1"]) { + oldandnewerr("rfc2026_10_4C_p1", "rfc3978_5_4_p1_u4748") + } + } + if (has["rfc3978_5_4_p1_u4748"]) { + if (has["rfc3978_5_4_p1"]) { + oldandnewerr("rfc3978_5_4_p1", "rfc3978_5_4_p1_u4748") + } + } + if (has["rfc3978_5_4_p1_u4748_e"]) { + if (has["rfc3978_5_4_p1"]) { + oldandnewerr("rfc3978_5_4_p1", "rfc3978_5_4_p1_u4748_e") + } + } + if (has["rfc3978_5_4_p1_u4748"]) { + if (has["rfc3978_5_4_p1_e"]) { + oldandnewerr("rfc3978_5_4_p1_e", "rfc3978_5_4_p1_u4748") + } + } + if (has["rfc3978_5_5"]) { + if (has["rfc2026_10_4C_p4"]) { + oldandnewerr("rfc2026_10_4C_p4", "rfc3978_5_5") + } + } + if (has["rfc3978_5_5_u4748"]) { + if (has["rfc2026_10_4C_p4"]) { + oldandnewerr("rfc2026_10_4C_p4", "rfc3978_5_5_u4748") + } + } + if (has["rfc3978_5_5_u4748"]) { + if (has["rfc3978_5_5"]) { + oldandnewerr("rfc3978_5_5", "rfc3978_5_5_u4748") + } + } + if (has["rfc3979_5_p1"]) { + if (has["rfc2026_10_4A"]) { + oldandnewerr("rfc2026_10_4A", "rfc3979_5_p1") + } + } + if (has["rfc3979_5_p3"]) { + if (has["rfc2026_10_4B"]) { + oldandnewerr("rfc2026_10_4B", "rfc3979_5_p3") + } + } + if (has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) { + err("The document claims conformance with section 10 of RFC 2026, but uses " "some RFC 3978/3979 boilerplate. As RFC 3978/3979 replaces section 10 of " "RFC 2026, you should not claim conformance with it if you have changed " "to using RFC 3978/3979 boilerplate.") + } + if (! (has["rfc3978_5_1"]) && ! is_rfc) { + sectionerr("rfc3978_5_1", "RFC 3978 Section 5.1 IPR Disclosure Acknowledgement") + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (has["rfc3978_5_2b"]) { + err("The document has an RFC 3978 Section 5.2(b) Derivative Works Limitation clause.") + } + if (has["rfc3978_5_3"]) { + err("The document has an RFC 3978 Section 5.3 Publication Limitation clause.") + } + } else { + if (has["rfc3978_5_2b"]) { + comment("The document has an RFC 3978 Section 5.2(b) Derivative Works Limitation clause. " "If this document is intended for submission to the IESG for publication, this " "constitutes an error.") + } + if (has["rfc3978_5_3"]) { + comment("The document has an RFC 3978 Section 5.3 Publication Limitation clause. " "If this document is intended for submission to the IESG for publication, this " "constitutes an error.") + } + } + if (! has["rfc3978_5_4_p1_u4748"]) { + if (has["rfc3978_5_4_p1"]) { + err("This document has an original RFC 3978 Section 5.4 Copyright Line, " "instead of the newer IETF Trust Copyright according " "to RFC 4748.") + } else { + sectionerr("rfc3978_5_4_p1_u4748", "RFC 3978 Section 5.4 (updated by RFC 4748) Copyright Line") + } + } + if (! has["rfc3978_5_4_p2"]) { + sectionerr("rfc3978_5_4_p2", "RFC 3978 Section 5.4 Reference to BCP 78") + } + if (! has["rfc3978_5_5_u4748"]) { + if (has["rfc3978_5_5"]) { + err("This document has an original RFC 3978 Section 5.5 Disclaimer, " "instead of the newer disclaimer which includes the IETF Trust according " "to RFC 4748.") + } else { + sectionerr("rfc3978_5_5_u4748", "RFC 3978 Section 5.5 (updated by RFC 4748) Disclaimer") + } + } + if (! has["rfc3979_5_p1"]) { + sectionerr("rfc3979_5_p1", "RFC 3979 Section 5, para. 1 IPR Disclosure Acknowledgement") + if (has["rfc2026_10_4A"]) { + note("( - It does however have an RFC 2026 Section 10.4(A) Disclaimer.)") + } + } + if (! has["rfc3979_5_p2"]) { + sectionerr("rfc3979_5_p2", "RFC 3979 Section 5, para. 2 IPR Disclosure Acknowledgement") + } + if (! has["rfc3979_5_p3"]) { + sectionerr("rfc3979_5_p3", "RFC 3979 Section 5, para. 3 IPR Disclosure Invitation") + if (has["rfc2026_10_4B"]) { + note("( - It does however have an RFC 2026 Section 10.4(B) IPR Disclosure Invitation.)") + } + } + if (has["rfc3667_3_claim"] || (has["rfc3667_5_1"] || has["rfc3978_5_1_a"]) && ! has["rfc3978_5_1"]) { + err("The document uses RFC 3667 boilerplate or RFC 3978-like " "boilerplate instead of verbatim RFC 3978 boilerplate. After 6 May 2005, " "submission of drafts without verbatim RFC 3978 boilerplate is not " "accepted.") + note("The following non-3978 patterns matched text found in the document. That text should be removed or replaced:\n") + if (has["rfc3667_3_claim"]) { + showsection("rfc3667_3_claim", 2) + } + if (has["rfc3667_5_1"]) { + showsection("rfc3667_5_1", 2) + } + if (has["rfc3978_5_1_a"] && ! has["rfc3978_5_1"]) { + showsection("rfc3978_5_1_a", 2) + } + } + if ((has["rfc3978_5_4_p1"] && has["rfc3978_5_4_p1_e"]) || (has["rfc3978_5_4_p1_u4748"] && has["rfc3978_5_4_p1_u4748_e"])) { + warn("In addition to a regular copyright notice, the document also has a " "copyright notice embedded in the text.") + } + } else if ((has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"] || has["rfc2026_10_4C_p2"] || has["rfc2026_10_4C_p3"] || has["rfc2026_10_4C_p4"])) { + if (option_verbose) { + print "" + if (has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) { + note(" [Claims RFC 2026 conformance...]") + } + if (has["rfc2026_10_4C_p1"]) { + note(" [Has RFC 2026 Sec. 10.4 para. 1...]") + } + if (has["rfc2026_10_4C_p2"]) { + note(" [Has RFC 2026 Sec. 10.4 para. 2...]") + } + if (has["rfc2026_10_4C_p3"]) { + note(" [Has RFC 2026 Sec. 10.4 para. 3...]") + } + if (has["rfc2026_10_4C_p4"]) { + note(" [Has RFC 2026 Sec. 10.4 para. 4...]") + } + print "" + } + err("Looks like you're using RFC 2026 boilerplate. This must be updated to follow RFC 3978/3979, as updated by RFC 4748.") + } else { + if (some_copyright) { + copyright_msg = " Found some kind of copyright notice around line " some_copyright " but it does not match any copyright boilerplate known by this tool." + } else { + copyright_msg = "" + } + err("Cannot find the required boilerplate sections (Copyright, IPR, etc.) in this document." copyright_msg) + note("Expected boilerplate is as follows today (" today ") according to https://trustee.ietf.org/license-info :\n") + showsection("trust-28-dec-2009_6_a") + showsection("trust-28-dec-2009_6_b_i_p2") + showsection("trust-28-dec-2009_6_b_i_p3") + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + } + if (! is_rfc) { + announce("Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt:") + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + if (! has_id_indication) { + errg("Missing document type: Expected \"INTERNET-DRAFT\" in the upper left hand corner of the first page") + } + if (! has_expiration) { + errg("Missing expiration date. The document expiration date should appear on the first and last page.") + } + if (! (has["1id_guidelines_p1"] || has["1id_guidelines_p1a"])) { + sectionerr("1id_guidelines_p1", "1id_guidelines paragraph about Internet-Drafts being working documents") + } + if (! (has["1id_guidelines_p2"] || has["1id_guidelines_p2a"])) { + sectionerr("1id_guidelines_p2", "1id_guidelines paragraph about 6 months document validity") + } + if (! (has["1id_guidelines_p3"] || has["1id_guidelines_p3a"] || has["1id_guidelines_p1a"])) { + sectionerr("1id_guidelines_p3", "1id_guidelines paragraph about the list of current Internet-Drafts") + } + if (! (has["1id_guidelines_p4"] || has["1id_guidelines_p4a"] || has["1id_guidelines_p1a"])) { + sectionerr("1id_guidelines_p4", "1id_guidelines paragraph about the list of Shadow Directories") + } + if (has["1id_guidelines_p1a"] && has["1id_guidelines_p3"]) { + newandolderr("1id_guidelines_p3", "1id_guidelines_p1a") + } + if (has["1id_guidelines_p1a"] && has["1id_guidelines_p3a"]) { + newandolderr("1id_guidelines_p3a", "1id_guidelines_p1a") + } + if (has["1id_guidelines_p1a"] && has["1id_guidelines_p4"]) { + newandolderr("1id_guidelines_p4", "1id_guidelines_p1a") + } + if (has["1id_guidelines_p1a"] && has["1id_guidelines_p4a"]) { + newandolderr("1id_guidelines_p4a", "1id_guidelines_p1a") + } + if (has_docname) { + file_docname = option_filename + # Get rid of path and extension + sub(".*/", "", file_docname) + sub(/\.(txt|pdf|xml|doc|nr)$/, "", file_docname) + sub(".*/", "", full_docname) + sub(/\.(txt|pdf|xml|doc)$/, "", full_docname) + if (good_docname != full_docname || full_docname ~ /[^a-z0-9-]/) { + errg(sprintf("Bad filename characters: the document name given in the document, '%s', contains other characters than digits, lowercase letters and dash.", full_docname)) + } else if (file_docname ~ /[^a-z0-9-]/) { + errg(sprintf("Bad filename characters: the file name of the draft, '%s', contains other characters than digits, lowercase letters and dash.", file_docname)) + } + if (! match(full_docname, /.*-[0-9][0-9]$/)) { + errg(sprintf("Missing revision: the document name given in the document, '%s', does not give the document revision number", full_docname)) + } + doc_has_empty_source = 0 + if (match(full_docname, /^draft--/)) { + doc_has_empty_source = 1 + errg(sprintf("Empty name element: the document name given in the document, '%s', lacks the source element (it starts with 'draft--'). See https://www.ietf.org/id-info/1id-guidelines.txt, section 7, on how to construct a good document name.", full_docname)) + } + if (match(full_docname, /--[0-9][0-9]$/)) { + errg(sprintf("Negative revision number: the document name given in the document, '%s', seems to have a negative revision number (it ends with '--%s'). See https://www.ietf.org/id-info/1id-guidelines.txt, section 7, on how to construct a good document name.", full_docname, substr(full_docname, length(full_docname) - 1))) + } + if (! match(full_docname, /^draft-[^-]+-.+-[0-9][0-9](\.[a-z]+)?$/)) { + if (! doc_has_empty_source) { + flaw(sprintf("Missing draftname component: the document name given in the document, '%s', does not seem to contain all the document name components required ('draft' prefix, document source, document name, and revision) -- see https://www.ietf.org/id-info/guidelines#naming for more information.", full_docname)) + } + } + if (length(file_docname) > length(full_docname)) { + long_docname = file_docname + } else { + long_docname = full_docname + } + sub(/-[0-9][0-9]$/, "", long_docname) + if (length(long_docname) > 50) { + errg(sprintf("Too long document name: The document name (without revision number), '%s', is %d characters long, but may be at most 50 characters", long_docname, length(long_docname))) + } + if (file_docname && file_docname != full_docname) { + warn(sprintf("Mismatching filename: the document gives the document name as '%s', but the file name used is '%s'", full_docname, file_docname)) + } + } else { + errg("Expected the document's filename to be given on the first page, but didn't find any") + } + if (has["rfc3978_5_1"] > firstpagelength && ! is_rfc) { + errg("An " expandname("rfc3978_5_1") " paragraph was found, but not on the first page, as required.") + } + # According to the nits page we should be comparing to 15 here, but + # that may be without the boilerplate - and practice seems to permit + # also 16 pages including boilerplate, so... + if (! has_toc && ((pagecount > 16) || (FNR > 50 * 16))) { + errw("The document is more than 15 pages and seems to lack a Table of Contents.") + } + if (nonascii && ! option_nonascii) { + warn(sprintf("There %s %d instance%s of lines with non-ascii characters in the document.", (nonascii == 1 ? "is" : "are"), nonascii, (nonascii == 1 ? "" : "s"))) + } + if (length(intended_status) == 0) { + warn("No 'Intended status' indicated for this document; assuming Proposed Standard") + intended_status = "proposed standard" + } + if (maxpagelength > 58) { + warnc(sprintf("The page length should not exceed 58 lines per page, " "but there was %d longer page%s, the longest (page %d) being %d lines", longpagecount, (longpagecount == 1 ? "" : "s"), longestpage, maxpagelength)) + } + if (pagecount > formfeedcount + 1) { + warnc(sprintf("It seems as if not all pages are separated by form feeds - " "found %d form feeds but %d page%s", formfeedcount, pagecount, (pagecount == 1 ? "" : "s"))) + } + if (missing_nroff_postprocessing) { + comment(sprintf("Found %d instances of the string 'FORMFEED[Page...' -- is this a case of missing nroff postprocessing?", missing_nroff_postprocessing)) + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + } + } + if (option_submitcheck) { + announce("Running in submission checking mode -- *not* checking nits according to https://www.ietf.org/id-info/checklist .") + } else { + announce("Checking nits according to https://www.ietf.org/id-info/checklist :") + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + if (! has_abstract) { + err("The document seems to lack an Abstract section.", indented_abstract) + } + if (! has_intro) { + errc("The document seems to lack an Introduction section.", indented_intro) + } + if (! has_security) { + errc("The document seems to lack a Security Considerations section.", indented_security) + } + if (is_rfc) { + if (! has_iana) { + comment("The document seems to lack an IANA Considerations section. ", indented_iana) + } + } else if (! has_iana) { + errc("The document seems to lack an IANA Considerations section. " "(See Section 2.2 of https://www.ietf.org/id-info/checklist for how " "to handle the case when there are no actions for IANA.)", indented_iana) + } + if (! has_addr) { + errc("The document seems to lack an Authors' Addresses Section.") + } + if (has_refs && ! has_splitrefs) { + errc("The document seems to lack separate sections for Informative/Normative References. " "All references will be assumed normative when checking for downward references.") + } + if (option_list_matches) { + print fold(" Boilerplate matches:", " ", columns) + for (n in has) { + if (n) { + note(sprintf("Found", n, "on line", has[n])) + } + } + print "" + } + if (spacing > 50) { + errc(sprintf("There %s %d instance%s of weird spacing in the document. " "Is it really formatted ragged-right, rather than justified?", (spacing == 1 ? "is" : "are"), spacing, (spacing == 1 ? "" : "s"))) + } + if (longlines) { + msg = sprintf("There %s %d instance%s of too long lines in the document, " "the longest one being %d character%s in excess of 72.", (longlines == 1 ? "is" : "are"), longlines, (longlines == 1 ? "" : "s"), excesslength, ((excesslength > 1) ? "s" : "")) + if (! option_submitcheck) { + errc(msg) + } else { + warn(msg) + } + } + if (controlchars) { + errc(sprintf("There %s %d instance%s of lines with control characters in the document.", (controlchars == 1 ? "is" : "are"), controlchars, (controlchars == 1 ? "" : "s"))) + } + if (abstract_references) { + list(abstract_references, ref_list) + ref_str = "" + for (i in ref_list) { + if (ref_str) { + ref_str = ref_str ", " + } + ref_str = ref_str i + } + errc("The abstract seems to contain references (" ref_str "), which it shouldn't. Please replace those with straight textual mentions of the documents in question.") + } + if (badfqdns) { + warnc(sprintf("There %s %d instance%s of lines with " "non-RFC2606-compliant FQDNs in the document.", (controlchars == 1 ? "is" : "are"), badfqdns, (badfqdns == 1 ? "" : "s"))) + } + if (badipv4addr) { + warnc(sprintf("There %s %d instance%s of lines with " "non-RFC6890-compliant IPv4 addresses in the document. " "If these are example addresses, they should be changed.", (controlchars == 1 ? "is" : "are"), badipv4addr, (badipv4addr == 1 ? "" : "s"))) + } + if (mcastipv4addr) { + warnc(sprintf("There %s %d instance%s of lines with " "multicast IPv4 addresses in the document. " "If these are generic example addresses, they should be changed " "to use the 233.252.0.x range defined in RFC 5771", (controlchars == 1 ? "is" : "are"), mcastipv4addr, (mcastipv4addr == 1 ? "" : "s"))) + } + if (privipv4addr) { + warnc(sprintf("There %s %d instance%s of lines with " "private range IPv4 addresses in the document. " "If these are generic example addresses, they should be changed " "to use any of the ranges defined in RFC 6890 (or successor): " "192.0.2.x, 198.51.100.x or 203.0.113.x.", (controlchars == 1 ? "is" : "are"), privipv4addr, (privipv4addr == 1 ? "" : "s"))) + } + if (badipv6addr) { + warnc(sprintf("There %s %d instance%s of lines with " "non-RFC3849-compliant IPv6 addresses in the document. " "If these are example addresses, they should be changed.", (controlchars == 1 ? "is" : "are"), badipv6addr, (badipv6addr == 1 ? "" : "s"))) + } + if (ulipv6addr) { + warnc(sprintf("There %s %d instance%s of lines with " "Unique Local Unicast IPv6 addresses (RFC 4193) in the document. " "If these are generic example addresses, they should be changed", "to use the 2001:DB8::/32 range defined in RFC 4291.", (controlchars == 1 ? "is" : "are"), ulipv6addr, (ulipv6addr == 1 ? "" : "s"))) + } + if (llipv6addr) { + warnc(sprintf("There %s %d instance%s of lines with " "Link Local Unicast IPv6 addresses (RFC 4291) in the document. " "If these are generic example addresses, they should be changed", "to use the 2001:DB8::/32 range defined in RFC 4291.", (controlchars == 1 ? "is" : "are"), llipv6addr, (llipv6addr == 1 ? "" : "s"))) + } + if (ipv4_example_addr && ! ipv6_example_addr) { + comment("The document has examples using IPv4 documentation addresses " "according to RFC6890, but does not use any IPv6 documentation " "addresses. Maybe there should be IPv6 examples, too?") + } + if (keywords && ! has["rfc2119_p2"] && ! has["rfc2119_p2a"] ! has["rfc8174_p11"]) { + # Check whether there is a reference to RFC 2119 at all + for (reftag in ref_text) { + if (ref_text[reftag] ~ /RFC[- ]?2119/) { + found_2119_ref = ref_def[reftag] + } + } + if (! found_2119_ref) { + sectionerr("rfc8174_p11", "both a reference to RFC 2119 and the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords", option_checklistwarn) + if (option_verbose <= 1) { + for (i = 1; i <= 5; i++) { + if (i in rfc2119line) { + fnr = rfc2119line[i] + printf " RFC 2119 keyword, line %d: '...%s...'\n", fnr, line[fnr] + } + } + if (keywords > 5) { + note(sprintf("(%d more instance%s...)", keywords - 5, (keywords - 5 == 1 ? "" : "s"))) + } + } + print ("") + } + } + if (obsoletes_junk) { + warnc("The 'Obsoletes: ' line in the draft header should list only the _numbers_ of the RFCs " "which will be obsoleted by this document (if approved); it should not include the word " "'RFC' in the list.") + } + if (updates_junk) { + warnc("The 'Updates: ' line in the draft header should list only the _numbers_ of the RFCs " "which will be updated by this document (if approved); it should not include the word " "'RFC' in the list.") + } + list(abstract_mentions, abstract_rfcs) + list(obsoletes_docs, obsoletes_list) + list(abstract_obsoletes, abs_obs_list) + for (doc in obsoletes_list) { + if (! (doc in abs_obs_list)) { + if (doc in abstract_rfcs) { + comment("The draft header indicates that this document obsoletes " doc ", but the abstract doesn't seem to directly say this. It does mention " doc " though, so this could be OK.") + } else { + comment("The draft header indicates that this document obsoletes " doc ", but the abstract doesn't seem to mention this, which it should.") + } + } + } + for (doc in abs_obs_list) { + if (! (doc in obsoletes_list)) { + comment("The abstract seems to indicate that this document obsoletes " doc ", but the header doesn't have an 'Obsoletes:' line to match this.") + } + } + list(updates_docs, updates_list) + list(abstract_updates, abs_upd_list) + for (doc in updates_list) { + if (! (doc in abs_upd_list)) { + if (doc in abstract_rfcs) { + comment("The draft header indicates that this document updates " doc ", but the abstract doesn't seem to directly say this. It does mention " doc " though, so this could be OK.") + } else { + comment("The draft header indicates that this document updates " doc ", but the abstract doesn't seem to mention this, which it should.") + } + } + } + for (doc in abs_upd_list) { + if (! (doc in updates_list)) { + comment("The abstract seems to indicate that this document updates " doc ", but the header doesn't have an 'Updates:' line to match this.") + } + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + # -------------------------------------------------------------- + # Warnings + } + announce("Miscellaneous warnings:") + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + warnshere = warnings + if (has_pk_mark) { + comment("The first octets (the first characters of the first line) of this " "draft are 'PK', which can make Internet Explorer erroneously think " "that it is a zip file. It is recommended that you change this, for " "instance by inserting a blank line before the line starting with 'PK'.") + } + if (has_bm_mark) { + comment("The first octets (the first characters of the first line) of this " "draft are 'BM', which can make the draft submission tool erroneously think " "that it is an image .bmp file. It is recommended that you change this, for " "instance by inserting a blank line before the line starting with 'BM'.") + } + checkmultibp("rfc3978_5_1") + checkmultibp("rfc3978_5_2b") + checkmultibp("rfc3978_5_3") + checkmultibp("rfc3978_5_5") + checkmultibp("rfc3978_5_5_u4748") + checkmultibp("rfc3979_5_p1") + checkmultibp("rfc3979_5_p2") + checkmultibp("rfc3979_5_p3") + if ((has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) && (has["rfc2026_10_4C_p2"] || has["rfc2026_10_4C_p3"] || has["rfc2026_10_4C_p4"])) { + if (option_rfc2026) { + if (! has["rfc2026_10_4A"]) { + warn("The document seems to lack an RFC 2026 Section 10.4(A) Disclaimer.") + } + if (! has["rfc2026_10_4B"]) { + warn("The document seems to lack an RFC 2026 Section 10.4(B) IPR Disclosure Invitation.") + } + if (has["rfc2026_10_4D"]) { + warn("The document has an RFC 2026 Section 10.4(D) IPR Notice.") + } + } + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (has["rfc3978_5_2a"]) { + warn("The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause.") + } + } else if (has["rfc3978_5_2a"]) { + note("The document has an RFC 3978 Section 5.2(a) Derivative Works Limitation clause.") + } + if (has["rfc3978_5_4_p1"] && ! has["rfc3978_5_4_p1_now"]) { + warn("The copyright year in the RFC 3978 Section 5.4 Copyright Line does not match the current year") + } + if (has["rfc3978_5_4_p1_u4748"] && ! has["rfc3978_5_4_p1_u4748_now"]) { + warn("The copyright year in the IETF Trust Copyright Line does not match the current year") + } + if (has["trust-28-dec-2009_6_b_i_p2"] && ! has["trust-28-dec-2009_6_b_i_p2_now"]) { + warn("The copyright year in the IETF Trust and authors Copyright Line does not match the current year") + } + if (has["rfc3978_5_4_p1_old"] && has["rfc3978_5_4_p1_now"]) { + warn(sprintf("The copyright year in the RFC 3978 Section 5.4 Copyright around line %s does not match the year around line %s", has["rfc3978_5_4_p1_old"], has["rfc3978_5_4_p1_now"])) + } + if (has["rfc3978_5_4_p1_old"] && has["rfc3978_5_4_p1_u4748_now"]) { + warn(sprintf("The copyright year in the IETF Trust Copyright around line %s does not match the year around line %s", has["rfc3978_5_4_p1_old"], has["rfc3978_5_4_p1_u4748_now"])) + } + # if (has["rfc3978_5_4_p1"] > firstpagelength) { + # warn( "An " expandname("rfc3978_5_4_p1") " paragraph was found, but not on the first page, as suggested." ); + # } + # + # if (has["rfc3978_5_4_p1_u4748"] > firstpagelength) { + # warn( "An " expandname("rfc3978_5_4_p1_u4748") " paragraph was found, but not on the first page, as suggested." ); + # } + # + if (hyphens && ! is_rfc) { + warnc(sprintf("There %s %d instance%s of lines with hyphenated line breaks in the document.", (hyphens == 1 ? "is" : "are"), hyphens, (hyphens == 1 ? "" : "s"))) + } + if (misspelled_toc) { + warnc("The \"Table of Contents\" section title seems to be misspelled.") + } + if (misspelled_addr) { + warnc("The \"Author's Address\" (or \"Authors' Addresses\") section title is misspelled.") + } + if (! option_verbose && spacing) { + for (i = 1; i <= 5; i++) { + if (i in sp_line) { + warnc(sprintf("Line %d has weird spacing: '...%s...'", linenum[i], extract[i])) + } + } + if (spacing > 5) { + warnc(sprintf("(%d more instance%s...)", spacing - 5, (spacing - 5 == 1 ? "" : "s"))) + } + } + if (keywords && ! has["rfc2119_p2"] && ! has["rfc2119_p2a"] && ! has["rfc8174_p11"] && found_2119_ref) { + sectionwarn("rfc8174_p11", "the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords") + note("(The document does seem to have the reference to RFC 2119 which the ID-Checklist requires).") + } + if (keywords && ! has["rfc2119_p2"] && has["rfc2119_p2a"] && ! has["rfc8174_p11"]) { + # Require that the reference used in "rfc2119_p2a" actually mentions RFC 2119... + if (ref_text[reftag2119] !~ /RFC[- ]?2119/) { + errg(sprintf("The document contains RFC2119-like boilerplate, but doesn't seem to mention RFC 2119. The boilerplate contains a reference [%s], but that reference does not seem to mention RFC 2119 either.", reftag2119)) + } + } + if (has_not_recommended && (has["rfc2119_p2"] || has["rfc2119_p2a"] || has["rfc8174_p11"]) && ! rfc2119_p2_not_recommended) { + warnc("The document seems to use 'NOT RECOMMENDED' as an RFC 2119 keyword, but does not include the phrase in its RFC 2119 key words list.") + } + if (! keywords) { + if (has["rfc2119_p2"] || has["rfc2119_p2a"] || has["rfc8174_p11"]) { + warnc("The document doesn't use any RFC 2119 keywords, yet seems to have RFC 2119 boilerplate text.") + } else if (almost_boilerplate["rfc2119_p2"] || almost_boilerplate["rfc2119_p2a"] || almost_boilerplate["rfc8174_p11"]) { + warnc("The document doesn't use any RFC 2119 keywords, yet has text resembling RFC 2119 boilerplate text.") + } + } + for (combo in rfc2119undefined) { + comment("The exact meaning of the all-uppercase expression '" combo "' is not defined in RFC 2119. If it is intended as a requirements " "expression, it should be rewritten using one of the combinations " "defined in RFC 2119; otherwise it should not be all-uppercase.") + } + for (bad_line in found_bad_pat) { + pattern = found_bad_pat[bad_line] + para = found_bad_para[bad_line] + warn(bad[pattern] "\n\n Found '" strip(pattern) "' in this paragraph:\n\n " para) + } + if (! (intended_status in status2code)) { + warn(sprintf("Unrecognized Status in '%s', assuming Proposed Standard", intended_status_text)) + note("(Expected one of 'Standards Track', 'Full Standard', 'Draft Standard', 'Proposed Standard', 'Best Current Practice', 'Informational', 'Experimental', 'Informational', 'Historic'.)\n") + intended_status = "proposed standard" + } + # The 'RFC 5378 fix' announced around 5 Feb 2009 means that drafts first + # submitted before 10 Nov 2008 with a high probability should have an additional + # boilerplate paragraph excempting it from full 5378 compliance. On the other + # hand, a draft first submitted on or after 10 Nov 2008 should probably not have + # such a paragraph. + if (has_docname) { + docname = full_docname + } else { + docname = file_docname + } + sub(/-[0-9][0-9](\.txt)?$/, "", docname) + get_state(docname, docstate, 1) + if ("creationdate" in docstate) { + created = docstate["creationdate"] + } + if ("created" in docstate) { + created = docstate["created"] + } + for (i in obsoletes) { + if (i !~ /draft-/) { + continue + } + refcreated = get_creation_date("rfc" i) + if (refcreated && jdn(refcreated) < jdn(created) && jdn(refcreated) < jdn("2008-11-10")) { + created = refcreated + refcreated = "" + note(sprintf("(Using the creation date from RFC%i, obsoleted by this document, for RFC5378 checks: %s)\n", i, created)) + } + } + for (i in updates) { + if (i ~ /draft-/) { + continue + } + refcreated = get_creation_date("rfc" i) + if (refcreated && jdn(refcreated) < jdn(created) && jdn(refcreated) < jdn("2008-11-10")) { + created = refcreated + refcreated = "" + note(sprintf("(Using the creation date from RFC%i, updated by this document, for RFC5378 checks: %s)\n", i, created)) + } + } + # for (key in docstate) { + # printf("docstate[%s]: %s\n", key, docstate[key]); + # } + if (created ~ /[12][0-9][0-9][0-9]-[01][0-9]-[0123][0-9]/) { + if (jdn(created) < jdn("2008-11-10")) { + if (! has["trust-28-dec-2009_6_c_iii"]) { + sectioncomment("trust-28-dec-2009_6_c_iii", "disclaimer for pre-RFC5378 work, but may have content which was first " "submitted before 10 " "November 2008. If you have contacted all the original authors and they " "are all willing to grant the BCP78 rights to the IETF Trust, then this " "is fine, and you can ignore this comment. If not, you may need to add " "the pre-RFC5378 disclaimer. (See the Legal Provisions document at " "https://trustee.ietf.org/license-info for more information.)") + } else { + comment("The document seems to contain a disclaimer for pre-RFC5378 work, and " "may have content which was first submitted before 10 November 2008. " "The disclaimer is necessary when " "there are original authors that you have been unable to contact, or " "if some do not wish to grant the BCP78 rights to the IETF Trust. If " "you are able to get all authors (current and original) to grant those " "rights, you can and should remove the disclaimer; otherwise, the " "disclaimer is needed and you can ignore this comment. " "(See the Legal Provisions document at https://trustee.ietf.org/license-info " "for more information.)") + } + } else { # document created on or after 2008-11-10 + if (has["trust-28-dec-2009_6_c_iii"]) { + warn("The document seems to contain a disclaimer for pre-RFC5378 work, but was " "first submitted on or after 10 November 2008. The disclaimer is usually " "necessary only for documents that revise or obsolete older RFCs, and " "that take significant amounts of text from those RFCs. If you can " "contact all authors of the source material and they are willing to " "grant the BCP78 rights to the IETF Trust, you can and should remove " "the disclaimer. Otherwise, the disclaimer is needed and you can " "ignore this comment. (See the Legal Provisions document at " "https://trustee.ietf.org/license-info for more information.)") + } else { + # No comment for documents created after 2008-11-10 without a disclaimer + } + } + } else { + warn("Couldn't figure out when the document was first submitted -- there may comments " "or warnings related to the use of a disclaimer for pre-RFC5378 work that could " "not be issued because of this. Please check the Legal Provisions document at " "https://trustee.ietf.org/license-info to determine if you need the pre-RFC5378 " "disclaimer.") + } + if (doc_date) { + days_off = doc_date - jdn(today) + if (days_off > date_skew) { + comment(sprintf("The document date (%s) is %s days in the future. Is this intentional?", date_lit, days_off)) + } + if (days_off < -date_skew) { + comment(sprintf("The document date (%s) is %s days in the past. Is this intentional?", date_lit, -days_off)) + } + } else { + comment("Couldn't find a document date in the document -- date freshness check skipped.") + } + if (code_comment_found) { + comment("Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines.") + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + } + announce("Checking references for intended status: " (code2status[status2code[intended_status]] ? code2status[status2code[intended_status]] : "None")) + errcount = errors + flawcount = flaws + warncount = warnings + commentcount = comments + warnshere = warnings + intended_code = status2code[intended_status] + split(warncodes[intended_code], warnlist, FS) + for (i in warnlist) { + warnlist[warnlist[i]] + } + std_codes["B"] + std_codes["P"] + std_codes["D"] + std_codes["S"] + if (intended_code in std_codes) { + note("(See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs)\n") + } + for (i = 1; i <= ref_use_count; i++) { + tag = ref_use_list[i] + if (! (tag in ref_def)) { + is_numeric = tag ~ /^[0-9]+$/ + if ((is_numeric && has_numeric_refs) || (! is_numeric && has_symbolic_refs)) { + warnc(sprintf("Missing Reference: '%s' is mentioned on line %s, but not defined", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) + miss_ref[tag] + check_downref(tag, warnlist) + } else if (has_numeric_refs || has_symbolic_refs) { + comment(sprintf("Looks like a reference, but probably isn't: '%s' on line %s", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) + } else { + comment(sprintf("Missing reference section? '%s' on line %s looks like a reference", tag, ref_use[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_use[tag]], 1, 68))) : "")) + } + } + } + for (i = 1; i <= ref_def_count; i++) { + tag = ref_def_list[i] + if (! (tag in ref_use)) { + warnc(sprintf("Unused Reference: '%s' is defined on line %s, but no explicit reference was found in the text", tag, ref_def[tag]) (option_verbose ? sprintf("\n'%s...'", strip(substr(line[ref_def[tag]], 1, 68))) : "")) + } + } + for (i = 1; i <= ref_def_count; i++) { + tag = ref_def_list[i] + check_downref(tag, warnlist) + } + if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { + note("No issues found here.") + } + } + # -------------------------------------------------------------- + # Summary + if (errors == 0 && warnings == 0 && comments == 0) { + print "" + note("No nits found.") + } else { + print "" + note(sprintf("Summary: %d error%s (%s), %d flaw%s (%s), %d warning%s (%s), %d comment%s (%s).", errors, (errors == 1 ? "" : "s"), errmark, flaws, (flaws == 1 ? "" : "s"), flawmark, warnings, (warnings == 1 ? "" : "s"), warnmark, comments, (comments == 1 ? "" : "s"), infomark)) + if (! option_verbose && ! option_submitcheck) { + print "" + note("Run idnits with the --verbose option for more detailed information about the items above.") + } + } + } } # ---------------------------------------------------------------------- @@ -3286,23 +3286,23 @@ function report(filename) # function rindex(str, find, start, pos, incr, i) { - start = 0 - pos = 0 - incr = length(find) - while (1) { - i = index(str, find) - if (i == 0) { - return pos - } - pos = start + i - str = substr(str, i + incr) - start = start + i + incr - 1 - } + start = 0 + pos = 0 + incr = length(find) + while (1) { + i = index(str, find) + if (i == 0) { + return pos + } + pos = start + i + str = substr(str, i + incr) + start = start + i + incr - 1 + } } function sectioncomment(name, str) { - sectionerr(name, str, 3) + sectionerr(name, str, 3) } # ---------------------------------------------------------------------- @@ -3310,44 +3310,44 @@ function sectioncomment(name, str) # function sectionerr(name, str, wflag) { - if (! name in has) { - print "?? internal error, expected a table match on %s", name - exit - } - if (str ~ /^the /) { - str = "The document seems to lack " str - } else if (str ~ /^[aeiouyAEIOUYRH]/) { - str = "The document seems to lack an " str - } else { - str = "The document seems to lack a " str - } - if (name in almost_boilerplate) { - str = str " -- however, there's a paragraph with a matching beginning. Boilerplate error?" - } else if (str !~ /(\.|\.\))$/) { - str = str ". " - } - if (wflag == 3) { - comment(str) - } else if (wflag == 2) { - warn(str) - } else if (wflag == 1) { - flaw(str) - } else { - err(str) - } - if ((option_verbose || option_submitcheck) && option_pass2) { - showsection(name) - } + if (! name in has) { + print "?? internal error, expected a table match on %s", name + exit + } + if (str ~ /^the /) { + str = "The document seems to lack " str + } else if (str ~ /^[aeiouyAEIOUYRH]/) { + str = "The document seems to lack an " str + } else { + str = "The document seems to lack a " str + } + if (name in almost_boilerplate) { + str = str " -- however, there's a paragraph with a matching beginning. Boilerplate error?" + } else if (str !~ /(\.|\.\))$/) { + str = str ". " + } + if (wflag == 3) { + comment(str) + } else if (wflag == 2) { + warn(str) + } else if (wflag == 1) { + flaw(str) + } else { + err(str) + } + if ((option_verbose || option_submitcheck) && option_pass2) { + showsection(name) + } } function sectionflaw(name, str) { - sectionerr(name, str, 1) + sectionerr(name, str, 1) } function sectionwarn(name, str) { - sectionerr(name, str, 2) + sectionerr(name, str, 2) } # ---------------------------------------------------------------------- @@ -3355,13 +3355,13 @@ function sectionwarn(name, str) # function showalmost(name, orig) { - p2 = almost_boilerplate[name] - p2 = fold(p2, " ", bpcols) - p2 = sprintf(" %s\n\n", p2) - if (orig) { - p2 = markdiff(orig, p2) - } - printf (p2) + p2 = almost_boilerplate[name] + p2 = fold(p2, " ", bpcols) + p2 = sprintf(" %s\n\n", p2) + if (orig) { + p2 = markdiff(orig, p2) + } + printf (p2) } # ---------------------------------------------------------------------- @@ -3369,35 +3369,35 @@ function showalmost(name, orig) # function showsection(name, suppress, initial, final) { - p = bp[name] - "date +'%Y'" | getline year - # Get rid of regexp stuff in the boilerplate text we show the user: - # - mark metacharacters with mark character "!" - gsub(/[()|?+*^$]/, "!&", p) - # - get rid of mark preceeded by escape char... - gsub(/\\!/, "", p) - # - get rid of alternates, keeping the first only - gsub(/!\|[^)]*!\)/, "", p) - # - and we can get rid of metacharacters not preceeded by escape char - gsub(/![\(\)?+*^$]/, "", p) - # and also of escape chars themselves - gsub(/\\/, "", p) - # - also say "year" instead of "[0-9]" - ##gsub(/\[0-9\]/, "", p); - gsub(/\[0-9\]\[0-9\]\[0-9\]\[0-9\]/, year, p) - if (suppress < 2) { - note(initial expandname(name) final ":") - } - p1 = fold(p, " ", bpcols) - p1 = sprintf(" %s", p1) - printf (p1) - if (name in almost_boilerplate && suppress == 0) { - note("\n\n ... text found in draft:") - showalmost(name, p1) - print "" - } else { - print "\n" - } + p = bp[name] + "date +'%Y'" | getline year + # Get rid of regexp stuff in the boilerplate text we show the user: + # - mark metacharacters with mark character "!" + gsub(/[()|?+*^$]/, "!&", p) + # - get rid of mark preceeded by escape char... + gsub(/\\!/, "", p) + # - get rid of alternates, keeping the first only + gsub(/!\|[^)]*!\)/, "", p) + # - and we can get rid of metacharacters not preceeded by escape char + gsub(/![\(\)?+*^$]/, "", p) + # and also of escape chars themselves + gsub(/\\/, "", p) + # - also say "year" instead of "[0-9]" + ##gsub(/\[0-9\]/, "", p); + gsub(/\[0-9\]\[0-9\]\[0-9\]\[0-9\]/, year, p) + if (suppress < 2) { + note(initial expandname(name) final ":") + } + p1 = fold(p, " ", bpcols) + p1 = sprintf(" %s", p1) + printf (p1) + if (name in almost_boilerplate && suppress == 0) { + note("\n\n ... text found in draft:") + showalmost(name, p1) + print "" + } else { + print "\n" + } } # ---------------------------------------------------------------------- @@ -3405,9 +3405,9 @@ function showsection(name, suppress, initial, final) # function strip(str) { - sub(/^[ \t\f\r]+/, "", str) - sub(/[ \t\f\r]+$/, "", str) - return str + sub(/^[ \t\f\r]+/, "", str) + sub(/[ \t\f\r]+$/, "", str) + return str } # ---------------------------------------------------------------------- @@ -3415,67 +3415,67 @@ function strip(str) # function update_references(this, pos) { - if (! match(this, /\[Page/)) { - nnnote(sprintf("update_references( %s)\n", this)) - if (match(this, "(^|[\\]A-Za-z0-9 \t.()])" reference_format "\\)?([) \t,;:.?[]|$)")) { - line[pos] = this - if (in_refs && this ~ ("^ *([0-9.]+ *)?" reference_format)) { - # Reference definitions - match(this, reference_format) - reftag = substr(this, RSTART + 1, RLENGTH - 2) - numrefs = split(reftag, reftags, /, +/) - for (i = 1; i <= numrefs; i++) { - reftag = reftags[i] - ref_def[reftag] = pos - if (! (reftag in ref_def_seen)) { - ref_def_seen[reftag] - ref_def_list[++ref_def_count] = reftag - } - if (reftag ~ /^[0-9]+$/) { - has_numeric_refs = 1 - } else { - has_symbolic_refs = 1 - } - if (option_pass2) { - nnnote(sprintf("\tref_def[%s] at %s: %s\n", reftag, pos, this)) - } - ref_text[reftag] = this - if (in_normref) { - ref_norm[reftag] - } - } - } else { - # Reference usage - while (match(this, reference_format)) { - reftag = substr(this, RSTART + 1, RLENGTH - 2) - numrefs = split(reftag, reftags, /, +/) - for (i = 1; i <= numrefs; i++) { - tags = substr(this, RSTART + 1, RLENGTH - 2) - split(tags, reftags, /(,|, )/) - for (i in reftags) { - reftag = reftags[i] - ref_use[reftag] = pos - if (! (reftag in ref_use_seen)) { - ref_use_seen[reftag] - ref_use_list[++ref_use_count] = reftag - } - if (option_verbose > 2 && option_pass2) { - printf "\tref_use[%s] = %s\n", reftag, pos - } - } - this = substr(this, RSTART + RLENGTH) - } - } - } - } else if (option_verbose && option_pass1) { - match(this, /\[[0-9A-Z-]+\]/) - printf "%s(%d): Unexpected reference format: '...%s...'\n", FILENAME, pos, substr(this, RSTART - 5, RLENGTH + 10) - if (option_verbose > 1) { - printf " --> %s\n", this - printf " %*s\n", RSTART, "^" - } - } - } + if (! match(this, /\[Page/)) { + nnnote(sprintf("update_references( %s)\n", this)) + if (match(this, "(^|[\\]A-Za-z0-9 \t.()])" reference_format "\\)?([) \t,;:.?[]|$)")) { + line[pos] = this + if (in_refs && this ~ ("^ *([0-9.]+ *)?" reference_format)) { + # Reference definitions + match(this, reference_format) + reftag = substr(this, RSTART + 1, RLENGTH - 2) + numrefs = split(reftag, reftags, /, +/) + for (i = 1; i <= numrefs; i++) { + reftag = reftags[i] + ref_def[reftag] = pos + if (! (reftag in ref_def_seen)) { + ref_def_seen[reftag] + ref_def_list[++ref_def_count] = reftag + } + if (reftag ~ /^[0-9]+$/) { + has_numeric_refs = 1 + } else { + has_symbolic_refs = 1 + } + if (option_pass2) { + nnnote(sprintf("\tref_def[%s] at %s: %s\n", reftag, pos, this)) + } + ref_text[reftag] = this + if (in_normref) { + ref_norm[reftag] + } + } + } else { + # Reference usage + while (match(this, reference_format)) { + reftag = substr(this, RSTART + 1, RLENGTH - 2) + numrefs = split(reftag, reftags, /, +/) + for (i = 1; i <= numrefs; i++) { + tags = substr(this, RSTART + 1, RLENGTH - 2) + split(tags, reftags, /(,|, )/) + for (i in reftags) { + reftag = reftags[i] + ref_use[reftag] = pos + if (! (reftag in ref_use_seen)) { + ref_use_seen[reftag] + ref_use_list[++ref_use_count] = reftag + } + if (option_verbose > 2 && option_pass2) { + printf "\tref_use[%s] = %s\n", reftag, pos + } + } + this = substr(this, RSTART + RLENGTH) + } + } + } + } else if (option_verbose && option_pass1) { + match(this, /\[[0-9A-Z-]+\]/) + printf "%s(%d): Unexpected reference format: '...%s...'\n", FILENAME, pos, substr(this, RSTART - 5, RLENGTH + 10) + if (option_verbose > 1) { + printf " --> %s\n", this + printf " %*s\n", RSTART, "^" + } + } + } } # ---------------------------------------------------------------------- @@ -3483,7 +3483,7 @@ function update_references(this, pos) # function usage() { - print "" "Usage: idnits [options] filename\n" "\n" " Options:\n" "\t--version\tPrint the version and exit\n" "\t--help\t\tPrint this text and exit\n" "\t--nowarn\tDon't issue warnings, only ID-Checklist violations\n" "\t--verbose\tShow more information about offending lines\n" "\t--nitcount\tShow a count of nits\n" "\t--debug\t\tDebug output, especially of boilerplate matching\n" "\t--year NNNN\tExpect the given year in the boilerplate\n" "\t--checklistwarn\tOnly warn (no errors) for ID-Checklist violations\n" "\t--nonascii\tDisable warnings for non-ascii characters\n" "\t--submitcheck\tOnly output errors and warnings related to 1id-guidelines\n" "\t--status doctype Assume the given intended document type\n" "" + print "" "Usage: idnits [options] filename\n" "\n" " Options:\n" "\t--version\tPrint the version and exit\n" "\t--help\t\tPrint this text and exit\n" "\t--nowarn\tDon't issue warnings, only ID-Checklist violations\n" "\t--verbose\tShow more information about offending lines\n" "\t--nitcount\tShow a count of nits\n" "\t--debug\t\tDebug output, especially of boilerplate matching\n" "\t--year NNNN\tExpect the given year in the boilerplate\n" "\t--checklistwarn\tOnly warn (no errors) for ID-Checklist violations\n" "\t--nonascii\tDisable warnings for non-ascii characters\n" "\t--submitcheck\tOnly output errors and warnings related to 1id-guidelines\n" "\t--status doctype Assume the given intended document type\n" "" } # ---------------------------------------------------------------------- @@ -3491,15 +3491,15 @@ function usage() # function warn(str, indented) { - if (option_warn) { - print fold(" " warnmark " " str, " ", columns) - if (indented) { - print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) - print fold(" '" indented "' )", " ", columns) - } - print "" - warnings++ - } + if (option_warn) { + print fold(" " warnmark " " str, " ", columns) + if (indented) { + print fold(" (A line matching the expected section header was found, but with an unexpected indentation:", " ", columns) + print fold(" '" indented "' )", " ", columns) + } + print "" + warnings++ + } } # ---------------------------------------------------------------------- @@ -3508,9 +3508,9 @@ function warn(str, indented) # Warnings which are IESG checlist warnings, but not submission warnings function warnc(str, indented) { - if (! option_submitcheck) { - warn(str, indented) - } + if (! option_submitcheck) { + warn(str, indented) + } } EOF From 40bcc283eca9f1a358f3bdbb335ad63295fecb57 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Wed, 23 Oct 2024 14:29:52 -0500 Subject: [PATCH 3/8] feat: handle tlp6 boilerplate --- idnits | 195 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 139 insertions(+), 56 deletions(-) diff --git a/idnits b/idnits index c954bea..41f7a6f 100755 --- a/idnits +++ b/idnits @@ -529,6 +529,15 @@ BEGIN { # This applies to non-IETF streams bp["trust-28-dec-2009_6_b_ii_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" # ---------------------------------------------------------------------------------------------- + bp["tlp6_copyright"] = "Copyright \\(c\\) \\(?[0-9][0-9][0-9][0-9]\\)?\\..+ IETF Intellectual Property " "Management Corporation and the persons identified as the document authors." + bp["tlp6_copyright_now"] = sprintf("Copyright \\(c\\) %s IETF Intellectual Property " "Management Corporation and the persons identified as the document authors.", year) + bp["tlp6_bcp_conformance"] = bp["trust-28-dec-2009_6_a"] + bp["tlp6_ietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "Revised BSD License text as described in Section 4.e of the " "Technical Legal Provisions and are provided without warranty as described " "in the Revised BSD License\\.$" + bp["tlp6_nonietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" + bp["tlp6_noderivatives_pubrfc"] = bp["trust-28-dec-2009_6_c_i"] + bp["tlp6_noderivatives_pubdraft"] = bp["trust-28-dec-2009_6_c_ii"] + bp["tlp6_pre5378"] = bp["trust-28-dec-2009_6_c_iii"] + # ---------------------------------------------------------------------------------------------- bp["rfc2026_10_4A"] = "The IETF takes no position regarding the validity or scope of " "any intellectual property or other rights that might be claimed " "to pertain to the implementation or use of the technology " "described in this document or the extent to which any license " "under such rights might or might not be available; neither does " "it represent that it has made any effort to identify any such " "rights. Information on the IETF's procedures with respect to " "rights in standards-track and standards-related documentation " "can be found in BCP-11. Copies of claims of rights made " "available for publication and any assurances of licenses to " "be made available, or the result of an attempt made " "to obtain a general license or permission for the use of such " "proprietary rights by implement[oe]rs or users of this " "specification can be obtained from the IETF Secretariat.$" bp["rfc2026_10_4B"] = "The IETF invites any interested party to bring to its " "attention any copyrights, patents or patent applications, or " "other proprietary rights which may cover technology that may be " "required to practice this standard. Please address the " "information to the IETF Executive Director.$" bp["rfc2026_10_4C_p1"] = "Copyright \\([Cc]\\) The Internet Society \\(?[0-9][0-9][0-9][0-9]\\)?. All Rights " "Reserved.$" @@ -1063,7 +1072,7 @@ normalized ~ /by submitting this internet-draft/ { normalized ~ /this document may not be modified/ { para = get_para() - match_para(para, "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_c_ii") || match_para(para, "rfc3978_5_2a") || match_para(para, "rfc3978_5_2ax") || match_para(para, "rfc3978_5_2b") || match_para(para, "rfc3978_5_2bx") + match_para(para, "tlp6_noderivatives_pubrfc") || match_para(para, "tlp6_noderivatives_pubdraft") || match_para(para, "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_c_ii") || match_para(para, "rfc3978_5_2a") || match_para(para, "rfc3978_5_2ax") || match_para(para, "rfc3978_5_2b") || match_para(para, "rfc3978_5_2bx") } normalized ~ /copyright ?\(c\) ?the / { @@ -1156,20 +1165,30 @@ normalized ~ /this internet-draft is submitted to ietf in/ { } normalized ~ /this internet-draft is submitted in full/ { - para = get_para() - match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1a") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_ii") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_iii") + para = get_para() + match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pubrfc") || match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pubdraft") || match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pre5378") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1a") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_ii") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_iii") } normalized ~ /copyright \(c\) [0-9]+ ietf trust and/ { if (! in_mib) { some_copyright = FNR para = get_para() + # This looks like a bug... has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_i_p3") has_some_year = match_para(para, "trust-28-dec-2009_6_b_i_p2", "trust-28-dec-2009_6_b_ii_p3") has_this_year = match_para(para, "trust-28-dec-2009_6_b_i_p2_now") } } +normalized ~ /copyright \(c\) [0-9]+ ietf ipmc and/ { + if (! in_mib) { + some_copyright = FNR + para = get_para() + has_some_year = match_para(para, "tlp6_copyright", "tlp6_ietf_tlp_section") || match_para(para, "tlp6_copyright", "tlp6_nonietf_tlp_section") + has_this_year = match_para(para, "tlp6_copyright_now") + } +} + normalized ~ /this document is subject to bcp 78/ { para = get_para() match_para(para, "trust-12-feb-2009_6_b_p3", "trust-12-feb-2009_6_c_i") @@ -1187,12 +1206,16 @@ normalized ~ /this document is subject to bcp 78/ { match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_i") match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_ii") match_para(para, "trust-28-dec-2009_6_b_ii_p3", "trust-28-dec-2009_6_c_iii") + match_para(para, "tlp6_ietf_tlp_section", "tlp6_noderivatives_pubrfc") + match_para(para, "tlp6_ietf_tlp_section", "tlp6_noderivatives_pubdraft") + match_para(para, "tlp6_ietf_tlp_section", "tlp6_pre5378") } normalized ~ /this document may contain material from ietf/ { para = get_para() match_para(para, "trust-12-sep-2009_6_c_iii") match_para(para, "trust-28-dec-2009_6_c_iii") + match_para(para, "tlp6_pre5378") } # RFC 2119 compliance @@ -2506,71 +2529,131 @@ function report(filename) printf ("\n Showing Errors (" errmark "), Flaws (" flawmark "), Warnings (" warnmark "), and Comments (" infomark ").\n") print (" Errors MUST be fixed before draft submission. Flaws SHOULD be fixed before draft submission.") } - announce("Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info):") + announce("Checking boilerplate required by RFC 5378 and the IETF IPMC (see https://www.ietf-ipmc.org/license-info):") errcount = errors flawcount = flaws warncount = warnings commentcount = comments - # 12 Sep 2009 values below are valid during the post-28-dec-2009 transition - if (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"] || has["trust-28-dec-2009_6_b_i_p2"] || has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"]) { - # We have some text from the current Trust Provisions boilerplate. Check that we don't have older - # boilerplate, too. + # 12 Sep 2009 values below were valid during the post-28-dec-2009 transition + has_roughly_tlp5_bits = has["trust-28-dec-2009_6_b_i_p2"] || has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"] + has_tlp6_bits = has["tlp6_copyright"] || has["tlp6_ietf_tlp_section"] || has["tlp6_nonietf_tlp_section"] + if (has_roughly_tlp5_bits || has_tlp6_bits || has["tlp6_bcp_conformance"]) { + # the bcp conformance clause (aka trust-28-dec-2009_6_a) hasn't changed between tlp5 and tlp6 + # We are no longer allowing "trust-16-oct-2008_6_a" matches to get into this branch + # Check that we don't have older boilerplate, too. + if (has_roughly_tlp5_bits && !has_tlp6_bits) { + warn("The document has boilerplate roughly matching the Trust TLP 5. The IPM TLP 6 boilerplate will soon be required. See https://www.ietf-ipmc/license-info") + } + if (has_roughly_tlp5_bits && has_tlp6_bits) { + # has_roughly_tlp5_bits will refactor later into the sections below + err("The document contains boilerplate matching both the Trust TLP5 and the IPM TLP 6. See https://www.ietf-ipmc/license-info") + for (bpname in bp) { + if (bpname ~ /^trust-/) { + if (has[bpname] && ! (bpname ~ "_now")) { + newandolderr(bpname, "IETF IPM Technical Legal Provisions of Dec 2024") + } + } + } + } for (bpname in bp) { if (bpname ~ /^rfc2026/ || bpname ~ /^rfc3667/ || bpname ~ /^rfc3978/ || bpname ~ /^rfc3979/) { if (has[bpname] && ! (bpname ~ "_now")) { - newandolderr(bpname, "IETF Trust Provisions of 12 Sep 2009") + newandolderr(bpname, "IETF IPM Technical Legal Provisions of Dec 2024") } } } - if (! is_rfc) { - if (! (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"])) { - sectionerr("trust-28-dec-2009_6_a", "Notice of Compliance with BCP 78 and BCP 79 according to " "IETF Trust Provisions of 28 Dec 2009, Section 6.a " "or Provisions of 12 Sep 2009, Section 6.a") - } - } - if (! has["trust-28-dec-2009_6_b_i_p2"]) { - sectionerr("trust-28-dec-2009_6_b_i_p2", "IETF Trust Provisions of 28 Dec 2009, Section 6.b Copyright Notice") - } - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { - if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-12-sep-2009_6_b_p3"])) { - sectionerr("trust-28-dec-2009_6_b_i_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.i or Provisions of 12 Sep 2009 Section 6.b") - if (has["trust-28-dec-2009_6_b_ii_p3"]) { - comment("It seems you're using the 'non-IETF stream' Licence Notice instead") + if (!has_tlp6_bits) { + if (! is_rfc) { + if (! (has["trust-28-dec-2009_6_a"] || has["trust-12-sep-2009_6_a"] )) { + sectionerr("trust-28-dec-2009_6_a", "Notice of Compliance with BCP 78 and BCP 79 according to " "IETF Trust Provisions of 28 Dec 2009, Section 6.a " "or Provisions of 12 Sep 2009, Section 6.a") } } - } else if (full_docname ~ /^draft-(iab|irtf|rfced|rfc-editor)-/) { - if (! (has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { - sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") - if (has["trust-28-dec-2009_6_b_i_p3"]) { - comment("It seems you're using the 'IETF stream' Licence Notice instead") + if (! has["trust-28-dec-2009_6_b_i_p2"]) { + sectionerr("trust-28-dec-2009_6_b_i_p2", "IETF Trust Provisions of 28 Dec 2009, Section 6.b Copyright Notice") + } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_i_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.i or Provisions of 12 Sep 2009 Section 6.b") + if (has["trust-28-dec-2009_6_b_ii_p3"]) { + comment("It seems you're using the 'non-IETF stream' Licence Notice instead") + } + } + } else if (full_docname ~ /^draft-(iab|irtf|rfced|rfc-editor)-/) { + if (! (has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") + if (has["trust-28-dec-2009_6_b_i_p3"]) { + comment("It seems you're using the 'IETF stream' Licence Notice instead") + } } + } else if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { + sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") } - } else if (! (has["trust-28-dec-2009_6_b_i_p3"] || has["trust-28-dec-2009_6_b_ii_p3"] || has["trust-12-sep-2009_6_b_p3"])) { - sectionerr("trust-28-dec-2009_6_b_ii_p3", "License Notice according IETF Trust Provisions of 28 Dec 2009, Section 6.b.ii or Provisions of 12 Sep 2009 Section 6.b") - } - # The following is just an informational note because we've emitted an error earlier: - if (has["trust-12-feb-2009_6_b_p3"]) { - note("(You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Feb 2009 rather than one of the newer Notices. " "See https://trustee.ietf.org/license-info/.)\n") - } - if (has["trust-12-sep-2009_6_b_p3"]) { - err("You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Sep 2009 rather than the newer Notice from 28 Dec 2009. " "(See https://trustee.ietf.org/license-info/)") - } - if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { - if (has["trust-28-dec-2009_6_c_i"]) { - warn("The document has an IETF Trust Provisions of 28 Dec 2009, Section 6.c(i) Publication Limitation clause.") + # The following is just an informational note because we've emitted an error earlier: + if (has["trust-12-feb-2009_6_b_p3"]) { + note("(You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Feb 2009 rather than one of the newer Notices. " "See https://trustee.ietf.org/license-info/.)\n") + } + if (has["trust-12-sep-2009_6_b_p3"]) { + err("You're using the IETF Trust Provisions' Section 6.b License Notice from " "12 Sep 2009 rather than the newer Notice from 28 Dec 2009. " "(See https://trustee.ietf.org/license-info/)") } - if (has["trust-28-dec-2009_6_c_ii"]) { - err("The document has an IETF Trust Provisions, 28 Dec 2009, Section 6.c(ii) Publication Limitation clause.") + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (has["trust-28-dec-2009_6_c_i"]) { + warn("The document has an IETF Trust Provisions of 28 Dec 2009, Section 6.c(i) Publication Limitation clause.") + } + if (has["trust-28-dec-2009_6_c_ii"]) { + err("The document has an IETF Trust Provisions, 28 Dec 2009, Section 6.c(ii) Publication Limitation clause.") + } + } else { + if (has["trust-28-dec-2009_6_c_i"]) { + comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(i) Publication Limitation clause.") + } + if (has["trust-28-dec-2009_6_c_ii"]) { + comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(ii) Publication " "Limitation clause. If this document is intended for submission to the IESG for " "publication, this constitutes an error.") + } } } else { - if (has["trust-28-dec-2009_6_c_i"]) { - comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(i) Publication Limitation clause.") + if (! is_rfc) { + if (!has["tlp6_bcp_conformance"]) { + sectionerr("tlp6_bcp_conformance", "Notice of Compliance with BCP 78 and BCP 79 according to " "IETF IPM Technical Legal Provisions of Dec 2024, Section 6.a") + } + } + if (! has["tlp6_bcp_copyright"]) { + sectionerr("tlp6_bcp_copyright", "IETF IPM Technical Legal Provisions of Dec 2024, Section 6.b Copyright Notice") } - if (has["trust-28-dec-2009_6_c_ii"]) { - comment("The document has an IETF Trust Provisions (28 Dec 2009) Section 6.c(ii) Publication " "Limitation clause. If this document is intended for submission to the IESG for " "publication, this constitutes an error.") + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (! has["tlp6_ietf_tlp_section"]) { + sectionerr("tlp6_ietf_tlp_section", "License Notice according IETF IPM Technical Legal Provisions of Dec 2024, Section 6.b.i") + if (has["tlp6_nonietf_tlp_section"]) { + comment("It seems you're using the 'non-IETF stream' Licence Notice instead") + } + } + } else if (full_docname ~ /^draft-(iab|irtf|rfced|rfc-editor)-/) { + if (! has["tlp6_nonietf_tlp_section"]) { + sectionerr("tlp6_nonietf_tlp_section", "License Notice according IETF IPM Technical Legal Provisions of Dec 2024, Section 6.b.ii") + if (has["tlp6_ietf_tlp_section"]) { + comment("It seems you're using the 'IETF stream' Licence Notice instead") + } + } + } else if (! (has["tlp6_ietf_tlp_section"] || has["tlp6_nonietf_tlp_section"] )) { + sectionerr("tlp6_nonietf_tlp_section", "License Notice according IETF IPM Technical Legal Provisions of Dec 2024, Section 6.b.ii") } + if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { + if (has["tlp6_noderivatives_pubrfc"]) { + warn("The document has an IETF IPM Technical Legal Provisions of Dec 2024, Section 6.c(i) Publication Limitation clause.") + } + if (has["tlp6_noderivatives_pubdraft"]) { + err("The document has an IETF IPM Technical Legal Provisions of Dec 2024, Section 6.c(ii) Publication Limitation clause.") + } + } else { + if (has["tlp6_noderivatives_pubrfc"]) { + comment("The document has an IETF IPM Technical Legal Provisions of Dec 2024, Section 6.c(i) Publication Limitation clause.") + } + if (has["tlp6_noderivatives_pubdraft"]) { + comment("The document has an IETF IPM Techincal Legal Provisions of Dec 2024, Section 6.c(ii) Publication " "Limitation clause. If this document is intended for submission to the IESG for " "publication, this constitutes an error.") + } + } } } else if ((has["rfc3667_5_1"] || has["rfc3978_5_1_a"] || has["rfc3978_5_1"] || has["rfc3978_5_2b"] || has["rfc3978_5_3"] || has["rfc3978_5_5"] || has["rfc3978_5_5_u4748"] || has["rfc3979_5_p1"] || has["rfc3979_5_p2"] || has["rfc3979_5_p3"])) { - err("It looks like you're using RFC 3978 boilerplate. You should update this to the " "boilerplate described in the IETF Trust License Policy document (see " "https://trustee.ietf.org/license-info), which is required now.") + err("It looks like you're using RFC 3978 boilerplate. You should update this to the " "boilerplate described in the IETF IPM Techincal Legal Provisions document (see " "https://www.ietf-ipmc.org/license-info), which is required now.") if (has["rfc3667_5_1"]) { olderr("rfc3667_5_1") } @@ -2659,7 +2742,7 @@ function report(filename) } } if (has["rfc2026_lax_claim"] || has["rfc2026b_lax_claim"]) { - err("The document claims conformance with section 10 of RFC 2026, but uses " "some RFC 3978/3979 boilerplate. As RFC 3978/3979 replaces section 10 of " "RFC 2026, you should not claim conformance with it if you have changed " "to using RFC 3978/3979 boilerplate.") + err("The document claims conformance with section 10 of RFC 2026, but uses " "some RFC 3978/3979 boilerplate.") } if (! (has["rfc3978_5_1"]) && ! is_rfc) { sectionerr("rfc3978_5_1", "RFC 3978 Section 5.1 IPR Disclosure Acknowledgement") @@ -2681,7 +2764,7 @@ function report(filename) } if (! has["rfc3978_5_4_p1_u4748"]) { if (has["rfc3978_5_4_p1"]) { - err("This document has an original RFC 3978 Section 5.4 Copyright Line, " "instead of the newer IETF Trust Copyright according " "to RFC 4748.") + err("This document has an original RFC 3978 Section 5.4 Copyright Line") } else { sectionerr("rfc3978_5_4_p1_u4748", "RFC 3978 Section 5.4 (updated by RFC 4748) Copyright Line") } @@ -2691,7 +2774,7 @@ function report(filename) } if (! has["rfc3978_5_5_u4748"]) { if (has["rfc3978_5_5"]) { - err("This document has an original RFC 3978 Section 5.5 Disclaimer, " "instead of the newer disclaimer which includes the IETF Trust according " "to RFC 4748.") + err("This document has an original RFC 3978 Section 5.5 Disclaimer") } else { sectionerr("rfc3978_5_5_u4748", "RFC 3978 Section 5.5 (updated by RFC 4748) Disclaimer") } @@ -2712,7 +2795,7 @@ function report(filename) } } if (has["rfc3667_3_claim"] || (has["rfc3667_5_1"] || has["rfc3978_5_1_a"]) && ! has["rfc3978_5_1"]) { - err("The document uses RFC 3667 boilerplate or RFC 3978-like " "boilerplate instead of verbatim RFC 3978 boilerplate. After 6 May 2005, " "submission of drafts without verbatim RFC 3978 boilerplate is not " "accepted.") + err("The document uses RFC 3667 boilerplate or RFC 3978-like " "boilerplate") note("The following non-3978 patterns matched text found in the document. That text should be removed or replaced:\n") if (has["rfc3667_3_claim"]) { showsection("rfc3667_3_claim", 2) @@ -2747,7 +2830,7 @@ function report(filename) } print "" } - err("Looks like you're using RFC 2026 boilerplate. This must be updated to follow RFC 3978/3979, as updated by RFC 4748.") + err("Looks like you're using RFC 2026 boilerplate. This must be updated to current boilerplate.") } else { if (some_copyright) { copyright_msg = " Found some kind of copyright notice around line " some_copyright " but it does not match any copyright boilerplate known by this tool." @@ -2755,10 +2838,10 @@ function report(filename) copyright_msg = "" } err("Cannot find the required boilerplate sections (Copyright, IPR, etc.) in this document." copyright_msg) - note("Expected boilerplate is as follows today (" today ") according to https://trustee.ietf.org/license-info :\n") - showsection("trust-28-dec-2009_6_a") - showsection("trust-28-dec-2009_6_b_i_p2") - showsection("trust-28-dec-2009_6_b_i_p3") + note("Expected boilerplate is as follows today (" today ") according to https://www.ietf-ipmc.org/license-info :\n") + showsection("tlp6_bcp_conformance") + showsection("tlp6_copyright") + showsection("tlp6_ietf_tlp_section") } if (errcount == errors && flawcount == flaws && warncount == warnings && commentcount == comments) { note("No issues found here.") From e72502036cbfcb7fcf7370a1c46363048755694d Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Wed, 23 Oct 2024 16:25:23 -0500 Subject: [PATCH 4/8] chore: tabs to spaces --- idnits | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/idnits b/idnits index 41f7a6f..56fa00d 100755 --- a/idnits +++ b/idnits @@ -530,13 +530,13 @@ BEGIN { bp["trust-28-dec-2009_6_b_ii_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" # ---------------------------------------------------------------------------------------------- bp["tlp6_copyright"] = "Copyright \\(c\\) \\(?[0-9][0-9][0-9][0-9]\\)?\\..+ IETF Intellectual Property " "Management Corporation and the persons identified as the document authors." - bp["tlp6_copyright_now"] = sprintf("Copyright \\(c\\) %s IETF Intellectual Property " "Management Corporation and the persons identified as the document authors.", year) + bp["tlp6_copyright_now"] = sprintf("Copyright \\(c\\) %s IETF Intellectual Property " "Management Corporation and the persons identified as the document authors.", year) bp["tlp6_bcp_conformance"] = bp["trust-28-dec-2009_6_a"] - bp["tlp6_ietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "Revised BSD License text as described in Section 4.e of the " "Technical Legal Provisions and are provided without warranty as described " "in the Revised BSD License\\.$" - bp["tlp6_nonietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" - bp["tlp6_noderivatives_pubrfc"] = bp["trust-28-dec-2009_6_c_i"] - bp["tlp6_noderivatives_pubdraft"] = bp["trust-28-dec-2009_6_c_ii"] - bp["tlp6_pre5378"] = bp["trust-28-dec-2009_6_c_iii"] + bp["tlp6_ietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "Revised BSD License text as described in Section 4.e of the " "Technical Legal Provisions and are provided without warranty as described " "in the Revised BSD License\\.$" + bp["tlp6_nonietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" + bp["tlp6_noderivatives_pubrfc"] = bp["trust-28-dec-2009_6_c_i"] + bp["tlp6_noderivatives_pubdraft"] = bp["trust-28-dec-2009_6_c_ii"] + bp["tlp6_pre5378"] = bp["trust-28-dec-2009_6_c_iii"] # ---------------------------------------------------------------------------------------------- bp["rfc2026_10_4A"] = "The IETF takes no position regarding the validity or scope of " "any intellectual property or other rights that might be claimed " "to pertain to the implementation or use of the technology " "described in this document or the extent to which any license " "under such rights might or might not be available; neither does " "it represent that it has made any effort to identify any such " "rights. Information on the IETF's procedures with respect to " "rights in standards-track and standards-related documentation " "can be found in BCP-11. Copies of claims of rights made " "available for publication and any assurances of licenses to " "be made available, or the result of an attempt made " "to obtain a general license or permission for the use of such " "proprietary rights by implement[oe]rs or users of this " "specification can be obtained from the IETF Secretariat.$" bp["rfc2026_10_4B"] = "The IETF invites any interested party to bring to its " "attention any copyrights, patents or patent applications, or " "other proprietary rights which may cover technology that may be " "required to practice this standard. Please address the " "information to the IETF Executive Director.$" From 3437654dbc9436310c61d903836856a2de51cd72 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Wed, 23 Oct 2024 16:29:29 -0500 Subject: [PATCH 5/8] fix: match xml2rfc output in tlp_section check --- idnits | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idnits b/idnits index 56fa00d..7d26c72 100755 --- a/idnits +++ b/idnits @@ -532,7 +532,7 @@ BEGIN { bp["tlp6_copyright"] = "Copyright \\(c\\) \\(?[0-9][0-9][0-9][0-9]\\)?\\..+ IETF Intellectual Property " "Management Corporation and the persons identified as the document authors." bp["tlp6_copyright_now"] = sprintf("Copyright \\(c\\) %s IETF Intellectual Property " "Management Corporation and the persons identified as the document authors.", year) bp["tlp6_bcp_conformance"] = bp["trust-28-dec-2009_6_a"] - bp["tlp6_ietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "Revised BSD License text as described in Section 4.e of the " "Technical Legal Provisions and are provided without warranty as described " "in the Revised BSD License\\.$" + bp["tlp6_ietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "Revised BSD License text as described in Section 4.e of the " "IETF IPM Technical Legal Provisions and are provided without warranty as described " "in the Revised BSD License\\.$" bp["tlp6_nonietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" bp["tlp6_noderivatives_pubrfc"] = bp["trust-28-dec-2009_6_c_i"] bp["tlp6_noderivatives_pubdraft"] = bp["trust-28-dec-2009_6_c_ii"] From 77a01178ad80b3f37425352233e5a32d12f26cb7 Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Thu, 24 Oct 2024 12:56:49 -0500 Subject: [PATCH 6/8] fix: tune regexes. fix has index typo. --- idnits | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/idnits b/idnits index 7d26c72..729814f 100755 --- a/idnits +++ b/idnits @@ -529,8 +529,8 @@ BEGIN { # This applies to non-IETF streams bp["trust-28-dec-2009_6_b_ii_p3"] = "This document is subject to BCP 78 and the IETF Trust's Legal Provisions " "Relating to IETF Documents \\(https?://trustee\\.ietf\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" # ---------------------------------------------------------------------------------------------- - bp["tlp6_copyright"] = "Copyright \\(c\\) \\(?[0-9][0-9][0-9][0-9]\\)?\\..+ IETF Intellectual Property " "Management Corporation and the persons identified as the document authors." - bp["tlp6_copyright_now"] = sprintf("Copyright \\(c\\) %s IETF Intellectual Property " "Management Corporation and the persons identified as the document authors.", year) + bp["tlp6_copyright"] = "Copyright \\(c\\) \\(?[0-9][0-9][0-9][0-9]\\)? IETF Intellectual Property " "Management Corporation and the persons identified as the document authors. All rights reserved\\." + bp["tlp6_copyright_now"] = sprintf("Copyright \\(c\\) %s IETF Intellectual Property " "Management Corporation and the persons identified as the document authors. All rights reserved\\.", year) bp["tlp6_bcp_conformance"] = bp["trust-28-dec-2009_6_a"] bp["tlp6_ietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\. " "Code Components extracted from this document must include " "Revised BSD License text as described in Section 4.e of the " "IETF IPM Technical Legal Provisions and are provided without warranty as described " "in the Revised BSD License\\.$" bp["tlp6_nonietf_tlp_section"] = "This document is subject to BCP 78 and the IETF IPM Technical Legal Provisions " "Relating to IETF Documents \\(https://www\\.ietf-ipm\\.org/license-inf(o|o/)\\) " "in effect on the date of publication of this document\\. " "Please review these documents carefully, as they describe your " "rights and restrictions with respect to this document\\.$" @@ -1180,7 +1180,7 @@ normalized ~ /copyright \(c\) [0-9]+ ietf trust and/ { } } -normalized ~ /copyright \(c\) [0-9]+ ietf ipmc and/ { +normalized ~ /copyright \(c\) [0-9]+ ietf intellectual property management corporation/ { if (! in_mib) { some_copyright = FNR para = get_para() @@ -2616,8 +2616,8 @@ function report(filename) sectionerr("tlp6_bcp_conformance", "Notice of Compliance with BCP 78 and BCP 79 according to " "IETF IPM Technical Legal Provisions of Dec 2024, Section 6.a") } } - if (! has["tlp6_bcp_copyright"]) { - sectionerr("tlp6_bcp_copyright", "IETF IPM Technical Legal Provisions of Dec 2024, Section 6.b Copyright Notice") + if (! has["tlp6_copyright"]) { + sectionerr("tlp6_copyright", "IETF IPM Technical Legal Provisions of Dec 2024, Section 6.b Copyright Notice") } if (full_docname ~ /^draft-ietf/ || destcode in ietf_stream_codes) { if (! has["tlp6_ietf_tlp_section"]) { From 94eb43f41559aebb7161b5c2f24da7f3ca6f412d Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Fri, 25 Oct 2024 08:22:12 -0500 Subject: [PATCH 7/8] fix: split bcp conformance match strategy. Reword update warning. --- idnits | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/idnits b/idnits index 729814f..d1617cf 100755 --- a/idnits +++ b/idnits @@ -1166,7 +1166,8 @@ normalized ~ /this internet-draft is submitted to ietf in/ { normalized ~ /this internet-draft is submitted in full/ { para = get_para() - match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pubrfc") || match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pubdraft") || match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pre5378") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1a") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_ii") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_iii") + match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pubrfc") || match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pubdraft") || match_para(para, "tlp6_bcp_conformance", "tlp6_noderivatives_pre5378") + match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1") || match_para(para, "trust-28-dec-2009_6_a", "1id_guidelines_p1a") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_i") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_ii") || match_para(para, "trust-28-dec-2009_6_a", "trust-28-dec-2009_6_c_iii") } normalized ~ /copyright \(c\) [0-9]+ ietf trust and/ { @@ -2542,7 +2543,7 @@ function report(filename) # We are no longer allowing "trust-16-oct-2008_6_a" matches to get into this branch # Check that we don't have older boilerplate, too. if (has_roughly_tlp5_bits && !has_tlp6_bits) { - warn("The document has boilerplate roughly matching the Trust TLP 5. The IPM TLP 6 boilerplate will soon be required. See https://www.ietf-ipmc/license-info") + warn("The document has boilerplate matching the Trust TLP 5. The IPM TLP 6 boilerplate will soon be required for submission. Updating now is encouraged. See https://www.ietf-ipmc/license-info") } if (has_roughly_tlp5_bits && has_tlp6_bits) { # has_roughly_tlp5_bits will refactor later into the sections below From 8006a22dcbcf4560e39783365fb8bde0aebabebc Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Fri, 25 Oct 2024 10:51:57 -0500 Subject: [PATCH 8/8] feat: updated version --- idnits | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idnits b/idnits index d1617cf..ea6d1f6 100755 --- a/idnits +++ b/idnits @@ -25,7 +25,7 @@ # # ----------------------------------------------------------------- -version="2.17.1"; +version="2.18.0"; progdate=""; export LC_ALL=C program=${0##*/}