idnits 2.17.1 draft-ietf-netmod-artwork-folding-09.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- No issues found here. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (August 29, 2019) is 1674 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Best Current Practice ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Obsolete informational reference (is this intentional?): RFC 7749 (Obsoleted by RFC 7991) Summary: 0 errors (**), 0 flaws (~~), 1 warning (==), 3 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 NETMOD Working Group K. Watsen 3 Internet-Draft Watsen Networks 4 Intended status: Best Current Practice A. Farrel 5 Expires: March 1, 2020 Old Dog Consulting 6 Q. Wu 7 Huawei Technologies 8 August 29, 2019 10 Handling Long Lines in Inclusions in Internet-Drafts and RFCs 11 draft-ietf-netmod-artwork-folding-09 13 Abstract 15 This document defines two strategies for handling long lines in 16 width-bounded text content. One strategy is based on the historic 17 use of a single backslash ('\') character to indicate where line- 18 folding has occurred, with the continuation occurring with the first 19 non-space (' ') character on the next line. The second strategy 20 extends the first strategy by adding a second backslash character to 21 identify where the continuation begins and thereby able to handle 22 cases not supported by the first strategy. Both strategies use a 23 self-describing header enabling automated reconstitution of the 24 original content. 26 Status of This Memo 28 This Internet-Draft is submitted in full conformance with the 29 provisions of BCP 78 and BCP 79. 31 Internet-Drafts are working documents of the Internet Engineering 32 Task Force (IETF). Note that other groups may also distribute 33 working documents as Internet-Drafts. The list of current Internet- 34 Drafts is at https://datatracker.ietf.org/drafts/current/. 36 Internet-Drafts are draft documents valid for a maximum of six months 37 and may be updated, replaced, or obsoleted by other documents at any 38 time. It is inappropriate to use Internet-Drafts as reference 39 material or to cite them other than as "work in progress." 41 This Internet-Draft will expire on March 1, 2020. 43 Copyright Notice 45 Copyright (c) 2019 IETF Trust and the persons identified as the 46 document authors. All rights reserved. 48 This document is subject to BCP 78 and the IETF Trust's Legal 49 Provisions Relating to IETF Documents 50 (https://trustee.ietf.org/license-info) in effect on the date of 51 publication of this document. Please review these documents 52 carefully, as they describe your rights and restrictions with respect 53 to this document. Code Components extracted from this document must 54 include Simplified BSD License text as described in Section 4.e of 55 the Trust Legal Provisions and are provided without warranty as 56 described in the Simplified BSD License. 58 Table of Contents 60 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 61 2. Applicability Statement . . . . . . . . . . . . . . . . . . . 4 62 3. Requirements Language . . . . . . . . . . . . . . . . . . . . 4 63 4. Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 64 4.1. Automated Folding of Long Lines in Text Content . . . . . 4 65 4.2. Automated Reconstitution of the Original Text Content . . 5 66 5. Limitations . . . . . . . . . . . . . . . . . . . . . . . . . 5 67 5.1. Not Recommended for Graphical Artwork . . . . . . . . . . 5 68 5.2. Doesn't Work as Well as Format-Specific Options . . . . . 5 69 6. Two Folding Strategies . . . . . . . . . . . . . . . . . . . 6 70 6.1. Comparison . . . . . . . . . . . . . . . . . . . . . . . 6 71 6.2. Recommendation . . . . . . . . . . . . . . . . . . . . . 6 72 7. The Single Backslash Strategy ('\') . . . . . . . . . . . . . 6 73 7.1. Folded Structure . . . . . . . . . . . . . . . . . . . . 6 74 7.1.1. Header . . . . . . . . . . . . . . . . . . . . . . . 6 75 7.1.2. Body . . . . . . . . . . . . . . . . . . . . . . . . 7 76 7.2. Algorithm . . . . . . . . . . . . . . . . . . . . . . . . 7 77 7.2.1. Folding . . . . . . . . . . . . . . . . . . . . . . . 7 78 7.2.2. Unfolding . . . . . . . . . . . . . . . . . . . . . . 9 79 8. The Double Backslash Strategy ('\\') . . . . . . . . . . . . 9 80 8.1. Folded Structure . . . . . . . . . . . . . . . . . . . . 9 81 8.1.1. Header . . . . . . . . . . . . . . . . . . . . . . . 9 82 8.1.2. Body . . . . . . . . . . . . . . . . . . . . . . . . 10 83 8.2. Algorithm . . . . . . . . . . . . . . . . . . . . . . . . 10 84 8.2.1. Folding . . . . . . . . . . . . . . . . . . . . . . . 10 85 8.2.2. Unfolding . . . . . . . . . . . . . . . . . . . . . . 12 86 9. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 12 87 9.1. Example Showing Boundary Conditions . . . . . . . . . . . 12 88 9.1.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 12 89 9.1.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 13 90 9.2. Example Showing Multiple Wraps of a Single Line . . . . . 13 91 9.2.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 13 92 9.2.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 14 93 9.3. Example Showing "Smart" Folding . . . . . . . . . . . . . 14 94 9.3.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 14 95 9.3.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 15 97 9.4. Example Showing "Forced" Folding . . . . . . . . . . . . 16 98 9.4.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 17 99 9.4.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 17 100 10. Security Considerations . . . . . . . . . . . . . . . . . . . 17 101 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 18 102 12. References . . . . . . . . . . . . . . . . . . . . . . . . . 18 103 12.1. Normative References . . . . . . . . . . . . . . . . . . 18 104 12.2. Informative References . . . . . . . . . . . . . . . . . 18 105 Appendix A. POSIX Shell Script: rfcfold . . . . . . . . . . . . 20 106 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 29 107 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 29 109 1. Introduction 111 [RFC7994] sets out the requirements for plain-text RFCs and states 112 that each line of an RFC (and hence of an Internet-Draft) must be 113 limited to 72 characters followed by the character sequence that 114 denotes an end-of-line (EOL). 116 Internet-Drafts and RFCs often include example text or code 117 fragments. Many times the example text or code exceeds the 72 118 character line-length limit. The `xml2rfc` utility does not attempt 119 to wrap the content of such inclusions, simply issuing a warning 120 whenever lines exceed 69 characters. According to the RFC Editor, 121 there is currently no convention in place for how to handle long 122 lines in such inclusions, other than advising authors to clearly 123 indicate what manipulation has occurred. 125 This document defines two strategies for handling long lines in 126 width-bounded text content. One strategy is based on the historic 127 use of a single backslash ('\') character to indicate where line- 128 folding has occurred, with the continuation occurring with the first 129 non-space (' ') character on the next line. The second strategy 130 extends the first strategy by adding a second backslash character to 131 identify where the continuation begins and thereby able to handle 132 cases not supported by the first strategy. Both strategies use a 133 self-describing header enabling automated reconstitution of the 134 original content. 136 The strategies defined in this document work on any text content, but 137 are primarily intended for a structured sequence of lines, such as 138 would be referenced by the element defined in 139 Section 2.48 of [RFC7991], rather than for two-dimensional imagery, 140 such as would be referenced by the element defined in 141 Section 2.5 of [RFC7991]. 143 Note that text files are represented as lines having their first 144 character in column 1, and a line length of N where the last 145 character is in the Nth column and is immediately followed by an end 146 of line character sequence. 148 2. Applicability Statement 150 The formats and algorithms defined in this document may be used in 151 any context, whether for IETF documents or in other situations where 152 structured folding is desired. 154 Within the IETF, this work primarily targets the xml2rfc v3 155 element (Section 2.48 of [RFC7991]) and the xml2rfc v2 156 element (Section 2.5 of [RFC7749]) that, for lack of a 157 better option, is currently used for both source code and artwork. 158 This work may be also be used for the xml2rfc v3 element 159 (Section 2.5 of [RFC7991]) but, as described in Section 5.1, it is 160 generally not recommended. 162 3. Requirements Language 164 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 165 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 166 "OPTIONAL" in this document are to be interpreted as described in BCP 167 14 [RFC2119] [RFC8174] when, and only when, they appear in all 168 capitals, as shown here. 170 4. Goals 172 4.1. Automated Folding of Long Lines in Text Content 174 Automated folding of long lines is needed in order to support draft 175 compilations that entail a) validation of source input files (e.g., 176 XML, JSON, ABNF, ASN.1) and/or b) dynamic generation of output, using 177 a tool that doesn't observe line lengths, that is stitched into the 178 final document to be submitted. 180 Generally, in order for tooling to be able to process input files, 181 the files must be in their original/natural state, which may entail 182 them having some long lines. Thus, these source files need to be 183 modified before inclusion in the document in order to satisfy the 184 line length limits. This modification SHOULD be automated to reduce 185 effort and errors resulting from manual processing. 187 Similarly, dynamically generated output (e.g., tree diagrams) must 188 also be modified, if necessary, in order for the resulting document 189 to satisfy the line length limits. This work should also be 190 automated to reduce effort and errors resulting from manual 191 processing. 193 4.2. Automated Reconstitution of the Original Text Content 195 Automated reconstitution of the exact original text content is needed 196 to support validation of text-based content extracted from documents. 198 For instance, already YANG [RFC7950] modules are extracted from 199 Internet-Drafts and validated as part of the draft-submission 200 process. Additionally, the desire to validate instance examples 201 (i.e., XML/JSON documents) contained within Internet-Drafts has been 202 discussed ([yang-doctors-thread]). 204 5. Limitations 206 5.1. Not Recommended for Graphical Artwork 208 While the solution presented in this document works on any kind of 209 text-based content, it is most useful on content that represents 210 source code (XML, JSON, etc.) or, more generally, on content that has 211 not been laid out in two dimensions (e.g., diagrams). 213 Fundamentally, the issue is whether the text content remains readable 214 once folded. Text content that is unpredictable is especially 215 susceptible to looking bad when folded; falling into this category 216 are most UML diagrams, YANG tree diagrams, and ASCII art in general. 218 It is NOT RECOMMENDED to use the solution presented in this document 219 on graphical artwork. 221 5.2. Doesn't Work as Well as Format-Specific Options 223 The solution presented in this document works generically for all 224 text-based content, as it only views content as plain text. However, 225 various formats sometimes have built-in mechanisms that are better 226 suited to prevent long lines. 228 For instance, both the `pyang` [pyang] and `yanglint` [yanglint] 229 utilities have the command line option "--tree-line-length" that can 230 be used to indicate a desired maximum line length for when generating 231 tree diagrams [RFC8340]. 233 In another example, some source formats (e.g., YANG [RFC7950]) allow 234 any quoted string to be broken up into substrings separated by a 235 concatenation character (e.g., '+'), any of which can be on a 236 different line. 238 It is RECOMMENDED that authors do as much as possible within the 239 selected format to avoid long lines. 241 6. Two Folding Strategies 243 This document defines two nearly identical strategies for folding 244 text-based content. 246 The Single Backslash Strategy ('\'): Uses a backslash ('\') 247 character at the end of the line where folding occurs, and 248 assumes that the continuation begins at the first character 249 that is not a space character (' ') on the following line. 251 The Double Backslash Strategy ('\\'): Uses a backslash ('\') 252 character at the end of the line where folding occurs, and 253 assumes that the continuation begins after a second backslash 254 ('\') character on the following line. 256 6.1. Comparison 258 The first strategy produces more readable output, however it is 259 significantly more likely to encounter unfoldable input (e.g., a long 260 line containing only space characters) and, for long lines that can 261 be folded, automation implementations may encounter scenarios that 262 will produce errors without special care. 264 The second strategy produces less readable output, but is unlikely to 265 encounter unfoldable input, there are no long lines that cannot be 266 folded, and no special care is required for when folding a long line. 268 6.2. Recommendation 270 It is RECOMMENDED for implementations to first attempt to fold 271 content using the single backslash strategy and, only in the unlikely 272 event that it cannot fold the input or the folding logic is unable to 273 cope with a contingency occurring on the desired folding column, then 274 fallback to the double backslash strategy. 276 7. The Single Backslash Strategy ('\') 278 7.1. Folded Structure 280 Text content that has been folded as specified by this strategy MUST 281 adhere to the following structure. 283 7.1.1. Header 285 The header is two lines long. 287 The first line is the following 46-character string that MAY be 288 surrounded by any number of printable characters. This first line 289 cannot itself be folded. 291 NOTE: '\' line wrapping per BCP XXX (RFC XXXX) 293 [Note to RFC Editor: Please replace XXX and XXXX with the numbers 294 assigned to this document and delete this note. Please make this 295 change in multiple places in this document.] 297 The second line is a empty line, containing only the end-of-line 298 character sequence. This line provides visual separation for 299 readability. 301 7.1.2. Body 303 The character encoding is the same as described in Section 2 of 304 [RFC7994], except that, per [RFC7991], tab characters are prohibited. 306 Lines that have a backslash ('\') occurring as the last character in 307 a line are considered "folded". 309 Really long lines may be folded multiple times. 311 7.2. Algorithm 313 This section describes a process for folding and unfolding long lines 314 when they are encountered in text content. 316 The steps are complete, but implementations MAY achieve the same 317 result in other ways. 319 When a larger document contains multiple instances of text content 320 that may need to be folded or unfolded, another process must insert/ 321 extract the individual text content instances to/from the larger 322 document prior to utilizing the algorithms described in this section. 323 For example, the `xiax` utility [xiax] does this. 325 7.2.1. Folding 327 Determine the desired maximum line length from input to the line- 328 wrapping process, such as from a command line parameter. If no value 329 is explicitly specified, the value "69" SHOULD be used. 331 Ensure that the desired maximum line length is not less than the 332 minimum header, which is 46 characters. If the desired maximum line 333 length is less than this minimum, exit (this text-based content 334 cannot be folded). 336 Scan the text content for horizontal tab characters. If any 337 horizontal tab characters appear, either resolve them to space 338 characters or exit, forcing the input provider to convert them to 339 space characters themselves first. 341 Scan the text content to ensure at least one line exceeds the desired 342 maximum. If no line exceeds the desired maximum, exit (this text 343 content does not need to be folded). 345 Scan the text content to ensure no existing lines already end with a 346 backslash ('\') character, as this could lead to an ambiguous result. 347 If such a line is found, and its width is less than the desired 348 maximum, then it SHOULD be flagged for forced folding (folding even 349 though unnecessary). If the folding implementation doesn't support 350 forced foldings, it MUST exit. 352 If this text content needs to and can be folded, insert the header 353 described in Section 7.1.1, ensuring that any additional printable 354 characters surrounding the header do not result in a line exceeding 355 the desired maximum. 357 For each line in the text content, from top-to-bottom, if the line 358 exceeds the desired maximum, or requires a forced folding, then fold 359 the line by: 361 1. Determine where the fold will occur. This location MUST be 362 before or at the desired maximum column, and MUST NOT be chosen 363 such that the character immediately after the fold is a space (' 364 ') character. For forced foldings, the location is between the 365 '\' and the end of line sequence. If no such location can be 366 found, then exit (this text content cannot be folded). 368 2. At the location where the fold is to occur, insert a backslash 369 ('\') character followed by the end of line character sequence. 371 3. On the following line, insert any number of space (' ') 372 characters. 374 The result of the previous operation is that the next line starts 375 with an arbitrary number of space (' ') characters, followed by the 376 character that was previously occupying the position where the fold 377 occurred. 379 Continue in this manner until reaching the end of the text content. 380 Note that this algorithm naturally addresses the case where the 381 remainder of a folded line is still longer than the desired maximum, 382 and hence needs to be folded again, ad infinitum. 384 The process described in this section is illustrated by the 385 "fold_it_1()" function in Appendix A. 387 7.2.2. Unfolding 389 Scan the beginning of the text content for the header described in 390 Section 7.1.1. If the header is not present, starting on the first 391 line of the text content, exit (this text contents does not need to 392 be unfolded). 394 Remove the 2-line header from the text content. 396 For each line in the text content, from top-to-bottom, if the line 397 has a backslash ('\') character immediately followed by the end of 398 line character sequence, then the line can be unfolded. Remove the 399 backslash ('\') character, the end of line character sequence, and 400 any leading space (' ') characters, which will bring up the next 401 line. Then continue to scan each line in the text content starting 402 with the current line (in case it was multiply folded). 404 Continue in this manner until reaching the end of the text content. 406 The process described in this section is illustrated by the 407 "unfold_it_1()" function in Appendix A. 409 8. The Double Backslash Strategy ('\\') 411 8.1. Folded Structure 413 Text content that has been folded as specified by this strategy MUST 414 adhere to the following structure. 416 8.1.1. Header 418 The header is two lines long. 420 The first line is the following 47-character string that MAY be 421 surrounded by any number of printable characters. This first line 422 cannot itself be folded. 424 NOTE: '\\' line wrapping per BCP XXX (RFC XXXX) 426 [Note to RFC Editor: Please replace XXX and XXXX with the numbers 427 assigned to this document and delete this note. Please make this 428 change in multiple places in this document.] 429 The second line is a empty line, containing only the end-of-line 430 character sequence. This line provides visual separation for 431 readability. 433 8.1.2. Body 435 The character encoding is the same as described in Section 2 of 436 [RFC7994], except that, per [RFC7991], tab characters are prohibited. 438 Lines that have a backslash ('\') occurring as the last character in 439 a line immediately followed by the end of line character sequence, 440 when the subsequent line starts with a backslash ('\') as the first 441 non-space (' ') character, are considered "folded". 443 Really long lines may be folded multiple times. 445 8.2. Algorithm 447 This section describes a process for folding and unfolding long lines 448 when they are encountered in text content. 450 The steps are complete, but implementations MAY achieve the same 451 result in other ways. 453 When a larger document contains multiple instances of text content 454 that may need to be folded or unfolded, another process must insert/ 455 extract the individual text content instances to/from the larger 456 document prior to utilizing the algorithms described in this section. 457 For example, the `xiax` utility [xiax] does this. 459 8.2.1. Folding 461 Determine the desired maximum line length from input to the line- 462 wrapping process, such as from a command line parameter. If no value 463 is explicitly specified, the value "69" SHOULD be used. 465 Ensure that the desired maximum line length is not less than the 466 minimum header, which is 47 characters. If the desired maximum line 467 length is less than this minimum, exit (this text-based content 468 cannot be folded). 470 Scan the text content for horizontal tab characters. If any 471 horizontal tab characters appear, either resolve them to space 472 characters or exit, forcing the input provider to convert them to 473 space characters themselves first. 475 Scan the text content to see if any line exceeds the desired maximum. 476 If no line exceeds the desired maximum, exit (this text content does 477 not need to be folded). 479 Scan the text content to ensure no existing lines already end with a 480 backslash ('\') character while the subsequent line starts with a 481 backslash ('\') character as the first non-space (' ') character, as 482 this could lead to an ambiguous result. If such a line is found, and 483 its width is less than the desired maximum, then it SHOULD be flagged 484 for forced folding (folding even though unnecessary). If the folding 485 implementation doesn't support forced foldings, it MUST exit. 487 If this text content needs to and can be folded, insert the header 488 described in Section 8.1.1, ensuring that any additional printable 489 characters surrounding the header do not result in a line exceeding 490 the desired maximum. 492 For each line in the text content, from top-to-bottom, if the line 493 exceeds the desired maximum, or requires a forced folding, then fold 494 the line by: 496 1. Determine where the fold will occur. This location MUST be 497 before or at the desired maximum column. For forced foldings, 498 the location is between the '\' and the end of line sequence on 499 the first line. 501 2. At the location where the fold is to occur, insert a first 502 backslash ('\') character followed by the end of line character 503 sequence. 505 3. On the following line, insert any number of space (' ') 506 characters followed by a second backslash ('\') character. 508 The result of the previous operation is that the next line starts 509 with an arbitrary number of space (' ') characters, followed by a 510 backslash ('\') character, immediately followed by the character that 511 was previously occupying the position where the fold occurred. 513 Continue in this manner until reaching the end of the text content. 514 Note that this algorithm naturally addresses the case where the 515 remainder of a folded line is still longer than the desired maximum, 516 and hence needs to be folded again, ad infinitum. 518 The process described in this section is illustrated by the 519 "fold_it_2()" function in Appendix A. 521 8.2.2. Unfolding 523 Scan the beginning of the text content for the header described in 524 Section 8.1.1. If the header is not present, starting on the first 525 line of the text content, exit (this text content does not need to be 526 unfolded). 528 Remove the 2-line header from the text content. 530 For each line in the text content, from top-to-bottom, if the line 531 has a backslash ('\') character immediately followed by the end of 532 line character sequence, and if the next line has a backslash ('\') 533 character as the first non-space (' ') character, then the lines can 534 be unfolded. Remove the first backslash ('\') character, the end of 535 line character sequence, any leading space (' ') characters, and the 536 second backslash ('\') character, which will bring up the next line. 537 Then continue to scan each line in the text content starting with the 538 current line (in case it was multiply folded). 540 Continue in this manner until reaching the end of the text content. 542 The process described in this section is illustrated by the 543 "unfold_it_2()" function in Appendix A. 545 9. Examples 547 The following self-documenting examples illustrate folded text-based 548 content. 550 The source text content cannot be presented here, as it would again 551 be folded. Alas, only the results can be provided. 553 9.1. Example Showing Boundary Conditions 555 This example illustrates boundary condition. The input contains 556 seven lines, each line one character longer than the previous line. 557 Numbers for counting purposes. The default desired maximum column 558 value "69" is used. 560 9.1.1. Using '\' 561 ========== NOTE: '\' line wrapping per BCP XXX (RFC XXXX) =========== 563 123456789012345678901234567890123456789012345678901234567890123456 564 1234567890123456789012345678901234567890123456789012345678901234567 565 12345678901234567890123456789012345678901234567890123456789012345678 566 123456789012345678901234567890123456789012345678901234567890123456789 567 12345678901234567890123456789012345678901234567890123456789012345678\ 568 90 569 12345678901234567890123456789012345678901234567890123456789012345678\ 570 901 571 12345678901234567890123456789012345678901234567890123456789012345678\ 572 9012 574 9.1.2. Using '\\' 576 ========== NOTE: '\\' line wrapping per BCP XXX (RFC XXXX) ========== 578 123456789012345678901234567890123456789012345678901234567890123456 579 1234567890123456789012345678901234567890123456789012345678901234567 580 12345678901234567890123456789012345678901234567890123456789012345678 581 123456789012345678901234567890123456789012345678901234567890123456789 582 12345678901234567890123456789012345678901234567890123456789012345678\ 583 \90 584 12345678901234567890123456789012345678901234567890123456789012345678\ 585 \901 586 12345678901234567890123456789012345678901234567890123456789012345678\ 587 \9012 589 9.2. Example Showing Multiple Wraps of a Single Line 591 This example illustrates what happens when very long line needs to be 592 folded multiple times. The input contains one line containing 280 593 characters. Numbers for counting purposes. The default desired 594 maximum column value "69" is used. 596 9.2.1. Using '\' 598 ========== NOTE: '\' line wrapping per BCP XXX (RFC XXXX) =========== 600 12345678901234567890123456789012345678901234567890123456789012345678\ 601 90123456789012345678901234567890123456789012345678901234567890123456\ 602 78901234567890123456789012345678901234567890123456789012345678901234\ 603 56789012345678901234567890123456789012345678901234567890123456789012\ 604 34567890 606 9.2.2. Using '\\' 608 ========== NOTE: '\\' line wrapping per BCP XXX (RFC XXXX) ========== 610 12345678901234567890123456789012345678901234567890123456789012345678\ 611 \9012345678901234567890123456789012345678901234567890123456789012345\ 612 \6789012345678901234567890123456789012345678901234567890123456789012\ 613 \3456789012345678901234567890123456789012345678901234567890123456789\ 614 \01234567890 616 9.3. Example Showing "Smart" Folding 618 This example illustrates how readability can be improved via "smart" 619 folding, whereby folding occurs at format-specific locations and 620 format-specific indentations are used. 622 The text content was manually folded, since the script in the 623 appendix does not implement smart folding. 625 Note that the headers are surrounded by different printable 626 characters than shown in the script-generated examples. 628 9.3.1. Using '\' 630 [NOTE: '\' line wrapping per BCP XXX (RFC XXXX)] 632 636 637 config-modules 638 639 ietf-interfaces 640 2018-02-20 641 \ 642 urn:ietf:params:xml:ns:yang:ietf-interfaces\ 643 644 645 ... 646 647 ... 648 650 Below is the equivalent to the above, but it was folded using the 651 script in the appendix. 653 ========== NOTE: '\' line wrapping per BCP XXX (RFC XXXX) =========== 655 659 660 config-modules 661 662 ietf-interfaces 663 2018-02-20 664 urn:ietf:params:xml:ns:yang:ietf-interfaces 666 667 ... 668 669 ... 670 672 9.3.2. Using '\\' 674 [NOTE: '\\' line wrapping per BCP XXX (RFC XXXX)] 676 680 681 config-modules 682 683 ietf-interfaces 684 2018-02-20 685 \ 686 \urn:ietf:params:xml:ns:yang:ietf-interfaces\ 687 \ 688 689 ... 690 691 ... 692 694 Below is the equivalent to the above, but it was folded using the 695 script in the appendix. 697 ========== NOTE: '\\' line wrapping per BCP XXX (RFC XXXX) ========== 699 703 704 config-modules 705 706 ietf-interfaces 707 2018-02-20 708 urn:ietf:params:xml:ns:yang:ietf-interfaces 710 711 ... 712 713 ... 714 716 9.4. Example Showing "Forced" Folding 718 This example illustrates how invalid sequences in lines that do not 719 have to be folded can be handled via forced folding, whereby the 720 folding occurs even though unnecessary. 722 The following line exceeds a 68-char max, thus demands folding 723 123456789012345678901234567890123456789012345678901234567890123456789 725 This line ends with a backslash \ 727 This line ends with a backslash \ 728 \ This line begins with a backslash 730 Following is an indented 3x3 block of backslashes: 731 \\\ 732 \\\ 733 \\\ 735 The samples below were manually folded, since the script in the 736 appendix does not implement forced folding. 738 Note that the headers are prefixed by a pound ('#') character, rather 739 than surrounded by equal ('=') characters as shown in the script- 740 generated examples. 742 9.4.1. Using '\' 744 # NOTE: '\' line wrapping per BCP XXX (RFC XXXX) 746 The following line exceeds a 68-char max, thus demands folding 747 1234567890123456789012345678901234567890123456789012345678901234567\ 748 89 750 This line ends with a backslash \\ 752 This line ends with a backslash \\ 754 \ This line begins with a backslash 756 Following is an indented 3x3 block of backslashes: 757 \\\\ 759 \\\\ 761 \\\ 763 9.4.2. Using '\\' 765 # NOTE: '\\' line wrapping per BCP XXX (RFC XXXX) 767 The following line exceeds a 68-char max, thus demands folding 768 1234567890123456789012345678901234567890123456789012345678901234567\ 769 \89 771 This line ends with a backslash \ 773 This line ends with a backslash \\ 774 \ 775 \ This line begins with a backslash 777 Following is an indented 3x3 block of backslashes: 778 \\\\ 779 \ 780 \\\\ 781 \ 782 \\\ 784 10. Security Considerations 786 This BCP has no Security Considerations. 788 11. IANA Considerations 790 This BCP has no IANA Considerations. 792 12. References 794 12.1. Normative References 796 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 797 Requirement Levels", BCP 14, RFC 2119, 798 DOI 10.17487/RFC2119, March 1997, 799 . 801 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 802 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 803 May 2017, . 805 12.2. Informative References 807 [pyang] "An extensible YANG (RFC 6020/7950) validator.", 808 . 810 [RFC7749] Reschke, J., "The "xml2rfc" Version 2 Vocabulary", 811 RFC 7749, DOI 10.17487/RFC7749, February 2016, 812 . 814 [RFC7950] Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language", 815 RFC 7950, DOI 10.17487/RFC7950, August 2016, 816 . 818 [RFC7991] Hoffman, P., "The "xml2rfc" Version 3 Vocabulary", 819 RFC 7991, DOI 10.17487/RFC7991, December 2016, 820 . 822 [RFC7994] Flanagan, H., "Requirements for Plain-Text RFCs", 823 RFC 7994, DOI 10.17487/RFC7994, December 2016, 824 . 826 [RFC8340] Bjorklund, M. and L. Berger, Ed., "YANG Tree Diagrams", 827 BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, 828 . 830 [xiax] "The `xiax` Python Package", 831 . 833 [yang-doctors-thread] 834 "[yang-doctors] automating yang doctor reviews", 835 . 838 [yanglint] 839 "A feature-rich tool for validation and conversion of the 840 schemas and YANG modeled data.", 841 . 843 Appendix A. POSIX Shell Script: rfcfold 845 This non-normative appendix section includes a shell script that can 846 both fold and unfold text content using both the single and double 847 backslash strategies described in Section 7 and Section 8 848 respectively. 850 This script is intended to be applied to a single text content 851 instance. If it is desired to fold or unfold text content instances 852 within a larger document (e.g., an Internet draft or RFC), then 853 another tool must be used to extract the content from the larger 854 document before utilizing this script. 856 For readability purposes, this script forces the minimally supported 857 line length to be eight characters longer than the raw header text 858 defined in Section 7.1.1 and Section 8.1.1 so as to ensure that the 859 header can be wrapped by a space (' ') character and three equal 860 ('=') characters on each side of the raw header text. 862 This script does not implement the whitespace-avoidance logic 863 described in Section 7.2.1. In such case, the script will exit with 864 one of the following message: 866 Error: infile has a space character occuring on the 867 folding column. This file cannot be folded using the 868 '\' strategy. 870 While this script can unfold input that contains forced foldings, it 871 unable to fold files that would require forced foldings. Forced 872 folding is described in Section 7.2.1 and Section 8.2.1. When being 873 asked to fold a file that would require forced folding, the script 874 will instead exit with one of the following messages: 876 Error: infile has a line ending with a '\' character. 877 This file cannot be folded using the '\' strategy without 878 there being false positives produced in the unfolding 879 (i.e., this script does not attempt to proactively 880 force-fold such lines, as described in RFC XXXX). 882 Error: infile has a line ending with a '\' character 883 followed by a '\' character as the first non-space 884 character on the next line. This script cannot fold 885 this file using '\\' strategy without there being 886 false positives produced in the unfolding (i.e., this 887 script does not attempt to proactively force-fold such 888 lines, as described in RFC XXXX). 890 Shell-level end-of-line backslash ('\') characters have been 891 purposely added to the script so as to ensure that the script is 892 itself not folded in this document, thus simplify the ability to 893 copy/paste the script for local use. As should be evident by the 894 lack of the mandatory header described in Section 7.1.1, these 895 backslashes do not designate a folded line, such as described in 896 Section 7. 898 900 #!/bin/bash --posix 902 # This script may need some adjustments to work on a given system. 903 # For instance, the utilities `pcregrep` and `gsed` may need to 904 # be installed. Also, please be advised that `bash` (not `sh`) 905 # must be used. 907 # Copyright (c) 2019 IETF Trust, Kent Watsen, and Erik Auerswald. 908 # All rights reserved. 909 # 910 # Redistribution and use in source and binary forms, with or without 911 # modification, are permitted provided that the following conditions 912 # are met: 913 # 914 # * Redistributions of source code must retain the above copyright 915 # notice, this list of conditions and the following disclaimer. 916 # 917 # * Redistributions in binary form must reproduce the above 918 # copyright notice, this list of conditions and the following 919 # disclaimer in the documentation and/or other materials 920 # provided with the distribution. 921 # 922 # * Neither the name of Internet Society, IETF or IETF Trust, nor 923 # the names of specific contributors, may be used to endorse or 924 # promote products derived from this software without specific 925 # prior written permission. 926 # 927 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 928 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 929 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 930 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 931 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 932 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 933 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 934 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 935 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 936 # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 937 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 938 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 940 print_usage() { 941 printf "\n" 942 printf "Folds or unfolds the input text file according to BCP XXX" 943 printf " (RFC XXXX).\n" 944 printf "\n" 945 printf "Usage: rfcfold [-s ] [-c ] [-r] -i " 946 printf " -o \n" 947 printf "\n" 948 printf " -s: strategy to use, '1' or '2' (default: try 1," 949 printf " else 2)\n" 950 printf " -c: column to fold on (default: 69)\n" 951 printf " -r: reverses the operation\n" 952 printf " -i: the input filename\n" 953 printf " -o: the output filename\n" 954 printf " -d: show debug messages\n" 955 printf " -q: quiet (suppress error messages)\n" 956 printf " -h: show this message\n" 957 printf "\n" 958 printf "Exit status code: 1 on error, 0 on success, -1 on no-op.\n" 959 printf "\n" 960 } 962 # global vars, do not edit 963 strategy=0 # auto 964 debug=0 965 quiet=0 966 reversed=0 967 infile="" 968 outfile="" 969 maxcol=69 # default, may be overridden by param 970 hdr_txt_1="NOTE: '\\' line wrapping per BCP XXX (RFC XXXX)" 971 hdr_txt_2="NOTE: '\\\\' line wrapping per BCP XXX (RFC XXXX)" 972 equal_chars="=======================================================" 973 space_chars=" " 974 temp_dir="" 976 # determine name of [g]sed binary 977 type gsed > /dev/null 2>&1 && SED=gsed || SED=sed 979 # warn if a non-GNU sed utility is used 980 "$SED" --version < /dev/null 2> /dev/null \ 981 | grep GNU >/dev/null 2>&1 || \ 982 echo 'Warning: not using GNU `sed` (likely cause if an error occurs)' 984 # verify the availability of pcregrep 985 type pcregrep > /dev/null 2>&1 || { 986 printf '\nError: missing utility `pcregrep`\n' 987 exit 1 988 } 990 cleanup() { 991 rm -rf "$temp_dir" 992 } 993 trap 'cleanup' EXIT 995 fold_it_1() { 996 # ensure input file doesn't contain the fold-sequence already 997 pcregrep -M "\\\\\n" $infile >> /dev/null 2>&1 998 if [[ $? -eq 0 ]]; then 999 if [[ $quiet -eq 0 ]]; then 1000 echo 1001 echo "Error: infile $infile has a line ending with a '\\'" 1002 echo "character. This file cannot be folded using the '\\'" 1003 echo "strategy without there being false positives produced" 1004 echo "in the unfolding (i.e., this script does not attempt" 1005 echo "to proactively force-fold such lines, as described" 1006 echo "in RFC XXXX)." 1007 echo 1008 fi 1009 return 1 1010 fi 1012 # where to fold 1013 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 1015 # ensure input file doesn't contain whitespace on the fold column 1016 grep "^.\{$foldcol\} " $infile >> /dev/null 2>&1 1017 if [[ $? -eq 0 ]]; then 1018 if [[ $quiet -eq 0 ]]; then 1019 echo 1020 echo "Error: infile has a space character occuring on the" 1021 echo "folding column. This file cannot be folded using the" 1022 echo "'\\' strategy." 1023 echo 1024 fi 1025 return 1 1026 fi 1028 # center header text 1029 length=`expr ${#hdr_txt_1} + 2` 1030 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 1031 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 1032 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 1033 "$hdr_txt_1" "$right_sp" "$equal_chars"` 1035 # generate outfile 1036 echo "$header" > $outfile 1037 echo "" >> $outfile 1038 "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\2/;t M;b;:M;P;D;'\ 1039 < $infile >> $outfile 2>/dev/null 1040 if [[ $? -ne 0 ]]; then 1041 return 1 1042 fi 1043 return 0 1044 } 1046 fold_it_2() { 1047 # where to fold 1048 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 1050 # ensure input file doesn't contain the fold-sequence already 1051 pcregrep -M "\\\\\n[\ ]*\\\\" $infile >> /dev/null 2>&1 1052 if [[ $? -eq 0 ]]; then 1053 if [[ $quiet -eq 0 ]]; then 1054 echo 1055 echo "Error: infile has a line ending with a '\\' character" 1056 echo "followed by a '\\' character as the first non-space" 1057 echo "character on the next line. This script cannot fold" 1058 echo "this file using '\\\\' strategy without there being" 1059 echo "false positives produced in the unfolding (i.e., this" 1060 echo "script does not attempt to proactively force-fold such" 1061 echo "lines, as described in RFC XXXX)." 1062 echo 1063 fi 1064 return 1 1065 fi 1067 # center header text 1068 length=`expr ${#hdr_txt_2} + 2` 1069 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 1070 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 1071 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 1072 "$hdr_txt_2" "$right_sp" "$equal_chars"` 1074 # generate outfile 1075 echo "$header" > $outfile 1076 echo "" >> $outfile 1077 "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\\\2/;t M;b;:M;P;D;'\ 1078 < $infile >> $outfile 2>/dev/null 1079 if [[ $? -ne 0 ]]; then 1080 return 1 1081 fi 1082 return 0 1084 } 1086 fold_it() { 1087 # ensure input file doesn't contain a TAB 1088 grep $'\t' $infile >> /dev/null 2>&1 1089 if [[ $? -eq 0 ]]; then 1090 if [[ $quiet -eq 0 ]]; then 1091 echo 1092 echo "Error: infile contains a TAB character, which is" 1093 echo "not allowed." 1094 echo 1095 fi 1096 return 1 1097 fi 1099 # check if file needs folding 1100 testcol=`expr "$maxcol" + 1` 1101 grep ".\{$testcol\}" $infile >> /dev/null 2>&1 1102 if [ $? -ne 0 ]; then 1103 if [[ $debug -eq 1 ]]; then 1104 echo "nothing to do" 1105 fi 1106 cp $infile $outfile 1107 return -1 1108 fi 1110 if [[ $strategy -eq 1 ]]; then 1111 fold_it_1 1112 return $? 1113 fi 1114 if [[ $strategy -eq 2 ]]; then 1115 fold_it_2 1116 return $? 1117 fi 1118 quiet_sav=$quiet 1119 quiet=1 1120 fold_it_1 1121 result=$? 1122 quiet=$quiet_sav 1123 if [[ $result -ne 0 ]]; then 1124 if [[ $debug -eq 1 ]]; then 1125 echo "Folding strategy 1 didn't succeed, trying strategy 2..." 1126 fi 1127 fold_it_2 1128 return $? 1129 fi 1130 return 0 1131 } 1132 unfold_it_1() { 1133 temp_dir=`mktemp -d` 1135 # output all but the first two lines (the header) to wip file 1136 awk "NR>2" $infile > $temp_dir/wip 1138 # unfold wip file 1139 "$SED" '{H;$!d};x;s/^\n//;s/\\\n *//g' $temp_dir/wip > $outfile 1141 return 0 1142 } 1144 unfold_it_2() { 1145 temp_dir=`mktemp -d` 1147 # output all but the first two lines (the header) to wip file 1148 awk "NR>2" $infile > $temp_dir/wip 1150 # unfold wip file 1151 "$SED" '{H;$!d};x;s/^\n//;s/\\\n *\\//g' $temp_dir/wip > $outfile 1153 return 0 1154 } 1156 unfold_it() { 1157 # check if file needs unfolding 1158 line=`head -n 1 $infile` 1159 line2=`$SED -n '2p' $infile` 1160 result=`echo $line | fgrep "$hdr_txt_1"` 1161 if [ $? -eq 0 ]; then 1162 if [ -n "$line2" ]; then 1163 if [[ $quiet -eq 0 ]]; then 1164 echo "Error: the second line is not empty." 1165 fi 1166 return 1 1167 fi 1168 unfold_it_1 1169 return $? 1170 fi 1171 result=`echo $line | fgrep "$hdr_txt_2"` 1172 if [ $? -eq 0 ]; then 1173 if [ -n "$line2" ]; then 1174 if [[ $quiet -eq 0 ]]; then 1175 echo "Error: the second line is not empty." 1176 fi 1177 return 1 1178 fi 1179 unfold_it_2 1180 return $? 1181 fi 1182 if [[ $debug -eq 1 ]]; then 1183 echo "nothing to do" 1184 fi 1185 cp $infile $outfile 1186 return -1 1187 } 1189 process_input() { 1190 while [ "$1" != "" ]; do 1191 if [ "$1" == "-h" -o "$1" == "--help" ]; then 1192 print_usage 1193 exit 0 1194 fi 1195 if [ "$1" == "-d" ]; then 1196 debug=1 1197 fi 1198 if [ "$1" == "-q" ]; then 1199 quiet=1 1200 fi 1201 if [ "$1" == "-s" ]; then 1202 strategy="$2" 1203 shift 1204 fi 1205 if [ "$1" == "-c" ]; then 1206 maxcol="$2" 1207 shift 1208 fi 1209 if [ "$1" == "-r" ]; then 1210 reversed=1 1211 fi 1212 if [ "$1" == "-i" ]; then 1213 infile="$2" 1214 shift 1215 fi 1216 if [ "$1" == "-o" ]; then 1217 outfile="$2" 1218 shift 1219 fi 1220 shift 1221 done 1223 if [[ -z "$infile" ]]; then 1224 if [[ $quiet -eq 0 ]]; then 1225 echo 1226 echo "Error: infile parameter missing (use -h for help)" 1227 echo 1229 fi 1230 exit 1 1231 fi 1233 if [[ -z "$outfile" ]]; then 1234 if [[ $quiet -eq 0 ]]; then 1235 echo 1236 echo "Error: outfile parameter missing (use -h for help)" 1237 echo 1238 exit 1 1239 fi 1240 fi 1242 if [[ ! -f "$infile" ]]; then 1243 if [[ $quiet -eq 0 ]]; then 1244 echo 1245 echo "Error: specified file \"$infile\" is does not exist." 1246 echo 1247 exit 1 1248 fi 1249 fi 1251 if [[ $strategy -eq 2 ]]; then 1252 min_supported=`expr ${#hdr_txt_2} + 8` 1253 else 1254 min_supported=`expr ${#hdr_txt_1} + 8` 1255 fi 1256 if [[ $maxcol -lt $min_supported ]]; then 1257 if [[ $quiet -eq 0 ]]; then 1258 echo 1259 echo "Error: the folding column cannot be less than" 1260 echo "$min_supported." 1261 echo 1262 fi 1263 exit 1 1264 fi 1266 # this is only because the code otherwise runs out of equal_chars 1267 max_supported=`expr ${#equal_chars} + 1 + ${#hdr_txt_1} + 1\ 1268 + ${#equal_chars}` 1269 if [[ $maxcol -gt $max_supported ]]; then 1270 if [[ $quiet -eq 0 ]]; then 1271 echo 1272 echo "Error: the folding column cannot be more than" 1273 echo "$max_supported." 1274 echo 1275 fi 1276 exit 1 1278 fi 1279 } 1281 main() { 1282 if [ "$#" == "0" ]; then 1283 print_usage 1284 exit 1 1285 fi 1287 process_input $@ 1289 if [[ $reversed -eq 0 ]]; then 1290 fold_it 1291 code=$? 1292 else 1293 unfold_it 1294 code=$? 1295 fi 1296 exit $code 1297 } 1299 main "$@" 1301 1303 Acknowledgements 1305 The authors thank the RFC Editor for confirming that there was 1306 previously no set convention for handling long lines in sourcecode 1307 inclusions, thus instigating this work. 1309 The authors thank the following folks for their various contributions 1310 while producing this document (sorted by first name): Benoit Claise, 1311 Erik Auerswald, Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan 1312 Hansford, Lou Berger, Martin Bjorklund, and Rob Wilton. 1314 Special acknowledgement to Erik Auerswald for his contributions to 1315 the `rfcfold` script, especially for greatly improving the `sed` one- 1316 liners used therein. 1318 Authors' Addresses 1320 Kent Watsen 1321 Watsen Networks 1323 EMail: kent+ietf@watsen.net 1324 Adrian Farrel 1325 Old Dog Consulting 1327 EMail: adrian@olddog.co.uk 1329 Qin Wu 1330 Huawei Technologies 1332 EMail: bill.wu@huawei.com