draft-ietf-netmod-artwork-folding-10.txt   draft-ietf-netmod-artwork-folding-11.txt 
NETMOD Working Group K. Watsen NETMOD Working Group K. Watsen
Internet-Draft Watsen Networks Internet-Draft Watsen Networks
Intended status: Informational A. Farrel Intended status: Informational E. Erik
Expires: March 8, 2020 Old Dog Consulting Expires: May 6, 2020 Individual Contributor
A. Farrel
Old Dog Consulting
Q. Wu Q. Wu
Huawei Technologies Huawei Technologies
September 5, 2019 November 3, 2019
Handling Long Lines in Inclusions in Internet-Drafts and RFCs Handling Long Lines in Inclusions in Internet-Drafts and RFCs
draft-ietf-netmod-artwork-folding-10 draft-ietf-netmod-artwork-folding-11
Abstract Abstract
This document defines two strategies for handling long lines in This document defines two strategies for handling long lines in
width-bounded text content. One strategy is based on the historical width-bounded text content. One strategy is based on the historical
use of a single backslash ('\') character to indicate where line- use of a single backslash ('\') character to indicate where line-
folding has occurred, with the continuation occurring with the first folding has occurred, with the continuation occurring with the first
non-space (' ') character on the next line. The second strategy non-space (' ') character on the next line. The second strategy
extends the first strategy by adding a second backslash character to extends the first strategy by adding a second backslash character to
identify where the continuation begins and thereby able to handle identify where the continuation begins and is thereby able to handle
cases not supported by the first strategy. Both strategies use a cases not supported by the first strategy. Both strategies use a
self-describing header enabling automated reconstitution of the self-describing header enabling automated reconstitution of the
original content. original content.
Editorial Note (To be removed by RFC Editor) Editorial Note (To be removed by RFC Editor)
Please be aware that this document uses throughout the five-character Please be aware that this document uses throughout the five-character
text seqeuence located between the following two double-quotes: "(' text sequence located between the following two double-quotes: "('
')". It has been observed that some renderings of this text sequence ')". It has been observed that some renderings of this text sequence
produces a natural line break at the space character in the middle, produces a natural line break at the space character in the middle,
thus causing "('" to appear at the end of the first line and "')" to thus causing "('" to appear at the end of the first line and "')" to
appear at the beginning of the next line. Such a line-break is appear at the beginning of the next line. Such a line-break is
confusing and should not occur in the RFC output formats. confusing and should not occur in the RFC output formats.
Status of This Memo Status of This Memo
This Internet-Draft is submitted in full conformance with the This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79. provisions of BCP 78 and BCP 79.
skipping to change at page 2, line 7 skipping to change at page 2, line 10
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/. Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on March 8, 2020. This Internet-Draft will expire on May 6, 2020.
Copyright Notice Copyright Notice
Copyright (c) 2019 IETF Trust and the persons identified as the Copyright (c) 2019 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents Provisions Relating to IETF Documents
(https://trustee.ietf.org/license-info) in effect on the date of (https://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents publication of this document. Please review these documents
skipping to change at page 3, line 22 skipping to change at page 3, line 23
9.3. Example Showing "Smart" Folding . . . . . . . . . . . . . 14 9.3. Example Showing "Smart" Folding . . . . . . . . . . . . . 14
9.3.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 14 9.3.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 14
9.3.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 15 9.3.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 15
9.4. Example Showing "Forced" Folding . . . . . . . . . . . . 16 9.4. Example Showing "Forced" Folding . . . . . . . . . . . . 16
9.4.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 17 9.4.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 17
9.4.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 17 9.4.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 17
10. Security Considerations . . . . . . . . . . . . . . . . . . . 18 10. Security Considerations . . . . . . . . . . . . . . . . . . . 18
11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 18 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 18
12. References . . . . . . . . . . . . . . . . . . . . . . . . . 18 12. References . . . . . . . . . . . . . . . . . . . . . . . . . 18
12.1. Normative References . . . . . . . . . . . . . . . . . . 18 12.1. Normative References . . . . . . . . . . . . . . . . . . 18
12.2. Informative References . . . . . . . . . . . . . . . . . 18 12.2. Informative References . . . . . . . . . . . . . . . . . 19
Appendix A. Bash Shell Script: rfcfold . . . . . . . . . . . . . 20 Appendix A. Bash Shell Script: rfcfold . . . . . . . . . . . . . 20
Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 29 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 29
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 29 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 30
1. Introduction 1. Introduction
[RFC7994] sets out the requirements for plain-text RFCs and states [RFC7994] sets out the requirements for plain-text RFCs and states
that each line of an RFC (and hence of an Internet-Draft) must be that each line of an RFC (and hence of an Internet-Draft) must be
limited to 72 characters followed by the character sequence that limited to 72 characters followed by the character sequence that
denotes an end-of-line (EOL). denotes an end-of-line (EOL).
Internet-Drafts and RFCs often include example text or code Internet-Drafts and RFCs often include example text or code
fragments. Many times the example text or code exceeds the 72 fragments. Many times the example text or code exceeds the 72
skipping to change at page 3, line 50 skipping to change at page 3, line 51
recommended convention in place for how to handle long lines in such recommended convention in place for how to handle long lines in such
inclusions, other than advising authors to clearly indicate what inclusions, other than advising authors to clearly indicate what
manipulation has occurred. manipulation has occurred.
This document defines two strategies for handling long lines in This document defines two strategies for handling long lines in
width-bounded text content. One strategy is based on the historical width-bounded text content. One strategy is based on the historical
use of a single backslash ('\') character to indicate where line- use of a single backslash ('\') character to indicate where line-
folding has occurred, with the continuation occurring with the first folding has occurred, with the continuation occurring with the first
non-space (' ') character on the next line. The second strategy non-space (' ') character on the next line. The second strategy
extends the first strategy by adding a second backslash character to extends the first strategy by adding a second backslash character to
identify where the continuation begins and thereby able to handle identify where the continuation begins and is thereby able to handle
cases not supported by the first strategy. Both strategies use a cases not supported by the first strategy. Both strategies use a
self-describing header enabling automated reconstitution of the self-describing header enabling automated reconstitution of the
original content. original content.
The strategies defined in this document work on any text content, but The strategies defined in this document work on any text content, but
are primarily intended for a structured sequence of lines, such as are primarily intended for a structured sequence of lines, such as
would be referenced by the <sourcecode> element defined in would be referenced by the <sourcecode> element defined in
Section 2.48 of [RFC7991], rather than for two-dimensional imagery, Section 2.48 of [RFC7991], rather than for two-dimensional imagery,
such as would be referenced by the <artwork> element defined in such as would be referenced by the <artwork> element defined in
Section 2.5 of [RFC7991]. Section 2.5 of [RFC7991].
skipping to change at page 4, line 29 skipping to change at page 4, line 30
2. Applicability Statement 2. Applicability Statement
The formats and algorithms defined in this document may be used in The formats and algorithms defined in this document may be used in
any context, whether for IETF documents or in other situations where any context, whether for IETF documents or in other situations where
structured folding is desired. structured folding is desired.
Within the IETF, this work primarily targets the xml2rfc v3 Within the IETF, this work primarily targets the xml2rfc v3
<sourcecode> element (Section 2.48 of [RFC7991]) and the xml2rfc v2 <sourcecode> element (Section 2.48 of [RFC7991]) and the xml2rfc v2
<artwork> element (Section 2.5 of [RFC7749]) that, for lack of a <artwork> element (Section 2.5 of [RFC7749]) that, for lack of a
better option, is currently used for both source code and artwork. better option, is currently used for both source code and artwork.
This work may be also be used for the xml2rfc v3 <artwork> element This work may also be used for the xml2rfc v3 <artwork> element
(Section 2.5 of [RFC7991]) but, as described in Section 5.1, it is (Section 2.5 of [RFC7991]) but, as described in Section 5.1, it is
generally not recommended. generally not recommended.
3. Requirements Language 3. Requirements Language
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP "OPTIONAL" in this document are to be interpreted as described in BCP
14 [RFC2119] [RFC8174] when, and only when, they appear in all 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here. capitals, as shown here.
skipping to change at page 7, line 34 skipping to change at page 7, line 34
The first line is the following 46-character string that MAY be The first line is the following 46-character string that MAY be
surrounded by any number of printable characters. This first line surrounded by any number of printable characters. This first line
cannot itself be folded. cannot itself be folded.
NOTE: '\' line wrapping per BCP XXX (RFC XXXX) NOTE: '\' line wrapping per BCP XXX (RFC XXXX)
[Note to RFC Editor: Please replace XXX and XXXX with the numbers [Note to RFC Editor: Please replace XXX and XXXX with the numbers
assigned to this document and delete this note. Please make this assigned to this document and delete this note. Please make this
change in multiple places in this document.] change in multiple places in this document.]
The second line is a empty line, containing only the end-of-line The second line is an empty line, containing only the end-of-line
character sequence. This line provides visual separation for character sequence. This line provides visual separation for
readability. readability.
7.1.2. Body 7.1.2. Body
The character encoding is the same as described in Section 2 of The character encoding is the same as described in Section 2 of
[RFC7994], except that, per [RFC7991], tab characters are prohibited. [RFC7994], except that, per [RFC7991], tab characters are prohibited.
Lines that have a backslash ('\') occurring as the last character in Lines that have a backslash ('\') occurring as the last character in
a line are considered "folded". a line are considered "folded".
skipping to change at page 9, line 31 skipping to change at page 9, line 31
Note that this algorithm naturally addresses the case where the Note that this algorithm naturally addresses the case where the
remainder of a folded line is still longer than the desired maximum, remainder of a folded line is still longer than the desired maximum,
and hence needs to be folded again, ad infinitum. and hence needs to be folded again, ad infinitum.
The process described in this section is illustrated by the The process described in this section is illustrated by the
"fold_it_1()" function in Appendix A. "fold_it_1()" function in Appendix A.
7.2.2. Unfolding 7.2.2. Unfolding
Scan the beginning of the text content for the header described in Scan the beginning of the text content for the header described in
Section 7.1.1. If the header is not present, starting on the first Section 7.1.1. If the header is not present, exit (this text content
line of the text content, exit (this text contents does not need to does not need to be unfolded).
be unfolded).
Remove the 2-line header from the text content. Remove the 2-line header from the text content.
For each line in the text content, from top-to-bottom, if the line For each line in the text content, from top-to-bottom, if the line
has a backslash ('\') character immediately followed by the end of has a backslash ('\') character immediately followed by the end of
line character sequence, then the line can be unfolded. Remove the line character sequence, then the line can be unfolded. Remove the
backslash ('\') character, the end of line character sequence, and backslash ('\') character, the end of line character sequence, and
any leading space (' ') characters, which will bring up the next any leading space (' ') characters, which will bring up the next
line. Then continue to scan each line in the text content starting line. Then continue to scan each line in the text content starting
with the current line (in case it was multiply folded). with the current line (in case it was multiply folded).
skipping to change at page 10, line 26 skipping to change at page 10, line 26
The first line is the following 47-character string that MAY be The first line is the following 47-character string that MAY be
surrounded by any number of printable characters. This first line surrounded by any number of printable characters. This first line
cannot itself be folded. cannot itself be folded.
NOTE: '\\' line wrapping per BCP XXX (RFC XXXX) NOTE: '\\' line wrapping per BCP XXX (RFC XXXX)
[Note to RFC Editor: Please replace XXX and XXXX with the numbers [Note to RFC Editor: Please replace XXX and XXXX with the numbers
assigned to this document and delete this note. Please make this assigned to this document and delete this note. Please make this
change in multiple places in this document.] change in multiple places in this document.]
The second line is a empty line, containing only the end-of-line The second line is an empty line, containing only the end-of-line
character sequence. This line provides visual separation for character sequence. This line provides visual separation for
readability. readability.
8.1.2. Body 8.1.2. Body
The character encoding is the same as described in Section 2 of The character encoding is the same as described in Section 2 of
[RFC7994], except that, per [RFC7991], tab characters are prohibited. [RFC7994], except that, per [RFC7991], tab characters are prohibited.
Lines that have a backslash ('\') occurring as the last character in Lines that have a backslash ('\') occurring as the last character in
a line immediately followed by the end of line character sequence, a line immediately followed by the end of line character sequence,
skipping to change at page 12, line 25 skipping to change at page 12, line 25
Note that this algorithm naturally addresses the case where the Note that this algorithm naturally addresses the case where the
remainder of a folded line is still longer than the desired maximum, remainder of a folded line is still longer than the desired maximum,
and hence needs to be folded again, ad infinitum. and hence needs to be folded again, ad infinitum.
The process described in this section is illustrated by the The process described in this section is illustrated by the
"fold_it_2()" function in Appendix A. "fold_it_2()" function in Appendix A.
8.2.2. Unfolding 8.2.2. Unfolding
Scan the beginning of the text content for the header described in Scan the beginning of the text content for the header described in
Section 8.1.1. If the header is not present, starting on the first Section 8.1.1. If the header is not present, exit (this text content
line of the text content, exit (this text content does not need to be does not need to be unfolded).
unfolded).
Remove the 2-line header from the text content. Remove the 2-line header from the text content.
For each line in the text content, from top-to-bottom, if the line For each line in the text content, from top-to-bottom, if the line
has a backslash ('\') character immediately followed by the end of has a backslash ('\') character immediately followed by the end of
line character sequence, and if the next line has a backslash ('\') line character sequence, and if the next line has a backslash ('\')
character as the first non-space (' ') character, then the lines can character as the first non-space (' ') character, then the lines can
be unfolded. Remove the first backslash ('\') character, the end of be unfolded. Remove the first backslash ('\') character, the end of
line character sequence, any leading space (' ') characters, and the line character sequence, any leading space (' ') characters, and the
second backslash ('\') character, which will bring up the next line. second backslash ('\') character, which will bring up the next line.
skipping to change at page 13, line 7 skipping to change at page 13, line 7
9. Examples 9. Examples
The following self-documenting examples illustrate folded text-based The following self-documenting examples illustrate folded text-based
content. content.
The source text content cannot be presented here, as it would again The source text content cannot be presented here, as it would again
be folded. Alas, only the results can be provided. be folded. Alas, only the results can be provided.
9.1. Example Showing Boundary Conditions 9.1. Example Showing Boundary Conditions
This example illustrates boundary condition. The input contains This example illustrates boundary conditions. The input contains
seven lines, each line one character longer than the previous line. seven lines, each line one character longer than the previous line.
Numbers for counting purposes. The default desired maximum column Numbers for counting purposes. The default desired maximum column
value "69" is used. value "69" is used.
9.1.1. Using '\' 9.1.1. Using '\'
========== NOTE: '\' line wrapping per BCP XXX (RFC XXXX) =========== ========== NOTE: '\' line wrapping per BCP XXX (RFC XXXX) ===========
123456789012345678901234567890123456789012345678901234567890123456 123456789012345678901234567890123456789012345678901234567890123456
1234567890123456789012345678901234567890123456789012345678901234567 1234567890123456789012345678901234567890123456789012345678901234567
skipping to change at page 13, line 44 skipping to change at page 13, line 44
123456789012345678901234567890123456789012345678901234567890123456789 123456789012345678901234567890123456789012345678901234567890123456789
12345678901234567890123456789012345678901234567890123456789012345678\ 12345678901234567890123456789012345678901234567890123456789012345678\
\90 \90
12345678901234567890123456789012345678901234567890123456789012345678\ 12345678901234567890123456789012345678901234567890123456789012345678\
\901 \901
12345678901234567890123456789012345678901234567890123456789012345678\ 12345678901234567890123456789012345678901234567890123456789012345678\
\9012 \9012
9.2. Example Showing Multiple Wraps of a Single Line 9.2. Example Showing Multiple Wraps of a Single Line
This example illustrates what happens when very long line needs to be This example illustrates what happens when a very long line needs to
folded multiple times. The input contains one line containing 280 be folded multiple times. The input contains one line containing 280
characters. Numbers for counting purposes. The default desired characters. Numbers for counting purposes. The default desired
maximum column value "69" is used. maximum column value "69" is used.
9.2.1. Using '\' 9.2.1. Using '\'
========== NOTE: '\' line wrapping per BCP XXX (RFC XXXX) =========== ========== NOTE: '\' line wrapping per BCP XXX (RFC XXXX) ===========
12345678901234567890123456789012345678901234567890123456789012345678\ 12345678901234567890123456789012345678901234567890123456789012345678\
90123456789012345678901234567890123456789012345678901234567890123456\ 90123456789012345678901234567890123456789012345678901234567890123456\
78901234567890123456789012345678901234567890123456789012345678901234\ 78901234567890123456789012345678901234567890123456789012345678901234\
skipping to change at page 18, line 40 skipping to change at page 18, line 40
12. References 12. References
12.1. Normative References 12.1. Normative References
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997, DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>. <https://www.rfc-editor.org/info/rfc2119>.
[RFC7991] Hoffman, P., "The "xml2rfc" Version 3 Vocabulary",
RFC 7991, DOI 10.17487/RFC7991, December 2016,
<https://www.rfc-editor.org/info/rfc7991>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>. May 2017, <https://www.rfc-editor.org/info/rfc8174>.
12.2. Informative References 12.2. Informative References
[bash] "GNU Bash Manual", [bash] "GNU Bash Manual",
<https://www.gnu.org/software/bash/manual>. <https://www.gnu.org/software/bash/manual>.
[pyang] "An extensible YANG (RFC 6020/7950) validator.", [pyang] "An extensible YANG (RFC 6020/7950) validator.",
<https://pypi.org/project/pyang/>. <https://pypi.org/project/pyang/>.
[RFC7749] Reschke, J., "The "xml2rfc" Version 2 Vocabulary", [RFC7749] Reschke, J., "The "xml2rfc" Version 2 Vocabulary",
RFC 7749, DOI 10.17487/RFC7749, February 2016, RFC 7749, DOI 10.17487/RFC7749, February 2016,
<https://www.rfc-editor.org/info/rfc7749>. <https://www.rfc-editor.org/info/rfc7749>.
[RFC7950] Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language", [RFC7950] Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language",
RFC 7950, DOI 10.17487/RFC7950, August 2016, RFC 7950, DOI 10.17487/RFC7950, August 2016,
<https://www.rfc-editor.org/info/rfc7950>. <https://www.rfc-editor.org/info/rfc7950>.
[RFC7991] Hoffman, P., "The "xml2rfc" Version 3 Vocabulary",
RFC 7991, DOI 10.17487/RFC7991, December 2016,
<https://www.rfc-editor.org/info/rfc7991>.
[RFC7994] Flanagan, H., "Requirements for Plain-Text RFCs", [RFC7994] Flanagan, H., "Requirements for Plain-Text RFCs",
RFC 7994, DOI 10.17487/RFC7994, December 2016, RFC 7994, DOI 10.17487/RFC7994, December 2016,
<https://www.rfc-editor.org/info/rfc7994>. <https://www.rfc-editor.org/info/rfc7994>.
[RFC8340] Bjorklund, M. and L. Berger, Ed., "YANG Tree Diagrams", [RFC8340] Bjorklund, M. and L. Berger, Ed., "YANG Tree Diagrams",
BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018,
<https://www.rfc-editor.org/info/rfc8340>. <https://www.rfc-editor.org/info/rfc8340>.
[xiax] "The `xiax` Python Package", [xiax] "The `xiax` Python Package",
<https://pypi.org/project/xiax/>. <https://pypi.org/project/xiax/>.
skipping to change at page 20, line 24 skipping to change at page 20, line 24
within a larger document (e.g., an Internet draft or RFC), then within a larger document (e.g., an Internet draft or RFC), then
another tool must be used to extract the content from the larger another tool must be used to extract the content from the larger
document before utilizing this script. document before utilizing this script.
For readability purposes, this script forces the minimally supported For readability purposes, this script forces the minimally supported
line length to be eight characters longer than the raw header text line length to be eight characters longer than the raw header text
defined in Section 7.1.1 and Section 8.1.1 so as to ensure that the defined in Section 7.1.1 and Section 8.1.1 so as to ensure that the
header can be wrapped by a space (' ') character and three equal header can be wrapped by a space (' ') character and three equal
('=') characters on each side of the raw header text. ('=') characters on each side of the raw header text.
When a TAB character is detected in the input file, this script exits
with the error message:
Error: infile contains a TAB character, which is not allowed.
This script tests for the availability of GNU awk (gawk), in order to
test for ASCII-based control characters and non-ASCII characters in
the input file (see below). Note that testing revealed flaws in the
default version of `awk` on some platforms. As the use of `gawk` is
only used to issue warning messages, if `gawk` of not found, this
script issues the debug message:
Debug: no GNU Awk, skipping checks for special characters.
When `gawk` is available (see above) and ASCII-based control
characters are detected in the input file, this script issues the
warning message:
Warning: infile contains ASCII control characters (unsupported).
When `gawk` is available (see above) and non-ASCII characters are
detected in the input file, this script issues the warning message:
Warning: infile contains non-ASCII characters (unsupported).
This script does not implement the whitespace-avoidance logic This script does not implement the whitespace-avoidance logic
described in Section 7.2.1. In such case, the script will exit with described in Section 7.2.1. In such case, the script will exit with
one of the following message: the following message:
Error: infile has a space character occurring on the Error: infile has a space character occurring on the
folding column. This file cannot be folded using the folding column. This file cannot be folded using the
'\' strategy. '\' strategy.
While this script can unfold input that contains forced foldings, it While this script can unfold input that contains forced foldings, it
is unable to fold files that would require forced foldings. Forced is unable to fold files that would require forced foldings. Forced
folding is described in Section 7.2.1 and Section 8.2.1. When being folding is described in Section 7.2.1 and Section 8.2.1. When being
asked to fold a file that would require forced folding, the script asked to fold a file that would require forced folding, the script
will instead exit with one of the following messages: will instead exit with the following message:
Error: infile has a line ending with a '\' character. For '\':
This file cannot be folded using the '\' strategy without
there being false positives produced in the unfolding
(i.e., this script does not force-fold such lines, as
described in BCP XXX, RFC XXXX).
Error: infile has a line ending with a '\' character Error: infile has a line ending with a '\' character.
followed by a '\' character as the first non-space This file cannot be folded using the '\' strategy without
character on the next line. This script cannot fold there being false positives produced in the unfolding
this file using '\\' strategy without there being (i.e., this script does not force-fold such lines, as
false positives produced in the unfolding (i.e., this described in BCP XXX, RFC XXXX).
script does not force-fold such lines, as described
in BCP XXX, RFC XXXX). For '\\':
Error: infile has a line ending with a '\' character
followed by a '\' character as the first non-space
character on the next line. This script cannot fold
this file using '\\' strategy without there being
false positives produced in the unfolding (i.e., this
script does not force-fold such lines, as described
in BCP XXX, RFC XXXX).
Shell-level end-of-line backslash ('\') characters have been Shell-level end-of-line backslash ('\') characters have been
purposely added to the script so as to ensure that the script is purposely added to the script so as to ensure that the script is
itself not folded in this document, thus simplifying the ability to itself not folded in this document, thus simplifying the ability to
copy/paste the script for local use. As should be evident by the copy/paste the script for local use. As should be evident by the
lack of the mandatory header described in Section 7.1.1, these lack of the mandatory header described in Section 7.1.1, these
backslashes do not designate a folded line, such as described in backslashes do not designate a folded line, such as described in
Section 7. Section 7.
<CODE BEGINS> <CODE BEGINS>
========== NOTE: '\\' line wrapping per BCP XXX (RFC XXXX) ==========
#!/bin/bash --posix #!/bin/bash --posix
# This script may need some adjustments to work on a given system. # This script may need some adjustments to work on a given system.
# For instance, the utilities `pcregrep` and `gsed` may need to # For instance, the utility `gsed` may need to be installed.
# be installed. Also, please be advised that `bash` (not `sh`) # Also, please be advised that `bash` (not `sh`) must be used.
# must be used.
# Copyright (c) 2019 IETF Trust, Kent Watsen, and Erik Auerswald. # Copyright (c) 2019 IETF Trust, Kent Watsen, and Erik Auerswald.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions # modification, are permitted provided that the following conditions
# are met: # are met:
# #
# * Redistributions of source code must retain the above copyright # * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer. # notice, this list of conditions and the following disclaimer.
skipping to change at page 22, line 22 skipping to change at page 22, line 47
printf "\n" printf "\n"
printf "Usage: rfcfold [-h] [-d] [-q] [-s <strategy>] [-c <col>]" printf "Usage: rfcfold [-h] [-d] [-q] [-s <strategy>] [-c <col>]"
printf " [-r] -i <infile> -o <outfile>\n" printf " [-r] -i <infile> -o <outfile>\n"
printf "\n" printf "\n"
printf " -s: strategy to use, '1' or '2' (default: try 1," printf " -s: strategy to use, '1' or '2' (default: try 1,"
printf " else 2)\n" printf " else 2)\n"
printf " -c: column to fold on (default: 69)\n" printf " -c: column to fold on (default: 69)\n"
printf " -r: reverses the operation\n" printf " -r: reverses the operation\n"
printf " -i: the input filename\n" printf " -i: the input filename\n"
printf " -o: the output filename\n" printf " -o: the output filename\n"
printf " -d: show debug messages\n" printf " -d: show debug messages (unless -q is given)\n"
printf " -q: quiet (suppress error messages)\n" printf " -q: quiet (suppress error and debug messages)\n"
printf " -h: show this message\n" printf " -h: show this message\n"
printf "\n" printf "\n"
printf "Exit status code: 1 on error, 0 on success, -1 on no-op.\n" printf "Exit status code: 1 on error, 0 on success, 255 on no-op."
printf "\n" printf "\n\n"
} }
# global vars, do not edit # global vars, do not edit
strategy=0 # auto strategy=0 # auto
debug=0 debug=0
quiet=0 quiet=0
reversed=0 reversed=0
infile="" infile=""
outfile="" outfile=""
maxcol=69 # default, may be overridden by param maxcol=69 # default, may be overridden by param
col_gvn=0 # maxcol overridden?
hdr_txt_1="NOTE: '\\' line wrapping per BCP XXX (RFC XXXX)" hdr_txt_1="NOTE: '\\' line wrapping per BCP XXX (RFC XXXX)"
hdr_txt_2="NOTE: '\\\\' line wrapping per BCP XXX (RFC XXXX)" hdr_txt_2="NOTE: '\\\\' line wrapping per BCP XXX (RFC XXXX)"
equal_chars="=======================================================" equal_chars="======================================================="
space_chars=" " space_chars=" "
temp_dir="" temp_dir=""
prog_name='rfcfold'
# functions for diagnostic messages
prog_msg() {
if [[ "$quiet" -eq 0 ]]; then
format_string="${prog_name}: $1: %s\n"
shift
printf -- "$format_string" "$@" >&2
fi
}
err() {
prog_msg 'Error' "$@"
}
warn() {
prog_msg 'Warning' "$@"
}
dbg() {
if [[ "$debug" -eq 1 ]]; then
prog_msg 'Debug' "$@"
fi
}
# determine name of [g]sed binary # determine name of [g]sed binary
type gsed > /dev/null 2>&1 && SED=gsed || SED=sed type gsed > /dev/null 2>&1 && SED=gsed || SED=sed
# warn if a non-GNU sed utility is used # warn if a non-GNU sed utility is used
"$SED" --version < /dev/null 2> /dev/null \ "$SED" --version < /dev/null 2> /dev/null \
| grep GNU >/dev/null 2>&1 || \ | grep GNU > /dev/null 2>&1 || \
echo 'Warning: not using GNU `sed` (likely cause if an error occurs)' warn 'not using GNU `sed` (likely cause if an error occurs)'
# verify the availability of pcregrep
type pcregrep >> /dev/null 2>&1 || {
printf '\nError: missing utility `pcregrep`\n'
exit 1
}
cleanup() { cleanup() {
rm -rf "$temp_dir" rm -rf "$temp_dir"
} }
trap 'cleanup' EXIT trap 'cleanup' EXIT
fold_it_1() { fold_it_1() {
# ensure input file doesn't contain the fold-sequence already # ensure input file doesn't contain the fold-sequence already
pcregrep -q -M "\\\\\n" "$infile" if [[ -n "$("$SED" -n '/\\$/p' "$infile")" ]]; then
if [[ $? -eq 0 ]]; then err "infile has a line ending with a '\\' character."\
if [[ $quiet -eq 0 ]]; then "This file cannot be folded using the '\\' strategy"\
echo "without there being false positives produced in the"\
echo "Error: infile has a line ending with a '\\' character." "unfolding (i.e., this script does not force-fold"\
echo "This file cannot be folded using the '\\' strategy" "such lines, as described in BCP XXX, RFC XXXX)."
echo "without there being false positives produced in the"
echo "unfolding (i.e., this script does not force-fold"
echo "such lines, as described in BCP XXX, RFC XXXX)."
echo
fi
return 1 return 1
fi fi
# where to fold # where to fold
foldcol=`expr "$maxcol" - 1` # for the inserted '\' char foldcol=$(expr "$maxcol" - 1) # for the inserted '\' char
# ensure input file doesn't contain whitespace on the fold column # ensure input file doesn't contain whitespace on the fold column
grep -q "^.\{$foldcol\} " "$infile" grep -q "^\(.\{$foldcol\}\)\{1,\} " "$infile"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
if [[ $quiet -eq 0 ]]; then err "infile has a space character occurring on the"\
echo "folding column. This file cannot be folded using the"\
echo "Error: infile has a space character occurring on the" "'\\' strategy."
echo "folding column. This file cannot be folded using the"
echo "'\\' strategy."
echo
fi
return 1 return 1
fi fi
# center header text # center header text
length=`expr ${#hdr_txt_1} + 2` length=$(expr ${#hdr_txt_1} + 2)
left_sp=`expr \( "$maxcol" - "$length" \) / 2` left_sp=$(expr \( "$maxcol" - "$length" \) / 2)
right_sp=`expr "$maxcol" - "$length" - "$left_sp"` right_sp=$(expr "$maxcol" - "$length" - "$left_sp")
header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ header=$(printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\
"$hdr_txt_1" "$right_sp" "$equal_chars"` "$hdr_txt_1" "$right_sp" "$equal_chars")
# generate outfile # generate outfile
echo "$header" > "$outfile" echo "$header" > "$outfile"
echo "" >> "$outfile" echo "" >> "$outfile"
"$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\2/;t M;b;:M;P;D;'\ "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\2/;t M;b;:M;P;D;'\
< "$infile" >> "$outfile" 2>/dev/null < "$infile" >> "$outfile" 2> /dev/null
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
return 1 return 1
fi fi
return 0 return 0
} }
fold_it_2() { fold_it_2() {
# where to fold # where to fold
foldcol=`expr "$maxcol" - 1` # for the inserted '\' char foldcol=$(expr "$maxcol" - 1) # for the inserted '\' char
# ensure input file doesn't contain the fold-sequence already # ensure input file doesn't contain the fold-sequence already
pcregrep -q -M "\\\\\n[\ ]*\\\\" "$infile" if [[ -n "$("$SED" -n '/\\$/{N;s/\\\n[ ]*\\/&/p}' "$infile")" ]]
if [[ $? -eq 0 ]]; then then
if [[ $quiet -eq 0 ]]; then err "infile has a line ending with a '\\' character"\
echo "followed by a '\\' character as the first non-space"\
echo "Error: infile has a line ending with a '\\' character" "character on the next line. This script cannot fold"\
echo "followed by a '\\' character as the first non-space" "this file using '\\\\' strategy without there being"\
echo "character on the next line. This script cannot fold" "false positives produced in the unfolding (i.e., this"\
echo "this file using '\\\\' strategy without there being" "script does not force-fold such lines, as described"\
echo "false positives produced in the unfolding (i.e., this" "in BCP XXX, RFC XXXX)."
echo "script does not force-fold such lines, as described"
echo "in BCP XXX, RFC XXXX)."
echo
fi
return 1 return 1
fi fi
# center header text # center header text
length=`expr ${#hdr_txt_2} + 2` length=$(expr ${#hdr_txt_2} + 2)
left_sp=`expr \( "$maxcol" - "$length" \) / 2` left_sp=$(expr \( "$maxcol" - "$length" \) / 2)
right_sp=`expr "$maxcol" - "$length" - "$left_sp"` right_sp=$(expr "$maxcol" - "$length" - "$left_sp")
header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ header=$(printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\
"$hdr_txt_2" "$right_sp" "$equal_chars"` "$hdr_txt_2" "$right_sp" "$equal_chars")
# generate outfile # generate outfile
echo "$header" > "$outfile" echo "$header" > "$outfile"
echo "" >> "$outfile" echo "" >> "$outfile"
"$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\\\2/;t M;b;:M;P;D;'\ "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\\\2/;t M;b;:M;P;D;'\
< "$infile" >> "$outfile" 2>/dev/null < "$infile" >> "$outfile" 2> /dev/null
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
return 1 return 1
fi fi
return 0 return 0
} }
fold_it() { fold_it() {
# ensure input file doesn't contain a TAB # ensure input file doesn't contain a TAB
grep -q $'\t' "$infile" grep -q $'\t' "$infile"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
if [[ $quiet -eq 0 ]]; then err "infile contains a TAB character, which is not allowed."
echo
echo "Error: infile contains a TAB character, which is"
echo "not allowed."
echo
fi
return 1 return 1
fi fi
# folding of input containing ASCII control or non-ASCII characters
# may result in a wrong folding column and is not supported
if type gawk > /dev/null 2>&1; then
env LC_ALL=C gawk '/[\000-\014\016-\037\177]/{exit 1}' "$infile"\
|| warn 'infile contains ASCII control characters (unsupported).'
env LC_ALL=C gawk '/[^\000-\177]/{exit 1}' "$infile"\
|| warn 'infile contains non-ASCII characters (unsupported).'
else
dbg 'no GNU Awk, skipping checks for special characters.'
fi
# check if file needs folding # check if file needs folding
testcol=`expr "$maxcol" + 1` testcol=$(expr "$maxcol" + 1)
grep -q ".\{$testcol\}" "$infile" grep -q ".\{$testcol\}" "$infile"
if [ $? -ne 0 ]; then if [[ $? -ne 0 ]]; then
if [[ $debug -eq 1 ]]; then dbg "nothing to do"
echo "nothing to do"
fi
cp "$infile" "$outfile" cp "$infile" "$outfile"
return -1 return 255
fi fi
if [[ $strategy -eq 1 ]]; then if [[ "$strategy" -eq 1 ]]; then
fold_it_1 fold_it_1
return $? return $?
fi fi
if [[ $strategy -eq 2 ]]; then if [[ "$strategy" -eq 2 ]]; then
fold_it_2 fold_it_2
return $? return $?
fi fi
quiet_sav=$quiet quiet_sav="$quiet"
quiet=1 quiet=1
fold_it_1 fold_it_1
result=$? result=$?
quiet=$quiet_sav quiet="$quiet_sav"
if [[ $result -ne 0 ]]; then if [[ "$result" -ne 0 ]]; then
if [[ $debug -eq 1 ]]; then dbg "Folding strategy 1 didn't succeed, trying strategy 2..."
echo "Folding strategy 1 didn't succeed, trying strategy 2..."
fi
fold_it_2 fold_it_2
return $? return $?
fi fi
return 0 return 0
} }
unfold_it_1() { unfold_it_1() {
temp_dir=`mktemp -d` temp_dir=$(mktemp -d)
# output all but the first two lines (the header) to wip file # output all but the first two lines (the header) to wip file
awk "NR>2" "$infile" > "$temp_dir/wip" awk "NR>2" "$infile" > "$temp_dir/wip"
# unfold wip file # unfold wip file
"$SED" '{H;$!d};x;s/^\n//;s/\\\n *//g' "$temp_dir/wip" > "$outfile" "$SED" '{H;$!d};x;s/^\n//;s/\\\n *//g' "$temp_dir/wip" > "$outfile"
return 0 return 0
} }
unfold_it_2() { unfold_it_2() {
temp_dir=`mktemp -d` temp_dir=$(mktemp -d)
# output all but the first two lines (the header) to wip file # output all but the first two lines (the header) to wip file
awk "NR>2" "$infile" > "$temp_dir/wip" awk "NR>2" "$infile" > "$temp_dir/wip"
# unfold wip file # unfold wip file
"$SED" '{H;$!d};x;s/^\n//;s/\\\n *\\//g' "$temp_dir/wip" > "$outfi\ "$SED" '{H;$!d};x;s/^\n//;s/\\\n *\\//g' "$temp_dir/wip"\
\le" > "$outfile"
return 0 return 0
} }
unfold_it() { unfold_it() {
# check if file needs unfolding # check if file needs unfolding
line=`head -n 1 "$infile"` line=$(head -n 1 "$infile")
line2=`$SED -n '2p' "$infile"` line2=$("$SED" -n '2p' "$infile")
result=`echo "$line" | fgrep "$hdr_txt_1"` result=$(echo "$line" | fgrep "$hdr_txt_1")
if [ $? -eq 0 ]; then if [[ $? -eq 0 ]]; then
if [ -n "$line2" ]; then if [[ -n "$line2" ]]; then
if [[ $quiet -eq 0 ]]; then err "the second line is not empty."
echo "Error: the second line is not empty."
fi
return 1 return 1
fi fi
unfold_it_1 unfold_it_1
return $? return $?
fi fi
result=`echo $line | fgrep "$hdr_txt_2"` result=$(echo "$line" | fgrep "$hdr_txt_2")
if [ $? -eq 0 ]; then if [[ $? -eq 0 ]]; then
if [ -n "$line2" ]; then if [[ -n "$line2" ]]; then
if [[ $quiet -eq 0 ]]; then err "the second line is not empty."
echo "Error: the second line is not empty."
fi
return 1 return 1
fi fi
unfold_it_2 unfold_it_2
return $? return $?
fi fi
if [[ $debug -eq 1 ]]; then dbg "nothing to do"
echo "nothing to do"
fi
cp "$infile" "$outfile" cp "$infile" "$outfile"
return -1 return 255
} }
process_input() { process_input() {
while [ "$1" != "" ]; do while [[ "$1" != "" ]]; do
if [ "$1" == "-h" -o "$1" == "--help" ]; then if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
print_usage print_usage
exit 0 exit 0
fi elif [[ "$1" == "-d" ]]; then
if [ "$1" == "-d" ]; then
debug=1 debug=1
fi elif [[ "$1" == "-q" ]]; then
if [ "$1" == "-q" ]; then
quiet=1 quiet=1
fi elif [[ "$1" == "-s" ]]; then
if [ "$1" == "-s" ]; then
strategy="$2" strategy="$2"
shift shift
fi elif [[ "$1" == "-c" ]]; then
if [ "$1" == "-c" ]; then col_gvn=1
maxcol="$2" maxcol="$2"
shift shift
fi elif [[ "$1" == "-r" ]]; then
if [ "$1" == "-r" ]; then
reversed=1 reversed=1
fi elif [[ "$1" == "-i" ]]; then
if [ "$1" == "-i" ]; then
infile="$2" infile="$2"
shift shift
fi elif [[ "$1" == "-o" ]]; then
if [ "$1" == "-o" ]; then
outfile="$2" outfile="$2"
shift shift
else
warn "ignoring unknown option '$1'"
fi fi
shift shift
done done
if [[ -z "$infile" ]]; then if [[ -z "$infile" ]]; then
if [[ $quiet -eq 0 ]]; then err "infile parameter missing (use -h for help)"
echo
echo "Error: infile parameter missing (use -h for help)"
echo
fi
exit 1 exit 1
fi fi
if [[ -z "$outfile" ]]; then if [[ -z "$outfile" ]]; then
if [[ $quiet -eq 0 ]]; then err "outfile parameter missing (use -h for help)"
echo exit 1
echo "Error: outfile parameter missing (use -h for help)"
echo
exit 1
fi
fi fi
if [[ ! -f "$infile" ]]; then if [[ ! -f "$infile" ]]; then
if [[ $quiet -eq 0 ]]; then err "specified file \"$infile\" is does not exist."
echo exit 1
echo "Error: specified file \"$infile\" is does not exist."
echo
exit 1
fi
fi fi
if [[ $strategy -eq 2 ]]; then if [[ "$col_gvn" -eq 1 ]] && [[ "$reversed" -eq 1 ]]; then
min_supported=`expr ${#hdr_txt_2} + 9` warn "'-c' option ignored when unfolding (option '-r')"
fi
if [[ "$strategy" -eq 0 ]] || [[ "$strategy" -eq 2 ]]; then
min_supported=$(expr ${#hdr_txt_2} + 8)
else else
min_supported=`expr ${#hdr_txt_1} + 9` min_supported=$(expr ${#hdr_txt_1} + 8)
fi fi
if [[ $maxcol -lt $min_supported ]]; then if [[ "$maxcol" -lt "$min_supported" ]]; then
if [[ $quiet -eq 0 ]]; then err "the folding column cannot be less than $min_supported."
printf "\nError: the folding column cannot be less than"
printf " $min_supported.\n\n"
fi
exit 1 exit 1
fi fi
# this is only because the code otherwise runs out of equal_chars # this is only because the code otherwise runs out of equal_chars
max_supported=`expr ${#equal_chars} + 1 + ${#hdr_txt_1} + 1\ max_supported=$(expr ${#equal_chars} + 1 + ${#hdr_txt_1} + 1\
+ ${#equal_chars}` + ${#equal_chars})
if [[ $maxcol -gt $max_supported ]]; then if [[ "$maxcol" -gt "$max_supported" ]]; then
if [[ $quiet -eq 0 ]]; then err "the folding column cannot be more than $max_supported."
printf "\nError: the folding column cannot be more than"
printf " $max_supported.\n\n"
fi
exit 1 exit 1
fi fi
} }
main() { main() {
if [ "$#" == "0" ]; then if [[ "$#" -eq "0" ]]; then
print_usage print_usage
exit 1 exit 1
fi fi
process_input "$@" process_input "$@"
if [[ $reversed -eq 0 ]]; then if [[ "$reversed" -eq 0 ]]; then
fold_it fold_it
code=$? code=$?
else else
unfold_it unfold_it
code=$? code=$?
fi fi
exit $code exit "$code"
} }
main "$@" main "$@"
<CODE ENDS> <CODE ENDS>
Acknowledgements Acknowledgements
The authors thank the RFC Editor for confirming that there was The authors thank the RFC Editor for confirming that there was
previously no set convention, at the time of this document's previously no set convention, at the time of this document's
publication, for handling long lines in source code inclusions, thus publication, for handling long lines in source code inclusions, thus
instigating this work. instigating this work.
The authors thank the following folks for their various contributions The authors thank the following folks for their various contributions
while producing this document (sorted by first name): Benoit Claise, while producing this document (sorted by first name): Benoit Claise,
Erik Auerswald, Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan Hansford, Lou
Hansford, Lou Berger, Martin Bjorklund, and Rob Wilton. Berger, Martin Bjorklund, and Rob Wilton.
Special acknowledgement to Erik Auerswald for his contributions to Special acknowledgement to Erik Auerswald for his contributions to
the `rfcfold` script, especially for greatly improving the `sed` one- the `rfcfold` script, especially for greatly improving the `sed` one-
liners used therein. liners used therein.
Authors' Addresses Authors' Addresses
Kent Watsen Kent Watsen
Watsen Networks Watsen Networks
EMail: kent+ietf@watsen.net EMail: kent+ietf@watsen.net
Erik Auerswald
Individual Contributor
EMail: auerswal@unix-ag.uni-kl.de
Adrian Farrel Adrian Farrel
Old Dog Consulting Old Dog Consulting
EMail: adrian@olddog.co.uk EMail: adrian@olddog.co.uk
Qin Wu Qin Wu
Huawei Technologies Huawei Technologies
EMail: bill.wu@huawei.com EMail: bill.wu@huawei.com
 End of changes. 82 change blocks. 
205 lines changed or deleted 217 lines changed or added

This html diff was produced by rfcdiff 1.47. The latest version is available from http://tools.ietf.org/tools/rfcdiff/