draft-ietf-netmod-artwork-folding-11.txt   draft-ietf-netmod-artwork-folding-12.txt 
NETMOD Working Group K. Watsen NETMOD Working Group K. Watsen
Internet-Draft Watsen Networks Internet-Draft Watsen Networks
Intended status: Informational E. Erik Intended status: Informational E. Auerswald
Expires: May 6, 2020 Individual Contributor Expires: July 23, 2020 Individual Contributor
A. Farrel A. Farrel
Old Dog Consulting Old Dog Consulting
Q. Wu Q. Wu
Huawei Technologies Huawei Technologies
November 3, 2019 January 20, 2020
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-11 draft-ietf-netmod-artwork-folding-12
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 is thereby able to handle identify where the continuation begins and is thereby able to handle
skipping to change at page 2, line 10 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 May 6, 2020. This Internet-Draft will expire on July 23, 2020.
Copyright Notice Copyright Notice
Copyright (c) 2019 IETF Trust and the persons identified as the Copyright (c) 2020 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
carefully, as they describe your rights and restrictions with respect carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as the Trust Legal Provisions and are provided without warranty as
skipping to change at page 3, line 25 skipping to change at page 3, line 25
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 . . . . . . . . . . . . . . . . . 19 12.2. Informative References . . . . . . . . . . . . . . . . . 19
Appendix A. Bash Shell Script: rfcfold . . . . . . . . . . . . . 20 Appendix A. Bash Shell Script: rfcfold . . . . . . . . . . . . . 20
Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 29 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 30
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 30 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
skipping to change at page 23, line 28 skipping to change at page 23, line 28
equal_chars="=======================================================" equal_chars="======================================================="
space_chars=" " space_chars=" "
temp_dir="" temp_dir=""
prog_name='rfcfold' prog_name='rfcfold'
# functions for diagnostic messages # functions for diagnostic messages
prog_msg() { prog_msg() {
if [[ "$quiet" -eq 0 ]]; then if [[ "$quiet" -eq 0 ]]; then
format_string="${prog_name}: $1: %s\n" format_string="${prog_name}: $1: %s\n"
shift shift
printf -- "$format_string" "$@" >&2 printf -- "$format_string" "$*" >&2
fi fi
} }
err() { err() {
prog_msg 'Error' "$@" prog_msg 'Error' "$@"
} }
warn() { warn() {
prog_msg 'Warning' "$@" prog_msg 'Warning' "$@"
} }
skipping to change at page 23, line 50 skipping to change at page 23, line 50
dbg() { dbg() {
if [[ "$debug" -eq 1 ]]; then if [[ "$debug" -eq 1 ]]; then
prog_msg 'Debug' "$@" prog_msg 'Debug' "$@"
fi 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 -q GNU || \
| grep GNU > /dev/null 2>&1 || \ warn 'not using GNU `sed` (likely cause if an error occurs).'
warn 'not using GNU `sed` (likely cause if an error occurs)'
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
if [[ -n "$("$SED" -n '/\\$/p' "$infile")" ]]; then if [[ -n "$("$SED" -n '/\\$/p' "$infile")" ]]; then
err "infile has a line ending with a '\\' character."\ err "infile '$infile' has a line ending with a '\\' character."\
"This file cannot be folded using the '\\' strategy"\ "This script cannot fold this file using the '\\' strategy"\
"without there being false positives produced in the"\ "without there being false positives produced in the"\
"unfolding (i.e., this script does not force-fold"\ "unfolding."
"such lines, as described in BCP XXX, RFC XXXX)."
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\}\)\{1,\} " "$infile" grep -q "^\(.\{$foldcol\}\)\{1,\} " "$infile"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
err "infile has a space character occurring on the"\ err "infile '$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."
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"\
skipping to change at page 25, line 4 skipping to change at page 24, line 48
# 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
if [[ -n "$("$SED" -n '/\\$/{N;s/\\\n[ ]*\\/&/p}' "$infile")" ]] if [[ -n "$("$SED" -n '/\\$/{N;s/\\\n[ ]*\\/&/p;D}' "$infile")" ]]
then then
err "infile has a line ending with a '\\' character"\ err "infile '$infile' has a line ending with a '\\' character"\
"followed by a '\\' character as the first non-space"\ "followed by a '\\' character as the first non-space"\
"character on the next line. This script cannot fold"\ "character on the next line. This script cannot fold"\
"this file using '\\\\' strategy without there being"\ "this file using '\\\\' strategy without there being"\
"false positives produced in the unfolding (i.e., this"\ "false positives produced in the unfolding."
"script does not force-fold such lines, as described"\
"in BCP XXX, RFC XXXX)."
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")
skipping to change at page 25, line 43 skipping to change at page 25, line 37
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
err "infile contains a TAB character, which is not allowed." err "infile '$infile' contains a TAB character, which is not"\
"allowed."
return 1 return 1
fi fi
# folding of input containing ASCII control or non-ASCII characters # folding of input containing ASCII control or non-ASCII characters
# may result in a wrong folding column and is not supported # may result in a wrong folding column and is not supported
if type gawk > /dev/null 2>&1; then if type gawk > /dev/null 2>&1; then
env LC_ALL=C gawk '/[\000-\014\016-\037\177]/{exit 1}' "$infile"\ env LC_ALL=C gawk '/[\000-\014\016-\037\177]/{exit 1}' "$infile"\
|| warn 'infile contains ASCII control characters (unsupported).' || warn "infile '$infile' contains ASCII control characters"\
"(unsupported)."
env LC_ALL=C gawk '/[^\000-\177]/{exit 1}' "$infile"\ env LC_ALL=C gawk '/[^\000-\177]/{exit 1}' "$infile"\
|| warn 'infile contains non-ASCII characters (unsupported).' || warn "infile '$infile' contains non-ASCII characters"\
"(unsupported)."
else else
dbg 'no GNU Awk, skipping checks for special characters.' dbg "no GNU Awk, skipping checks for special characters."
fi 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
dbg "nothing to do" dbg "nothing to do; copying infile to outfile."
cp "$infile" "$outfile" cp "$infile" "$outfile"
return 255 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
dbg "Folding strategy 1 didn't succeed, trying strategy 2..." dbg "Folding strategy '1' didn't succeed, trying strategy '2'..."
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
skipping to change at page 27, line 24 skipping to change at page 27, line 21
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
err "the second line is not empty." err "the second line in '$infile' is not empty."
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
err "the second line is not empty." err "the second line in '$infile' is not empty."
return 1 return 1
fi fi
unfold_it_2 unfold_it_2
return $? return $?
fi fi
dbg "nothing to do" dbg "nothing to do; copying infile to outfile."
cp "$infile" "$outfile" cp "$infile" "$outfile"
return 255 return 255
} }
process_input() { process_input() {
while [[ "$1" != "" ]]; do while [[ "$1" != "" ]]; do
if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
print_usage print_usage
exit 0 exit 0
elif [[ "$1" == "-d" ]]; then elif [[ "$1" == "-d" ]]; then
debug=1 debug=1
elif [[ "$1" == "-q" ]]; then elif [[ "$1" == "-q" ]]; then
quiet=1 quiet=1
elif [[ "$1" == "-s" ]]; then elif [[ "$1" == "-s" ]]; then
if [[ "$#" -eq "1" ]]; then
err "option '-s' needs an argument (use -h for help)."
exit 1
fi
strategy="$2" strategy="$2"
shift shift
elif [[ "$1" == "-c" ]]; then elif [[ "$1" == "-c" ]]; then
if [[ "$#" -eq "1" ]]; then
err "option '-c' needs an argument (use -h for help)."
exit 1
fi
col_gvn=1 col_gvn=1
maxcol="$2" maxcol="$2"
shift shift
elif [[ "$1" == "-r" ]]; then elif [[ "$1" == "-r" ]]; then
reversed=1 reversed=1
elif [[ "$1" == "-i" ]]; then elif [[ "$1" == "-i" ]]; then
if [[ "$#" -eq "1" ]]; then
err "option '-i' needs an argument (use -h for help)."
exit 1
fi
infile="$2" infile="$2"
shift shift
elif [[ "$1" == "-o" ]]; then elif [[ "$1" == "-o" ]]; then
if [[ "$#" -eq "1" ]]; then
err "option '-o' needs an argument (use -h for help)."
exit 1
fi
outfile="$2" outfile="$2"
shift shift
else else
warn "ignoring unknown option '$1'" warn "ignoring unknown option '$1'."
fi fi
shift shift
done done
if [[ -z "$infile" ]]; then if [[ -z "$infile" ]]; then
err "infile parameter missing (use -h for help)" err "infile parameter missing (use -h for help)."
exit 1 exit 1
fi fi
if [[ -z "$outfile" ]]; then if [[ -z "$outfile" ]]; then
err "outfile parameter missing (use -h for help)" err "outfile parameter missing (use -h for help)."
exit 1 exit 1
fi fi
if [[ ! -f "$infile" ]]; then if [[ ! -f "$infile" ]]; then
err "specified file \"$infile\" is does not exist." err "specified file '$infile' does not exist."
exit 1 exit 1
fi fi
if [[ "$col_gvn" -eq 1 ]] && [[ "$reversed" -eq 1 ]]; then if [[ "$col_gvn" -eq 1 ]] && [[ "$reversed" -eq 1 ]]; then
warn "'-c' option ignored when unfolding (option '-r')" warn "'-c' option ignored when unfolding (option '-r')."
fi fi
if [[ "$strategy" -eq 0 ]] || [[ "$strategy" -eq 2 ]]; then if [[ "$strategy" -eq 0 ]] || [[ "$strategy" -eq 2 ]]; then
min_supported=$(expr ${#hdr_txt_2} + 8) min_supported=$(expr ${#hdr_txt_2} + 8)
else else
min_supported=$(expr ${#hdr_txt_1} + 8) min_supported=$(expr ${#hdr_txt_1} + 8)
fi fi
if [[ "$maxcol" -lt "$min_supported" ]]; then if [[ "$maxcol" -lt "$min_supported" ]]; then
err "the folding column cannot be less than $min_supported." err "the folding column cannot be less than $min_supported."
exit 1 exit 1
skipping to change at page 29, line 47 skipping to change at page 30, line 14
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,
Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan Hansford, Lou Ben Kaduk, Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan
Berger, Martin Bjorklund, and Rob Wilton. 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 Authors' Addresses
Kent Watsen Kent Watsen
Watsen Networks Watsen Networks
EMail: kent+ietf@watsen.net EMail: kent+ietf@watsen.net
Erik Auerswald Erik Auerswald
Individual Contributor Individual Contributor
 End of changes. 36 change blocks. 
43 lines changed or deleted 54 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/