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