Big documentation update, particularly tags (#290)

* Big documentation update, particularly tags

* More documentation fixes

---------

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index e9409ef..a580e4d 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -197,6 +197,10 @@
 		E7B699092D128AC800D8F78F /* qcbor_number_encode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_number_encode.c; path = src/qcbor_number_encode.c; sourceTree = "<group>"; };
 		E7B6990D2D13E56F00D8F78F /* qcbor_number_encode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qcbor_number_encode.h; path = inc/qcbor/qcbor_number_encode.h; sourceTree = "<group>"; };
 		E7B6990E2D13EF4700D8F78F /* qcbor_encode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = qcbor_encode.h; path = inc/qcbor/qcbor_encode.h; sourceTree = "<group>"; };
+		E7B699102D17327F00D8F78F /* TimeTag1FAQ.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = TimeTag1FAQ.md; path = doc/TimeTag1FAQ.md; sourceTree = "<group>"; };
+		E7B699112D17328B00D8F78F /* mainpage.dox */ = {isa = PBXFileReference; lastKnownFileType = text; name = mainpage.dox; path = doc/mainpage.dox; sourceTree = "<group>"; };
+		E7B699122D1732BD00D8F78F /* Building.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = Building.md; path = doc/Building.md; sourceTree = "<group>"; };
+		E7B699132D17421D00D8F78F /* Overview.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = Overview.md; path = doc/Overview.md; sourceTree = "<group>"; };
 		E7C6D9952CB7D4010034425D /* tag-examples.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "tag-examples.h"; sourceTree = "<group>"; };
 		E7C6D9962CB7D4010034425D /* tag-examples.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "tag-examples.c"; sourceTree = "<group>"; };
 		E7C960B72800A09E00FB537C /* ub-example.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ub-example.h"; sourceTree = "<group>"; };
@@ -270,14 +274,11 @@
 		E776E073214ADF7F00E67947 = {
 			isa = PBXGroup;
 			children = (
-				E776E161214EE19C00E67947 /* README.md */,
-				E743D132251014E60017899F /* Tagging.md */,
-				E7E305E02CE14447000E9348 /* Numbers.md */,
-				E7A7B60E2B76FB62009102C2 /* Serialization.md */,
 				E776E096214AE0C700E67947 /* cmd_line_main.c */,
 				E776E092214AE07C00E67947 /* inc */,
 				E776E08B214AE06600E67947 /* src */,
 				E776E095214AE0B600E67947 /* test */,
+				E7B6990F2D17321B00D8F78F /* doc */,
 				E743D0E024AC51470017899F /* example */,
 				E776E07D214ADF7F00E67947 /* Products */,
 			);
@@ -354,6 +355,21 @@
 			name = test;
 			sourceTree = "<group>";
 		};
+		E7B6990F2D17321B00D8F78F /* doc */ = {
+			isa = PBXGroup;
+			children = (
+				E7B699132D17421D00D8F78F /* Overview.md */,
+				E7B699122D1732BD00D8F78F /* Building.md */,
+				E7B699112D17328B00D8F78F /* mainpage.dox */,
+				E7B699102D17327F00D8F78F /* TimeTag1FAQ.md */,
+				E776E161214EE19C00E67947 /* README.md */,
+				E743D132251014E60017899F /* Tagging.md */,
+				E7E305E02CE14447000E9348 /* Numbers.md */,
+				E7A7B60E2B76FB62009102C2 /* Serialization.md */,
+			);
+			name = doc;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
diff --git a/README.md b/README.md
index 5630e01..ae4fc30 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
 * Unexpected tag numbers are not silently ignored unless in v1 compatibility
 mode. This is more correct decoding behavior.
 
-* New API to explicitly decode tag numbers to make tag numbers easier to 
+* New API to explicitly decode tag numbers to make tag numbers easier to
 work with.
 
 * Plug-in API scheme for custom tag content processors.
@@ -44,19 +44,19 @@
 so it is often better to not return to QCBOR v1 behavior.
 
 Another difference is that the tag content decoders for big numbers,
-big floats, URIs and such are not enabled by default. These are 
+big floats, URIs and such are not enabled by default. These are
 what notices the things like the big number and big float tags,
 decodes them and turns them into QCBOR types for big numbers and floats.
 
 QCBORDecode_Compatibilityv1() disables the error out on unprocessed
 tag numbers and installs the same tag content decoders that v1 had.
 
-The tag number decoders can be installed with the retention of 
+The tag number decoders can be installed with the retention of
 erroring out on unprocessed tag numbers by calling
 QCBORDecode_InstallTagDecoders(pMe, QCBORDecode_TagDecoderTablev1, NULL);
 
 QCBOR v2 requires tag numbers to be consumed in one of three ways.
-It may be consumed explicitly with QCBORDecode_GetNextTagNumber(). 
+It may be consumed explicitly with QCBORDecode_GetNextTagNumber().
 It may be consumed by a tag content process or like QCBORDecode_DateEpochTagCB()
 installed with QCBORDecode_InstallTagDecoders(). It may be
 consumed with a spiffy decode function like QCBORDecode_GetTBigNumber().
@@ -205,332 +205,6 @@
 through CAF](https://source.codeaurora.org/quic/QCBOR/QCBOR/) with a
 permissive Linux license, September 2018 (thanks Qualcomm!).
 
-## Building
-
-The library is built solely from the src and inc directores. The inc directory
-contains the public interface. The test app and such are in other
-directories.
-
-There is a basic makefile that will build the library and command 
-line test app. CMake is also available, please read
-the "Building with CMake" section for more information.
-
-QCBOR will compile and fully function without any build configuration
-or set up. It is 100% portable.
-
-There are a number of C preprocessor #defines that can be set. 
-Their primary purpose is to reduce library object code sizes
-by disabling features.  A couple slightly improve performance. 
-See the comment sections on "Configuration" in inc/UsefulBuf.h and
-the pre processor defines that start with QCBOR_DISABLE_XXX.
-
-The test directory includes the tests that are nearly as portable as
-the main implementation.  If your development environment doesn't
-support UNIX style command line and make, you should be able to make a
-simple project and add the test files to it.  Then just call
-RunTests() to invoke them all.
-
-### Building with CMake
-
-CMake can also be used to build QCBOR and the test application. Having the root
-`CMakeLists.txt` file, QCBOR can be easily integrated with your project's
-existing CMake environment. The result of the build process is a static library,
-to build a shared library instead you must add the
-`-DBUILD_SHARED_LIBS=ON` option at the CMake configuration step.
-The tests can be built into a simple command line application to run them as it
-was mentioned before; or it can be built as a library to be integrated with your
-development environment.
-The `BUILD_QCBOR_TEST` CMake option can be used for building the tests, it can
-have three values: `APP`, `LIB` or `OFF` (default, test are not included in the
-build).
-
-Building the QCBOR library:
-
-```bash
-cd <QCBOR_base_folder>
-# Configuring the project and generating a native build system
-cmake -S . -B <build_folder>
-# Building the project
-cmake --build <build_folder>
-```
-
-Building and running the QCBOR test app:
-```bash
-cd <QCBOR_base_folder>
-# Configuring the project and generating a native build system
-cmake -S . -B <build_folder> -DBUILD_QCBOR_TEST=APP
-# Building the project
-cmake --build <build_folder>
-# Running the test app
-.<build_folder>/test/qcbortest
-```
-
-To enable all the compiler warnings that are used in the QCBOR release process
-you can use the `BUILD_QCBOR_WARN` option at the CMake configuration step:
-```bash
-cmake -S . -B <build_folder> -DBUILD_QCBOR_WARN=ON
-```
-
-### Floating Point Support & Configuration
-
-By default, all QCBOR floating-point features are enabled:
-
-* Encoding and decoding of basic float types, single and double-precision
-* Encoding and decoding of half-precision with conversion to/from single
-  and double-precision
-* Preferred serialization of floating-point
-* Floating point dates
-* Methods that can convert big numbers, decimal fractions and other numbers
-  to/from floating-point
-
-If full floating-point is not needed, the following #defines can be
-used to reduce object code size and dependency.
-
-See discussion in qcbor_encode.h for other details.
-
-#### #define QCBOR_DISABLE_FLOAT_HW_USE
-
-This removes dependency on:
-
-* Floating-point hardware and floating-point instructions
-* `<math.h>` and `<fenv.h>`
-* The math library (libm, -lm)
-
-For most limited environments, this removes enough floating-point
-dependencies to be able to compile and run QCBOR.
-
-Note that this does not remove use of the types double and float from
-QCBOR, but it limits QCBOR's use of them to converting the encoded
-byte stream to them and copying them. Converting and copying them
-usually don't require any hardware, libraries or includes. The C
-compiler takes care of it on its own.
-
-QCBOR uses its own implementation of half-precision float-pointing
-that doesn't depend on math libraries. It uses masks and shifts
-instead. Thus, even with this define, half-precision encoding and
-decoding works.
-
-When this is defined, the QCBOR functionality lost is minimal and only
-for decoding:
-
-* Decoding floating-point format dates are not handled
-* There is no conversion between floats and integers when decoding. For
-  example, QCBORDecode_GetUInt64ConvertAll() will be unable to convert
-  to and from float-point.
-* Floats will be unconverted to double when decoding.
-
-No interfaces are disabled or removed with this define.  If input that
-requires floating-point conversion or functions are called that
-request floating-point conversion, an error code like
-`QCBOR_ERR_HW_FLOAT_DISABLED` will be returned.
-
-This saves only a small amount of object code. The primary purpose for
-defining this is to remove dependency on floating point hardware and
-libraries.
-
-
-#### #define QCBOR_DISABLE_PREFERRED_FLOAT
-
-This eliminates support of:
-- encode/decode of half-precision
-- shortest-form encoding of floats
-- QCBORDecode_GetNumberConvertPrecisely()
-
-This saves about 1KB of object code, though much of this can be saved
-by not calling any functions to encode doubles or floats or
-QCBORDecode_GetNumberConvertPrecisely()
-
-With this defined, single and double-precision floating-point numbers
-can still be encoded and decoded. Some conversion of floating-point to
-and from integers, big numbers and such is also supported. Floating-point
-dates are still supported.
-
-
-#### #define USEFULBUF_DISABLE_ALL_FLOAT
-
-This eliminates floating point support completely (along with related function
-headers). This is useful if the compiler options deny the usage of floating
-point operations completely, and the usage of a soft floating point ABI is not
-possible.
-
-#### Compiler options
-
-Compilers support a number of options that control
-which float-point related code is generated. For example,
-it is usually possible to give options to the compiler to avoid all
-floating-point hardware and instructions, to use software
-and replacement libraries instead. These are usually
-bigger and slower, but these options may still be useful
-in getting QCBOR to run in some environments in
-combination with `QCBOR_DISABLE_FLOAT_HW_USE`.
-In particular, `-mfloat-abi=soft`, disables use of
- hardware instructions for the float and double
- types in C for some architectures.
-
-#### CMake options
-
-If you are using CMake, it can also be used to configure the floating-point
-support. These options can be enabled by adding them to the CMake configuration
-step and setting their value to 'ON' (True). The following table shows the
-available options and the associated #defines.
-
-    | CMake option                      | #define                       |
-    |-----------------------------------|-------------------------------|
-    | QCBOR_OPT_DISABLE_FLOAT_HW_USE    | QCBOR_DISABLE_FLOAT_HW_USE    |
-    | QCBOR_OPT_DISABLE_FLOAT_PREFERRED | QCBOR_DISABLE_PREFERRED_FLOAT |
-    | QCBOR_OPT_DISABLE_FLOAT_ALL       | USEFULBUF_DISABLE_ALL_FLOAT   |
-
-## Code Size
-
-These are approximate sizes on a 64-bit x86 CPU with the -Os optimization.
-All QCBOR_DISABLE_XXX are set and compiler stack frame checking is disabled
-for smallest but not for largest. Smallest is the library functions for a
-protocol with strings, integers, arrays, maps and Booleans, but not floats
-and standard tag types.
-
-    |               | smallest | largest |
-    |---------------|----------|---------|
-    | encode only   |          |         |
-    | decode only   |          |         |
-    | combined      |          |         |
-
- From the table above, one can see that the amount of code pulled in
- from the QCBOR library varies a lot, ranging from 1KB to 15KB.  The
- main factor is the number of QCBOR functions called and
- which ones they are. QCBOR minimizes internal
- interdependency so only code necessary for the called functions is
- brought in.
-
- Encoding is simpler and smaller. An encode-only implementation may
- bring in only 1KB of code.
-
- Encoding of floating-point brings in a little more code as does
- encoding of tagged types and encoding of bstr wrapping.
-
- Basic decoding using QCBORDecode_GetNext() brings in 3KB.
-
- Use of the supplied MemPool by calling  QCBORDecode_SetMemPool() to
- setup to decode indefinite-length strings adds 0.5KB.
-
- Basic use of spiffy decode to brings in about 3KB. Using more spiffy
- decode functions, such as those for tagged types bstr wrapping brings
- in more code.
-
- Finally, use of all of the integer conversion functions will bring in
- about 5KB, though you can use the simpler ones like
- QCBORDecode_GetInt64() without bringing in very much code.
-
- In addition to using fewer QCBOR functions, the following are some
- ways to make the code smaller.
-
- The gcc compiler output is usually smaller than llvm because stack
- guards are off by default (be sure you actually have gcc and not llvm
- installed to be invoked by the gcc command). You can also turn off
- stack gaurds with llvm. It is safe to turn off stack gaurds with this
- code because Usefulbuf provides similar defenses and this code was
- carefully written to be defensive.
-
- If QCBOR is installed as a shared library, then of course only one
- copy of the code is in memory no matter how many applications use it.
-
-### Disabling Features
-
-The main control over the amount of QCBOR code that gets linked
-is through which QCBOR functions are used. Linking against a
-library or dead stripping will eliminate all code not explicitly
-called.
-
-In addition to using fewer QCBOR functions, the following #defines
-can be set to further reduce code size. For example,
-QCBOR_DISABLE_ENCODE_USAGE_GUARDS will reduce the size
-of many common encoding functions by performing less error
-checking (but not compromising any code safety).
-
-The amounts saved listed below are approximate. They depends on
-the CPU, the compiler, configuration, which functions are
-use and so on.
-
-
-    | #define                                 | Saves |
-    | ----------------------------------------| ------|
-    | QCBOR_DISABLE_ENCODE_USAGE_GUARDS       |       |
-    | QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |       |
-    | QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS  |       |
-    | QCBOR_DISABLE_EXP_AND_MANTISSA          |       |
-    | QCBOR_DISABLE_PREFERRED_FLOAT           |       |
-    | QCBOR_DISABLE_FLOAT_HW_USE              |       |
-    | QCBOR_DISABLE_TAGS                      |       |
-    | QCBOR_DISABLE_NON_INTEGER_LABELS        |       |
-    | USEFULBUF_DISABLE_ALL_FLOAT             |       |
-
-QCBOR_DISABLE_ENCODE_USAGE_GUARDS affects encoding only.  It doesn't
-disable any encoding features, just some error checking.  Disable it
-when you are confident that an encoding implementation is complete and
-correct.
-
-Indefinite lengths are a feature of CBOR that makes encoding simpler
-and the decoding more complex. They allow the encoder to not have to
-know the length of a string, map or array when they start encoding
-it. Their main use is when encoding has to be done on a very
-constrained device.  Conversely when decoding on a very constrained
-device, it is good to prohibit use of indefinite lengths so the
-decoder can be smaller.
-
-The QCBOR decode API processes both definite and indefinite lengths
-with the same API, except to decode indefinite-length strings a
-storage allocator must be configured.
-
-To reduce the size of the decoder define
-QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS particularly if you are not
-configuring a storage allocator.
-
-Further reduction can be by defining
-QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS which will result in an error
-when an indefinite-length map or array arrives for decoding.
-
-QCBOR_DISABLE_UNCOMMON_TAGS is removed from QCBOR v2. It didn't save
-very much and you can get the same effect by not install
-the tag content handlers.
-
-QCBOR_DISABLE_EXP_AND_MANTISSA disables the decoding of decimal
-fractions and big floats.
-
-QCBOR_DISABLE_TAGS disables all decoding of CBOR tags. If the input has
-a single tag, the error is unrecoverable so it is suitable only for protocols that
-have no tags. "Borrowed" tag content formats (e.g. an epoch-based date
-without the tag number), can still be processed.
-
-QCBOR_DISABLE_NON_INTEGER_LABELS causes any label that doesn't
-fit in an int64_t to result in a QCBOR_ERR_MAP_LABEL_TYPE error.
-This also disables QCBOR_DECODE_MODE_MAP_AS_ARRAY and
-QCBOR_DECODE_MODE_MAP_STRINGS_ONLY. It is fairly common for CBOR-based
-protocols to use only small integers as labels.
-
-See the discussion above on floating-point.
-
- ### Size of spiffy decode
-
- When creating a decode implementation, there is a choice of whether
- or not to use spiffy decode features or to just use
- QCBORDecode_GetNext().
-
- The implementation using spiffy decode will be simpler resulting in
- the calling code being smaller, but the amount of code brought in
- from the QCBOR library will be larger. Basic use of spiffy decode
- brings in about 2KB of object code.  If object code size is not a
- concern, then it is probably better to use spiffy decode because it
- is less work, there is less complexity and less testing to worry
- about.
-
- If code size is a concern, then use of QCBORDecode_GetNext() will
- probably result in smaller overall code size for simpler CBOR
- protocols. However, if the CBOR protocol is complex then use of
- spiffy decode may reduce overall code size.  An example of a complex
- protocol is one that involves decoding a lot of maps or maps that
- have many data items in them.  The overall code may be smaller
- because the general purpose spiffy decode map processor is the one
- used for all the maps.
-
 
 ## Other Software Using QCBOR
 
diff --git a/doc/Tagging.md b/doc/Tagging.md
index abb75f9..acaa1f7 100644
--- a/doc/Tagging.md
+++ b/doc/Tagging.md
@@ -1,31 +1,50 @@
 
 @anchor CBORTags
 
-#  Types and Tagging in CBOR
+#  QCBOR-oriented Introduction to Tags
 
 ## New Types
 
-CBOR provides a means for defining new data types beyond the primitive
-types like integers and strings. These new types can be the simple
-association of some further semantics with a primitive type or they
-can be large complex aggregations.
+CBOR allows for the definition of new data types beyond basic
+primitives like integers, strings, array and such. These new types can either be
+simple extensions of a primitive type with additional semantics or
+more complex structures involving large aggregations.
 
-The explicit means for identifying these new types as called tagging.
-It uses a simple unsigned integer known as the tag number to indicate
-that the following CBOR is of that type. Officially speaking, a "tag"
-is made up of exactly a tag number and tag content.  The tag content
-is exactly a single data item, but note that a single data item can be
-a map or an array which contains further nested maps and arrays and
-thus arbitrarily complex.
+The mechanism for identifying these new types is called tagging.
+Tagging uses a simple unsigned integer to indicate that the following
+CBOR item is a different type.
 
-The tag numbers can be up to UINT64_MAX, so there are a lot of them.
-Some defined in standards and registered in the IANA CBOR Tag
-Registry. A very large range is available for proprietary tags.
+For example, when an encoded integer is preceeded by the encoded
+tag number 1, the integer represents an epoch date.
 
+It's important to note that CBOR uses the word "tag" in an unusual
+way. In CBOR, a "tag" refers to the combination of the tag number and
+the tag content.  By the normal dictionary definition, a "tag" would
+be just a tag number, not an aggregation of tag number and tag content
+By analogy, if you attach a small label to an elephant's ear, the
+"tag" in CBOR terms would be the combination of the label (tag number)
+and the elephant (tag content).
+
+QCBOR always uses the term "tag number" to refer to the integer that
+identifies the type, "tag content" to refer to the target of the
+indicating integer and "tag" as the full combination of both.
+
+The tag content is always a single data item. However, this item can
+itself be a complex structure, such as a map or an array, which may
+contain nested maps and arrays, allowing for arbitrarily complex tag
+content.
+
+Tag numbers can range up to UINT64_MAX, providing a large number of
+possible tags. Some are defined by standards and registered in the
+IANA CBOR Tag Registry, while a substantial range is available for
+proprietary use.
+
+
+@anchor AreTagsOptional
 ## Are Tags "Optional"?
 
 The description of tags in
-[RFC 7049] (https://tools.ietf.org/html/rfc7049) and in some other
+[RFC 7049](https://tools.ietf.org/html/rfc7049) and in some other
 places can lead one to think they are optional prefixes that can be
 ignored at times. This is not true.
 
@@ -35,11 +54,11 @@
 ignoring a typedef or struct in C.
 
 However, it is common in CBOR-based protocols to use the format,
-semantics or definition of the tag content without it actually being a
+semantics and definition of the tag content without it actually being a
 *tag*. One can think of this as *borrowing* the tag content or implied
 type information.
 
-For example, [RFC 8392] (https://tools.ietf.org/html/rfc8392) which
+For example, [RFC 8392](https://tools.ietf.org/html/rfc8392) which
 defines a CBOR Web Token, a CWT, says that the NumericDate field is
 represented as a CBOR numeric date described as tag 1 in the CBOR
 standard, but with the tag number 1 omitted from the encoding. A
@@ -73,42 +92,52 @@
 Finally, every CBOR protocol should explicitly spell out how it is
 using each tag, borrowing tag content and such. If the protocol you
 are trying to implement doesn't, ask the designer.  Generally,
-protocols designs should not allow for some data item to optional be
+protocols designs should not allow for some data item to be
 either a tag or to be the borrowed tag content.  While allowing this
 tag optionality is a form of Postel's law, "be liberal in what you
 accept", current wisdom is somewhat the opposite.
 
 
-## Types and Tags in QCBOR
+## QCBOR Tag APIs
 
-QCBOR explicitly supports all the tags defined in
-[RFC 7049] (https://tools.ietf.org/html/rfc7049). It has specific APIs
-and data structures for encoding and decoding them.
+The encode APIs are in @ref inc/qcbor/qcbor_tag_encode.h "qcbor_tag_encode.h"
+and decoding APIs in @ref inc/qcbor/qcbor_tag_decode.h "qcbor_tag_decode.h"
 
-These APIs and structures can support either the full and proper tag
-form or the borrowed content form that is not a tag.
+The base primitives for encoding and decoding tag numbers are
+QCBOREncode_AddTagNumber() and QCBORDecode_VGetNextTagNumber().  These
+are used in constructing and decoding tags. Note that for decoding,
+all tag numbers have to be consumed before decoding the tag
+content. This is different from QCBOR v1 where tag numbers did not
+have to be explicitly consumed.
 
-The original QCBOR APIs for encoding tags did not allow for encoding
-the borrowed content format. They only support the proper tag
-format. With spiffy decode, a second set of APIs was added that takes
-and argument to indicate whether the proper tag should be output or
-just the borrowed content format should be output. The first set are
-the "AddXxxx" functions and the second the "AddTXxxx" functions.
+QCBOR also provides APIs for directly encoding and decoding all the
+tags standardized in [RFC 8949](https://tools.ietf.org/html/rfc8949)
+for dates, big numbers and such. For encoding their names start with
+"QCBOREncode_AddT" and for decoding they start with "QCBOREncode_Get"
+(TODO: fix this).  These APIs can handle
 
-When decoding with QCBORDecode_GetNext(), the non-spiffy decode API,
-the proper tag form is automatically recognized by the tag number and
-decoded into QCBORItem. This decoding API however cannot recognize
-borrowed content format. The caller must tell QCBOR when borrowed
-content format is expected.
+These APIs and structures support both the full tag form and the
+borrowed content form that is not a tag. An argument of type @ref xxx
+and @ref QCBORDecodeTagReq is provided respectively to the tag encode
+and decode functions to distinguish between full tags and borrowed
+content.
 
-The spiffy decode APIs for the particular tags are the way the caller
-tells QCBOR to expect borrowed content format. These spiffy decode
-APIs can also decode the proper tag as well. When asked to decode a
-proper tag and the input CBOR is not, it is a decode validity
-error. These APIs take an argument which says whether to expect the
-proper tag or just the borrowed content. They can also be told to
-allow either to "be liberal in what you accept", but this is not
-recommended.
+Early versions of QCBOR do not support encoding borrowed content. The
+old APIs for dates, big numbers and such are listed as deprecated, but
+will continue to be supported. The encode side has functions like
+QCBOREncode_AddDateEpoch() rather than
+QCBOREncode_AddTDateEpoch(). The tag decode APIs always supported
+borrowed content.
+
+Last, QCBORDecode_InstallTagDecoders() allows callbacks to be
+installed that will fire on a particular tag number. These callbacks
+decode the tag content and put it into a QCBORItem with a new QCBOR
+data type. The decoded tags show up as a @ref QCBORItem fetched by
+QCBORDecode_VGetNext().
+
+A set of callbacks called @ref QCBORDecode_TagDecoderTablev1 is
+provided for all the standard tags from RFC 8949. These are not
+automatically installed in QCBOR v2. These were built into QCBOR v1.
 
 
 ## Nested Tags
@@ -117,8 +146,9 @@
 encloses another, the enclosed tag is the content for the enclosing
 tag.
 
-Encoding nested tags is easy with QCBOREncode_AddTagNumber(). Just call it
-several times before calling the functions to encode the tag content.
+Encoding nested tags is easy with QCBOREncode_AddTagNumber(). Just
+call it several times before calling the functions to encode the tag
+content.
 
 When QCBOR decodes tags it does so by first completely processing the
 built-in tags that it knows how to process. It returns that processed
@@ -144,6 +174,7 @@
 the decode context and have to be fetched with
 QCBORDecode_GetNthTagOfLast().
 
+
 ## Tags for Encapsulated CBOR
 
 Tag 24 and 63 deserve special mention. The content of these tags is a
@@ -154,7 +185,7 @@
 either a map or an array or a tag that defined to be complex and
 nested. With tag 63, the content can be a sequence of integers not
 held together in a map or array. Tag 63 is defined in
-[RFC 8742] (https://tools.ietf.org/html/rfc8742).
+[RFC 8742](https://tools.ietf.org/html/rfc8742).
 
 The point of encapsulating CBOR this way is often so it can be
 cryptographically signed. It works well with off-the-shelf encoders
@@ -190,6 +221,7 @@
 payload is known to contain CBOR, like the case of a CWT, then QCBOR's
 QCBORDecode_EnterBstrWrapped() can be used to decode it.
 
+
 ## Tags that Can be Ignored
 
 There are a few specially defined tags that can actually be
@@ -216,98 +248,16 @@
 ## Standard Tags and the Tags Registry
 
 Tags used in CBOR protocols should at least be registered in the
-[IANA CBOR Tags Registry] (https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml).
-A small number of tags (0-23), are full IETF standards. Further, tags
-24-255 require published documentation, but are not full IETF
-standards. Beyond tag 255, the tags are first come first served.
+[IANA CBOR Tags Registry](https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml).
+A small number of tags (0-23), must be full IETF standards. Tags
+24-255 require published documentation. Beyond tag 255, the tags are
+first come first served.  Any tag can be an IETF standard if the
+authors chooses to take it through the process.
 
 There is no range for private use, so any tag used in a CBOR protocol
 should be registered. The range of tag values is very large to
 accommodate this.
 
-As described above, It is common to use data types from the registry
-in a CBOR protocol without the explicit tag, so in a way the registry
-is a registry of data types.
-
-
-
-## Tag Decoding
-
-QCBOR offers two ways to decoding tags.
-
-The first is by registering a call back that can transform the tag into
-a QCBORItem itendified by a new QCBOR Type. It is limited in that
-the decoded data must fit into the 24 bytes of a QCBORItem values. It is
-good for new data types.
-
-The second is by getting tag numbers in the course of decoding. This 
-is more suitable for tags numbers that indicate message types, those
-that alter the decode flow.
-
-QCBOR v2 (when not in v1 compatibility) requires all tags be consumed.
-If they are not consumed by one of the above methods, xxxx error occurs.
-They are never optional (as they were described in RFC 7049) just is
-it is not optional to ignore whether an item is a string rather than
-an integer.
-
-In v2
-
-TODO: make clean this up
-
-When asking for specific tag decode, for example GetDateEpoch()
-
-Tag required
- - No tag gives error xxxx
- - The epoch date tag by itself succeeds
- - The epoch date tag with wrong content gives error yyy
- - The epoch date tag with additional
- - The additional have been consumed -- suceeds
- - The aditional tags have not been consumed -- gives error aaa
- - Another tag gives --- error zzz
- 
- Tag not required
- - No tags, correct tag content -- success
- - No tags, incorrect tag content type error yyy
- - Another tag, not consumed ---  error aaa
- - Another tag consumed -- success
- - Another tag consumed and made into another type --- error xxxx
- 
- Tag optional
- - No tags, correct content -- success
- - No tags, incorrect content -- error yyy
- - Expected tag -- success
- - Another tag, consumed -- success
- - Another tag, not consumed tag content correct -- error, probably aaa
- - Another tag, consumed and made into another type -- error xxx
- - Expected tag + another tag, not consumed -- error aaa
- 
- 
- Now fan out for ALLOW_EXTRA --- yuckkkkk
- 
- Ignore ALLOW_EXTRA in v2?
- 
- Fan out for v1
- 
- 
- 
- 
- 0(140) good date tag
- 50000(140) 
-    interpret as a date with some other tag on it -- must be consumed, so unconsumed tag error
-    intepret this as not a date -- wrong type error
-    subjective depending on whether tag content decoder is installed
- 1(140) same as above
- 
- Tag optional
-
-
-
-
-
-
-## See Also
-
-See @ref Tags-Overview and @ref Tag-Usage.
-
-
-
+As described above, it is common to use data types from the registry
+in a CBOR protocol without the explicit tag, to borrow the content, so
+in a way the IANA registry is a registry of data types.
diff --git a/doc/mainpage.dox b/doc/mainpage.dox
index 18c27f8..2a723ce 100644
--- a/doc/mainpage.dox
+++ b/doc/mainpage.dox
@@ -3,13 +3,28 @@
 @par Table of Contents
 
 API Reference
-- Encoding functions: @ref inc/qcbor/qcbor_encode.h "qcbor_encode.h"
-- Main/Basic decode functions: @ref inc/qcbor/qcbor_main_decode.h "qcbor_main_decode.h"
-- Spiffy decode functions: @ref inc/qcbor/qcbor_spiffy_decode.h "qcbor_spiffy_decode.h"
-- Tag decode functions: @ref inc/qcbor/qcbor_tag_decode.h "qcbor_tag_decode.h"
-- Number decode functions: @ref inc/qcbor/qcbor_number_decode.h "qcbor_number_decode.h"
+- Common
+   - Error codes and common constants: @ref inc/qcbor/qcbor_common.h "qcbor_common.h"
+- Encoding
+   - Main/Basic encode functions: @ref inc/qcbor/qcbor_main_encode.h "qcbor_main_encode.h"
+   - Number encode functions: @ref inc/qcbor/qcbor_number_encode.h "qcbor_number_encode.h"
+   - Tag encode functions: @ref inc/qcbor/qcbor_tag_encode.h "qcbor_tag_encode.h"
+- Decoding
+   - Main/Basic decode functions: @ref inc/qcbor/qcbor_main_decode.h "qcbor_main_decode.h"
+   - Spiffy decode functions: @ref inc/qcbor/qcbor_spiffy_decode.h "qcbor_spiffy_decode.h"
+   - Tag decode functions: @ref inc/qcbor/qcbor_tag_decode.h "qcbor_tag_decode.h"
+   - Number decode functions: @ref inc/qcbor/qcbor_number_decode.h "qcbor_number_decode.h"
+
+Note: the API Reference is largely complete, the subject matter below is partial
 
 Subject Matter
-- @ref SpiffyDecode
+- @ref Overview "QCBOR overview and implementation limits"
+- @ref Building "Building QCBOR with make and cmake"
+- @ref CodeSize "Minimizing the amount of code linked and disabling features"
+- @ref SpiffyDecode "The 'spiffy' decode functions for easier map decoding"
+- CBOR Numbers
+   - @ref BigNumbers "Characteristics, encoding and decoding big numbers"
+- Tags
+   - @ref CBORTags
 
 */
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index fdc5d3a..b6fbdd1 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -47,8 +47,8 @@
 /**
  * @file qcbor_common.h
  *
- * Constant values for types, error codes and such that are common to
- * encoding and decoding.
+ * qcbor_common.h contains error codes and constant values that are
+ * common between encoding and decoding.
  */
 
 
@@ -458,11 +458,8 @@
 #define QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS 59
 
    /** More than @ref QCBOR_MAX_TAGS_PER_ITEM tags encountered for a
-    *  CBOR ITEM.  @ref QCBOR_MAX_TAGS_PER_ITEM is a limit of this
-    *  implementation.  During decoding, too many tags in the
-    *  caller-configured tag list, or not enough space in
-    *  @ref  QCBORTagListOut. This error makes no further decoding
-    *  possible.  */
+    *  CBOR Item.  @ref QCBOR_MAX_TAGS_PER_ITEM is a limit of this
+    *  implementation. x  */
    QCBOR_ERR_TOO_MANY_TAGS = 60,
 
    /** When decoding for a specific type, the type was not expected.  */
@@ -567,14 +564,14 @@
     * a @ref QCBORStringAllocate. */
    QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING = 81,
 
-   /* Can't output a negative zero big num */
+   /** Can't output a negative zero big num */
    QCBOR_ERR_NO_NEGATIVE_ZERO = 87,
 
    /** An unconsumed tag number was encountered. */
    QCBOR_ERR_UNEXPECTED_TAG_NUMBER = 89, // TODO: rid of this in favor of below?
 
    /** In QCBOR v2, tag numbers must be processed by QCBORDecode_GetNextTagNumber().
-    * See @ref QCBOR_DECODE_CONFIG_UNPROCESSED_TAG_NUMBERS. */
+    * See @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS. */
    QCBOR_ERR_UNPROCESSED_TAG_NUMBER = 90,
 
    /** A range of error codes that can be made use of by the
diff --git a/inc/qcbor/qcbor_main_decode.h b/inc/qcbor/qcbor_main_decode.h
index b502431..8f3e487 100644
--- a/inc/qcbor/qcbor_main_decode.h
+++ b/inc/qcbor/qcbor_main_decode.h
@@ -109,7 +109,7 @@
  * an error will be returned.
  *
  * This new behavior saves the caller from having to do this check
- * (that they probably didn't know they neeeded).  It is much more
+ * (that they probably didn't know they neeeded).  It is more
  * correct behavior.
  *
  * This behavior is not backwards compatible with v1. The v1 behavior
@@ -190,24 +190,6 @@
  * item being sought, in which case the unrecoverable error will be
  * returned. Unrecoverable errors are those indicated by
  * QCBORDecode_IsUnrecoverableError().
- *
- * @anchor Disabilng-Tag-Decoding
- * # Disabilng Tag Decoding
- *
- * TODO: update this
- * If QCBOR_DISABLE_TAGS is defined, all code for decoding tags will
- * be omitted reducing the core decoder, QCBORDecode_VGetNext(), by
- * about 400 bytes. If a tag number is encountered in the decoder
- * input the unrecoverable error @ref QCBOR_ERR_TAGS_DISABLED will be
- * returned.  No input with tags can be decoded.
- *
- * Decode functions like QCBORDecode_GetEpochDate() and
- * QCBORDecode_GetDecimalFraction() that can decode the tag content
- * even if the tag number is absent are still available.  Typically
- * they won't be linked in because of dead stripping. The
- * @c uTagRequirement parameter has no effect, but if it is
- * @ref QCBOR_TAG_REQUIREMENT_TAG, @ref QCBOR_ERR_TAGS_DISABLED
- * will be set.
  */
 
 
@@ -366,7 +348,7 @@
  *  @ref  CBOR_TAG_NEG_BIGNUM. */
 #define QCBOR_TYPE_NEGBIGNUM     10
 
-/** Type for [RFC 3339] (https://tools.ietf.org/html/rfc3339) date
+/** Type for [RFC 3339](https://tools.ietf.org/html/rfc3339) date
  *  string, possibly with time zone. Data is in @c val.string . Note this
  *  was previously in @c val.dateString, however this is the same as
  *  val.string being the same type in same union. val.dateString will
@@ -699,7 +681,7 @@
    /**
     * PRIVATE MEMBER
     * Use  QCBORDecode_GetNthTagNumber() to retrieve tag numbers on an item.
-    * Also see @ref Tags-Overview.
+    * Also see @ref CBORTags
     *
     * In QCBOR v1 this was named uTags and was in the reverse order.
     * It wasn't explicitly described as private, but was implicitly private.
@@ -927,8 +909,8 @@
  *
  * - @c uDataType which indicates which member of the @c val union the
  *   data is in. This decoder figures out the type based on the CBOR
- *   major type, the CBOR "additionalInfo", the CBOR optional tags and
- *   the value of the integer.
+ *   major type, the CBOR "additionalInfo", and sometimes by
+ *   preceding tag numbers.
  *
  * - The value of the item, which might be an integer, a pointer and a
  *   length, the count of items in an array, a floating-point number or
@@ -939,7 +921,7 @@
  * - The label for an item in a map, which may be a text or byte string
  *   or an integer.
  *
- * - The unprocessed tag numbers for which the item is the tag content.
+ * - When @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS is set,  unprocessed tag numbers.
  *
  * See @ref QCBORItem for all the details about what is returned.
  *
@@ -1005,8 +987,6 @@
  * array. For indefinite-length arrays, @c QCBORItem.val.uCount
  * is @c UINT16_MAX.
  *
- * See extensive discussion in @ref Tag-Decoding.
- *
  * See [Decode Error Overview](#Decode-Errors-Overview).
  *
  * If a decoding error occurs or previously occured, @c uDataType and
@@ -1180,7 +1160,7 @@
  * at the next item to be decoded as expected.
  *
  * There are some special rules for the traversal cursor when fetching
- * map items by label. See the description of @SpiffyDecode.
+ * map items by label. See the description of @ref SpiffyDecode.
  *
  * When traversal is bounded because an array or map has been entered
  * (e.g., QCBORDecode_EnterMap()) and all items in the array or map
@@ -1242,8 +1222,9 @@
  * use. Because of this, It can't be called multiple times like
  * QCBORDecode_PartialFinish().
  *
- * Some CBOR protocols use a CBOR sequence defined in [RFC 8742]
- * (https://tools.ietf.org/html/rfc8742). A CBOR sequence typically
+ * Some CBOR protocols use a CBOR sequence defined in 
+ * [RFC 8742](https://tools.ietf.org/html/rfc8742).
+ * A CBOR sequence typically
  * doesn't start out with a map or an array. The end of the CBOR is
  * determined in some other way, perhaps by external framing, or by
  * the occurrence of some particular CBOR data item or such. The
diff --git a/inc/qcbor/qcbor_main_encode.h b/inc/qcbor/qcbor_main_encode.h
index 9b4396d..a87f9a0 100644
--- a/inc/qcbor/qcbor_main_encode.h
+++ b/inc/qcbor/qcbor_main_encode.h
@@ -51,117 +51,6 @@
 /**
  * @file qcbor_main_encode.h
  *
- * @anchor Overview
- *
- * # QCBOR Overview
- *
- * This implements CBOR -- Concise Binary Object Representation as
- * defined in [RFC 8949] (https://www.rfc-editor.org/rfc/rfc8949.html).
- * More information is at http://cbor.io.  This is a near-complete
- * implementation of the specification. [RFC 8742]
- * (https://www.rfc-editor.org/rfc/rfc8742.html) CBOR Sequences is
- * also supported. Limitations are listed further down.
- *
- * See @ref Encoding for general discussion on encoding,
- * @ref BasicDecode for general discussion on the basic decode features
- * and @ref SpiffyDecode for general discussion on the easier-to-use
- * decoder functions.
- *
- * CBOR is intentionally designed to be translatable to JSON, but not
- * all CBOR can convert to JSON. See RFC 8949 for more info on how to
- * construct CBOR that is the most JSON friendly.
- *
- * The memory model for encoding and decoding is that encoded CBOR must
- * be in a contiguous buffer in memory.  During encoding the caller must
- * supply an output buffer and if the encoding would go off the end of
- * the buffer an error is returned.  During decoding the caller supplies
- * the encoded CBOR in a contiguous buffer and the decoder returns
- * pointers and lengths into that buffer for strings.
- *
- * This implementation does not require malloc. All data structures
- * passed in/out of the APIs can fit on the stack.
- *
- * Decoding of indefinite-length strings is a special case that requires
- * a "string allocator" to allocate memory into which the segments of
- * the string are coalesced. Without this, decoding will error out if an
- * indefinite-length string is encountered (indefinite-length maps and
- * arrays do not require the string allocator). A simple string
- * allocator called MemPool is built-in and will work if supplied with a
- * block of memory to allocate. The string allocator can optionally use
- * malloc() or some other custom scheme.
- *
- * Here are some terms and definitions:
- *
- * - "Item", "Data Item": An integer or string or such. The basic "thing" that
- * CBOR is about. An array is an item itself that contains some items.
- *
- * - "Array": An ordered sequence of items, the same as JSON.
- *
- * - "Map": A collection of label/value pairs. Each pair is a data
- * item. A JSON "object" is the same as a CBOR "map".
- *
- * - "Label": The data item in a pair in a map that names or identifies
- * the pair, not the value. This implementation refers to it as a
- * "label".  JSON refers to it as the "name". The CBOR RFC refers to it
- * this as a "key".  This implementation chooses label instead because
- * key is too easily confused with a cryptographic key. The COSE
- * standard, which uses CBOR, has also chosen to use the term "label"
- * rather than "key" for this same reason.
- *
- * - "Key": See "Label" above.
- *
- * - "Tag": A data item that is an explicitly labeled new data
- * type made up of the tagging integer and the tag content.
- * See @ref Tags-Overview and @ref Tag-Usage.
- *
- * - "Initial Byte": The first byte of an encoded item. Encoding and
- * decoding of this byte is taken care of by the implementation.
- *
- * - "Additional Info": In addition to the major type, all data items
- * have some other info. This is usually the length of the data but can
- * be several other things. Encoding and decoding of this is taken care
- * of by the implementation.
- *
- * CBOR has two mechanisms for tagging and labeling the data values like
- * integers and strings. For example, an integer that represents
- * someone's birthday in epoch seconds since Jan 1, 1970 could be
- * encoded like this:
- *
- * - First it is CBOR_MAJOR_TYPE_POSITIVE_INT (@ref QCBOR_TYPE_INT64),
- * the primitive positive integer.
- *
- * - Next it has a "tag" @ref CBOR_TAG_DATE_EPOCH indicating the integer
- * represents a date in the form of the number of seconds since Jan 1,
- * 1970.
- *
- * - Last it has a string "label" like "BirthDate" indicating the
- * meaning of the data.
- *
- * The encoded binary looks like this:
- *
- *      a1                      # Map of 1 item
- *         69                   # Indicates text string of 9 bytes
- *           426972746844617465 # The text "BirthDate"
- *        c1                    # Tags next integer as epoch date
- *           1a                 # Indicates a 4-byte integer
- *               580d4172       # unsigned integer date 1477263730
- *
- * Implementors using this API will primarily work with
- * labels. Generally, tags are only needed for making up new data
- * types. This implementation covers most of the data types defined in
- * the RFC using tags. It also, allows for the use of custom tags if
- * necessary.
- *
- * This implementation explicitly supports labels that are text strings
- * and integers. Text strings translate nicely into JSON objects and are
- * very readable.  Integer labels are much less readable but can be very
- * compact. If they are in the range of 0 to 23, they take up only one
- * byte.
- *
- * CBOR allows a label to be any type of data including an array or a
- * map. It is possible to use this API to construct and parse such
- * labels, but it is not explicitly supported.
- *
  * @anchor Encoding
  *
  * ## Encoding
@@ -224,10 +113,10 @@
  *
  * Many CBOR-based protocols start with an array or map. This makes
  * them self-delimiting. No external length or end marker is needed to
- * know the end. It is also possible not start this way, in which case
+ * know the end. It is also possible to not start this way, in which case
  * this it is usually called a CBOR sequence which is described in
- * [RFC 8742] (https://www.rfc-editor.org/rfc/rfc8742.html). This
- * encoder supports either just by whether the first item added is an
+ * [RFC 8742](https://www.rfc-editor.org/rfc/rfc8742.html).
+ * This encoder supports either just by whether the first item added is an
  * array, map or other.
  *
  * If QCBOR is compiled with QCBOR_DISABLE_ENCODE_USAGE_GUARDS defined,
@@ -242,37 +131,6 @@
  * disable these checks. Bounds checking that prevents security issues
  * in the code is still enforced. This define reduces the size of
  * encoding object code by about 150 bytes.
- *
- * ## Limitations
- *
- * Summary limitations:
- * - The entire encoded CBOR must fit into contiguous memory.
- * - Max size of encoded CBOR data is a few bytes less than
- *   @c UINT32_MAX (4GB).
- * - Max array / map nesting level when encoding or decoding is
- *   @ref QCBOR_MAX_ARRAY_NESTING (this is typically 15).
- * - Max items in an array or map when encoding or decoding is
- *   @ref QCBOR_MAX_ITEMS_IN_ARRAY (typically 65,536).
- * - Does not directly support labels in maps other than text strings & integers.
- * - Traversal, duplicate and sort order checking errors out for labels that are arrays or maps.
- * - Does not directly support integer labels beyond whats fits in @c int64_t
- *   or @c uint64_t.
- * - Epoch dates limited to @c INT64_MAX (+/- 292 billion years).
- * - Exponents for bigfloats and decimal integers are limited to whats fits in
- *   @c int64_t.
- * - Tags on labels are ignored during decoding.
- * - The maximum tag nesting is @c QCBOR_MAX_TAGS_PER_ITEM (typically 4).
- * - Works only on 32- and 64-bit CPUs.
- * - QCBORDecode_EnterBstrWrapped() doesn't work on indefinite-length strings.
- *
- * The public interface uses @c size_t for all lengths. Internally the
- * implementation uses 32-bit lengths by design to use less memory and
- * fit structures on the stack. This limits the encoded CBOR it can
- * work with to size @c UINT32_MAX (4GB).
- *
- * This implementation requires two's compliment integers. While
- * C doesn't require two's compliment,  <stdint.h> does. Other
- * parts of this implementation may also require two's compliment.
  */
 
 
@@ -285,19 +143,6 @@
 #define QCBOR_HEAD_BUFFER_SIZE  (sizeof(uint64_t) + 2)
 
 
-/**
- * Output the full CBOR tag. See @ref CBORTags, @ref Tag-Usage and
- * @ref Tags-Overview.
- */
-#define QCBOR_ENCODE_AS_TAG      0
-
-/**
- * Output only the 'borrowed' content format for the relevant tag.
- * See @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
- */
-#define QCBOR_ENCODE_AS_BORROWED 1
-
-
 
 /**
  * This enum is the bit flags for configuring the encoder for things
@@ -574,8 +419,8 @@
  * @param[in] Text   Pointer and length of text to add.
  *
  * The text passed in must be unencoded UTF-8 according to
- * [RFC 3629] (https://www.rfc-editor.org/rfc/rfc3629.html). There is
- * no NULL termination. The text is added as CBOR major type 3.
+ * [RFC 3629](https://www.rfc-editor.org/rfc/rfc3629.html). There is
+ * no @c NULL termination. The text is added as CBOR major type 3.
  *
  * If called with @c nBytesLen equal to 0, an empty string will be
  * added. When @c nBytesLen is 0, @c pBytes may be @c NULL.
@@ -806,7 +651,7 @@
  * @param[in] uNum   The simple value.
  *
  * QCBOREncode_AddBool(), QCBOREncode_AddUndef() and
- * QCBOREncode_AddNull() are preferred to this for the simple values
+ * QCBOREncode_AddNULL() are preferred to this for the simple values
  * defined in RFC 8949, but this can be used for them too.
  *
  * The main purpose of this is to add simple values beyond those in
@@ -933,7 +778,7 @@
  * text strings, then just call the QCBOREncode_AddXxx() function
  * explicitly to add the label. Then call it again to add the value.
  *
- * See the [RFC 8949] (https://www.rfc-editor.org/rfc/rfc8949.html)
+ * See the [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html)
  * for a lot more information on creating maps.
  */
 static void
@@ -1085,8 +930,9 @@
  * contain encoded CBOR. This increases nesting level by one.
  *
  * The typical use case is for encoded CBOR that is to be
- * cryptographically hashed, as part of a [RFC 9052, COSE]
- * (https://www.rfc-editor.org/rfc/rfc9052.html) implementation. The
+ * cryptographically hashed, as part of a
+ * [RFC 9052, COSE](https://www.rfc-editor.org/rfc/rfc9052.html)
+ * implementation. The
  * wrapping byte string is taken as input by the hash function (which
  * is why it is returned by QCBOREncode_CloseBstrWrap2()).  It is also
  * easy to recover on decoding with standard CBOR decoders.
@@ -1131,7 +977,7 @@
  * A pointer and length of the enclosed encoded CBOR is returned in @c
  * *pWrappedCBOR if it is not @c NULL. The main purpose of this is so
  * this data can be hashed (e.g., with SHA-256) as part of a
- * [RFC 9052, COSE] (https://www.rfc-editor.org/rfc/rfc9052.html)
+ * [RFC 9052, COSE](https://www.rfc-editor.org/rfc/rfc9052.html)
  * implementation. **WARNING**, this pointer and length should be used
  * right away before any other calls to @c QCBOREncode_CloseXxx() as
  * they will move data around and the pointer and length will no
diff --git a/inc/qcbor/qcbor_number_decode.h b/inc/qcbor/qcbor_number_decode.h
index 7031bfd..5ea7597 100644
--- a/inc/qcbor/qcbor_number_decode.h
+++ b/inc/qcbor/qcbor_number_decode.h
@@ -651,7 +651,7 @@
  *
  * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
  *
- * See @ref Tag-Usage for discussion on tag requirements.
+ * See @ref QCBORDecodeTagReq for discussion on tag requirements.
  */
 void
 QCBORDecode_GetTBigNumber(QCBORDecodeContext    *pCtx,
@@ -811,7 +811,7 @@
  *
  * Depending on @c uTagRequirement, the tag number
  * @ref CBOR_TAG_DECIMAL_FRACTION (4) may or may not need to be
- * present before the array. See @ref Tag-Usage.
+ * present before the array. See @ref QCBORDecodeTagReq.
  *
  * The exponent must always be an integer (CBOR type 0 or 1). The
  * mantissa may be an integer or a big number. If it is a big number,
@@ -998,7 +998,7 @@
  *
  * Depending on @c uTagRequirement, the tag number
  * @ref CBOR_TAG_BIGFLOAT (5) may or may not need to be present
- * before the array. See @ref Tag-Usage.
+ * before the array. See @ref QCBORDecodeTagReq.
  *
  * The exponent must always be an integer (CBOR type 0 or 1). The
  * mantissa may be an integer or a big number. If it is a big number,
diff --git a/inc/qcbor/qcbor_number_encode.h b/inc/qcbor/qcbor_number_encode.h
index 783b832..6c7fa4d 100644
--- a/inc/qcbor/qcbor_number_encode.h
+++ b/inc/qcbor/qcbor_number_encode.h
@@ -131,20 +131,6 @@
 #define QCBOR_HEAD_BUFFER_SIZE  (sizeof(uint64_t) + 2)
 
 
-/**
- * Output the full CBOR tag. See @ref CBORTags, @ref Tag-Usage and
- * @ref Tags-Overview.
- */
-#define QCBOR_ENCODE_AS_TAG      0
-
-/**
- * Output only the 'borrowed' content format for the relevant tag.
- * See @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
- */
-#define QCBOR_ENCODE_AS_BORROWED 1
-
-
-
 
 /**
  * @brief  Add a signed 64-bit integer to the encoded output.
@@ -169,11 +155,11 @@
  * represent the value.  For example, CBOR always encodes the value 0
  * as one byte, 0x00. The representation as 0x00 includes
  * identification of the type as an integer too as the major type for
- * an integer is 0. See [RFC 8949 Appendix A]
- * (https://www.rfc-editor.org/rfc/rfc8949.html#section-appendix.a)
+ * an integer is 0. See 
+ * [RFC 8949 Appendix A](https://www.rfc-editor.org/rfc/rfc8949.html#section-appendix.a)
  * for more examples of CBOR encoding. This compact encoding is
- * preferred serialization CBOR as per [RFC 8949 section 4.1]
- * (https://www.rfc-editor.org/rfc/rfc8949.html#section-4.1)
+ * preferred serialization CBOR as per
+ * [RFC 8949 section 4.1](https://www.rfc-editor.org/rfc/rfc8949.html#section-4.1)
  *
  * There are no functions to add @c int16_t or @c int32_t because they
  * are not necessary because this always encodes to the smallest
@@ -314,7 +300,7 @@
  *
  * By default, this will error out on an attempt to encode a NaN with
  * a payload. See QCBOREncode_Allow() and @ref
- * QCBOR_ENCODE_ALLOW_NAN_PAYLOAD.
+ * QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD.
  * If preferred serialization is disabled at compliation, this check for
  * for NaN payloads is disabled.
  */
@@ -510,8 +496,8 @@
  *                             byte order).
  *
  * This encodes CBOR tag numbers 2 and 3, positive and negative big
- * numbers, as defined in [RFC 8949 section 3.4.3]
- * (https://www.rfc-editor.org/rfc/rfc8949.html#section-3.4.3).
+ * numbers, as defined in 
+ * [RFC 8949 section 3.4.3](https://www.rfc-editor.org/rfc/rfc8949.html#section-3.4.3).
  *
  * This performs the offset of one required when encoding negative
  * numbers.
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 903f68e..f79c256 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -109,6 +109,13 @@
  * quantified). One way ease this is to use
  * QCBORDecode_GetItemsInMap() which allows decoding of a list of
  * items expected in an map in one traveral.
+ *
+ * * Map searching works with indefinite length strings. A string
+ * allocator must be set up the same as for any handling of indefinite
+ * length strings.  However, It currently over-allocates memory from the
+ * string pool and thus requires a much larger string pool than it
+ * should. The over-allocation happens every time a map is searched by
+ * label.  (This may be corrected in the future).
  */
 
 
@@ -594,7 +601,7 @@
  * every pItemList.auTagNumbers is empty or has tag numbers that are
  * expected. While tag numbers were once described as "optional",
  * they really do have critical information that should not be ignored.
- * See @ref Tag-Decoding
+ * See @ref TagDecoding
  *
  * This function works well with tag content decoders as described in
  * QCBORDecode_InstallTagDecoders().
diff --git a/inc/qcbor/qcbor_tag_decode.h b/inc/qcbor/qcbor_tag_decode.h
index 32dd1f5..b6b5dce 100644
--- a/inc/qcbor/qcbor_tag_decode.h
+++ b/inc/qcbor/qcbor_tag_decode.h
@@ -26,106 +26,135 @@
 /**
  * @file qcbor_tag_decode.h
  *
- * This file defines the interface for tag decoders that turn tags
- * into custom QCBORItems with custom user-defined CBOR_TYPEs using
- * callbacks.
+ * @anchor TagDecoding
+ * ## Tag Decoding
  *
- * This also gives function prototypes for callbacks that are supplied
- * for standard CBOR data types like dates and big numbers.
+  * See @ref CBORTags first if you are unfamiliar with the notion of
+ * tags in CBOR.
  *
- * This is one of two main facilities for handling tags in CBOR. The
- * other is QCBORDecode_GetNextTagNumber().
+ * QCBOR v2 offers several ways to decode tags.
  *
- * This file is new in QCBOR v2.
+ * One is by registering a call back that can transform the tag into a
+ * @ref QCBORItem identified by a new QCBOR type, perhaps in the range
+ * starting with @ref QCBOR_TYPE_START_USER_DEFINED. It is limited in
+ * that the decoded data must fit into the 24 bytes of a QCBORItem
+ * value. It is good for simple new data types. See
+ * QCBORTagContentCallBack()
  *
- * @anchor Tag-Decoding
+ * Another is by getting (consuming) tag numbers in the course of
+ * decoding. This is more suitable for tags numbers that indicate
+ * message types, those that alter the decode flow. See
+ * QCBORDecode_VGetNextTagNumber().
  *
- * ## Tags Decoding
+ * QCBOR offers specific functions to decode the standard tags such as
+ * epoch dates and big numbers. One form of these is call backs that
+ * can be installed such as QCBORDecode_DateEpochTagCB(). Another is
+ * spiffy decode style QCBORDecode_GetXxx() functions like
+ * QCBORDecode_GetDateString()
  *
- * TODO: lots to write here
+ * QCBOR v2 (when not in v1 compatibility) requires all tags be
+ * consumed.  If they are not consumed by one of the above methods,
+ * @ref QCBOR_ERR_UNPROCESSED_TAG_NUMBER error occurs.  They are never
+ * optional (as they were described in RFC 7049) just is it is not
+ * optional to ignore whether an item is a string rather than an
+ * integer.
  *
- *  * @anchor Tag-Usage
- * ## Tag Usage
+ * ### QCBOR v2 tag decoding compared to v1
  *
- * Data types beyond the basic CBOR types of numbers, strings, maps and
- * arrays are called tags. The main registry of these new types is in
- * the IANA CBOR tags registry. These new types may be simple such a
- * number that is to be interpreted as a date, or of moderate complexity
- * such as defining a decimal fraction that is an array containing a
- * mantissa and exponent, or complex such as format for signing and
- * encryption.
+ * Thorough CBOR decoding requires that tag numbers not be
+ * ignored. Tag numbers fundamentally change the type of an item.
+ * QCBOR v1 does not support this well. It neatly put all the tag
+ * numbers on an item in the @ref QCBORItem, but left it up to the
+ * caller to check that every QCBORItem had no tag numbers on it. It
+ * is likely that protocol implementors rarely performed this check.
+ * For the most part this is tolerable, but it really isn't proper and
+ * thorough decoding.
  *
- * When a tag occurs in a protocol it is encoded as an integer tag
- * number plus the content of the tag.
+ * Also, spiffy decode methods like QCBORDecode_GetInt64() saved
+ * associated tag numbers so they could be fetched with
+ * QCBORDecode_GetNthTagNumberOfLast(), but did nothing more.
  *
- * The content format of a tag may also be "borrowed". For example, a
- * protocol definition may say that a particular data item is an epoch
- * date just like tag 1, but not actually tag 1. In practice the
- * difference is the presence or absence of the integer tag number in
- * the encoded CBOR.
+ * QCBOR v2 behaves different. It errors out if all tag numbers are
+ * not consumed.
  *
- * The decoding functions for these new types takes a tag requirement
- * parameter to say whether the item is a tag, is just borrowing the
- * content format and is not a tag, or whether either is OK.
+ * Most applications that worked correclty with v1 will work with
+ * v2. Decoding will become appropriately more thorough.
  *
- * If the parameter indicates the item must be a tag (@ref
- * QCBOR_TAG_REQUIREMENT_TAG), then @ref QCBOR_ERR_UNEXPECTED_TYPE is
- * set if it is not one of the expected tag types. To decode correctly
- * the contents of the tag must also be of the correct type. For
- * example, to decode an epoch date tag the content must be an integer
- * or floating-point value.
+ * If an application relied on the v1 behavior, it can be restored
+ * with the configuration @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS.
+
+ * Before QCBOR v1.5, the GetString decode functions would error
+ * out if preceeded by a tag number. This was unlike all the other
+ * Get() functions that queitly decoded the tag numbers and
+ * included them in the QCBORItem. The getString functions
+ * were modified by v1.5 so they were more liberal like
+ * the other Get functions.  This is only of note between
+ * QCBOR v1.5 and what came before it, not fo QCBOR v2.
+ * QCBOR v2 in compatibility mode behaves like QCBOR v1.5.
  *
- * If the parameter indicates it should not be a tag
- * (@ref  QCBOR_TAG_REQUIREMENT_NOT_A_TAG), then
- *  @ref QCBOR_ERR_UNEXPECTED_TYPE set if it is a tag or the type of the
- * encoded CBOR is not what is expected.  In the example of an epoch
- * date, the data type must be an integer or floating-point value. This
- * is the case where the content format of a tag is borrowed.
+ * @anchor Disabilng-Tag-Decoding
+ * ## Disabling Tag Decoding
  *
- * The parameter can also indicate that either a tag or no tag is
- * allowed ( @ref QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG ).  A good protocol
- * design should however be clear and choose one or the other and not
- * need this option. This is a way to implement "be liberal in what you
- * accept", however these days that is less in favor. See
- * https://tools.ietf.org/id/draft-thomson-postel-was-wrong-03.html.
+ * If @ref QCBOR_DISABLE_TAGS is defined, all code for decoding tags
+ * will be omitted reducing the core decoder, QCBORDecode_VGetNext(),
+ * by about 500 bytes. If a tag number is encountered in the decoder
+ * input the unrecoverable error @ref QCBOR_ERR_TAGS_DISABLED will be
+ * returned.  No input with tags can be decoded.
  *
- * Map searching works with indefinite length strings. A string
- * allocator must be set up the same as for any handling of indefinite
- * length strings.  However, It currently over-allocates memory from the
- * string pool and thus requires a much larger string pool than it
- * should. The over-allocation happens every time a map is searched by
- * label.  (This may be corrected in the future).
- *
- *
- * TODO: this text isn't right
- * In v1, some spiffy decode functions ignored tag numbers and
- * some didn't.  For example, GetInt64 ignored and GetString didn't.
- * The "GetXxx" where Xxxx is a tag ignore conditionally based
- * on an argument.
- * (Would be good to verify this with tests)
- *
- * Do we fix the behavior of GetString in v1?  Relax so it
- * allows tag numbers like the rest? Probably.
- *
- * In v2, the whole mechanism is with GetTagNumbers. They are
- * never ignored and they must always be consumed.
- *
- * With v2 in v1 mode, the functions that were ignoring
- * tags must go back to ignoring them.
- *
- * How does TagRequirement work in v2?
- *
- * GetInt64 and GetString require all tag numbs to be processed
- * to work.
+ * Decode functions like QCBORDecode_GetEpochDate() and
+ * QCBORDecode_GetDecimalFraction() are still available, but only work
+ * on "borrowed" tag content.  When they are called with tags
+ * disabled, the @c uTagRequirement parameter should be
+ * @ref QCBOR_TAG_REQUIREMENT_NOT_A_TAG.
  */
 
+
+/*
+This describes the fan out of use cases for spiffy style tag decoding
+ in detail.
+
+TODO:  make sure this full fan out is tested
+TODO: perhaps incorporate some of this into documentation
+
+When asking for specific tag decode, for example GetDateEpoch()
+
+Tag required
+ - No tag gives error xxxx
+ - The epoch date tag by itself succeeds
+ - The epoch date tag with wrong content gives error yyy
+ - The epoch date tag with additional
+ - The additional have been consumed -- suceeds
+ - The aditional tags have not been consumed -- gives error aaa
+ - Another tag gives --- error zzz
+
+ Tag not required
+ - No tags, correct tag content -- success
+ - No tags, incorrect tag content type error yyy
+ - Another tag, not consumed ---  error aaa
+ - Another tag consumed -- success
+ - Another tag consumed and made into another type --- error xxxx
+
+ Tag optional
+ - No tags, correct content -- success
+ - No tags, incorrect content -- error yyy
+ - Expected tag -- success
+ - Another tag, consumed -- success
+ - Another tag, not consumed tag content correct -- error, probably aaa
+ - Another tag, consumed and made into another type -- error xxx
+ - Expected tag + another tag, not consumed -- error aaa
+
+
+ Now fan out for ALLOW_EXTRA --- yuckkkkk
+
+ Ignore ALLOW_EXTRA in v2?
+
+ Fan out for v1
+*/
+
+
 /**
- * When decoding a particular tag like an epoch date, the tag number
- * identifying it may be required to be present, or to be absent depending
- * on the protocol design. It may also be optional. This enum tells the decoder
- * what is required to decode a particular tagged type.
- *
- * See @ref Tag-Usage.
+ * This enum indicates how decode functions for specific tag types
+ * behave in relation to the tag numbers.
  */
 enum QCBORDecodeTagReq {
 
@@ -138,13 +167,14 @@
    /** The data item must be of the type expected for content data type
     *  being fetched. It is an error if it is not. For example, when
     *  calling QCBORDecode_GetEpochDate() and it must not be an @ref
-    *  CBOR_TAG_DATE_EPOCH tag.  */
+    *  CBOR_TAG_DATE_EPOCH tag.  See @ref AreTagsOptional.*/
    QCBOR_TAG_REQUIREMENT_NOT_A_TAG = 1,
 
    /** Either of the above two are allowed. This allows implementation of
     *  being liberal in what you receive, but it is better if CBOR-based
     *  protocols pick one and stick to and not required the reciever to
-    *  take either. */
+    *  take either. See
+    * https://tools.ietf.org/id/draft-thomson-postel-was-wrong-03.html. */
    QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG = 2,
 
    /** Add this into the above value if other tags not processed by QCBOR
@@ -257,7 +287,7 @@
  * the constant can be increased and the library recompiled. It will
  * use more memory).
  *
- * See also @ref Tag-Decoding @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
+ * See also @ref TagDecoding @ref CBORTags.
  *
  * To reduce memory used by a @ref QCBORItem, tag numbers larger than
  * @c UINT16_MAX are mapped so the tag numbers in @c uTags should be
@@ -312,7 +342,7 @@
  * and 63 a CBOR sequence.  This implementation doesn't distinguish
  * between the two (it would be more code and doesn't seem important).
  *
- * The @ref Tag-Usage discussion on the tag requirement applies here
+ * The @ref QCBORDecodeTagReq discussion on the tag requirement applies here
  * just the same as any other tag.
  *
  * In other cases, CBOR is wrapped in a byte string, but it is
@@ -404,6 +434,7 @@
  * See also @ref CBOR_TAG_DATE_STRING, QCBOREncode_AddDateString() and
  * @ref QCBOR_TYPE_DATE_STRING.
  */
+// TODO: should this be GetTDateString like AddTDateString???
 static void
 QCBORDecode_GetDateString(QCBORDecodeContext    *pCtx,
                           enum QCBORDecodeTagReq uTagRequirement,
@@ -811,7 +842,7 @@
  * returned in normal decoding with QCBORDecode_VGetNext() and
  * related.
  *
- * The other facility is QCBORDecode_GetNextTagNumber(). Note als that
+ * The other facility is QCBORDecode_GetNextTagNumber(). Note that
  * tag processing is substantially changed in QCBOR v2.
  *
  * A CBOR tag consists of a tag number and tag content. The tag
@@ -1093,6 +1124,7 @@
  *
  * @param[in] pCtx    The decoder context.
  * @param[in] uIndex The index of the tag to get.
+ * @param[in] pItem The item from which to get the tag number.
  *
  * This is the same as QCBORDecode_GetNthTagNumber() but the order is
  * opposite when there are multiple tags. @c uIndex 0 is the tag
diff --git a/inc/qcbor/qcbor_tag_encode.h b/inc/qcbor/qcbor_tag_encode.h
index a862056..f69ff16 100644
--- a/inc/qcbor/qcbor_tag_encode.h
+++ b/inc/qcbor/qcbor_tag_encode.h
@@ -40,6 +40,7 @@
 
 #include "qcbor/qcbor_common.h"
 #include "qcbor/qcbor_private.h"
+#include "qcbor/qcbor_main_encode.h"
 #include <stdbool.h>
 
 
@@ -54,56 +55,70 @@
 /**
  * @file qcbor_tag_encode.h
  *
- * @anchor Tags-Overview
+ * @anchor TagEncoding
+ * ## Tag Encoding
  *
- * ## Tags Overview
+ * If you are unfamiliar with CBOR tags and related terminology,
+ * reviewing the @ref CBORTags documentation.
  *
- * Any CBOR data item can be made into a tag to add semantics, define a
- * new data type or such. Some tags are fully standardized and some are
- * just registered. Others are not registered and used in a proprietary
- * way.
+ * QCBOR provides multiple ways to encode tags, some for standard tags
+ * that QCBOR supports directly and another that works for any tag.
  *
- * Encoding and decoding of many of the registered tags is fully
- * implemented by QCBOR. It is also possible to encode and decode tags
- * that are not directly supported.  For many use cases the built-in tag
- * support should be adequate.
+ * ### Encoding Standardized Tags
  *
- * For example, the registered epoch date tag is supported in encoding
- * by QCBOREncode_AddTDateEpoch() and in decoding by @ref
- * QCBOR_TYPE_DATE_EPOCH and the @c epochDate member of @ref
- * QCBORItem. This is typical of the built-in tag support. There is an
- * API to encode data for it and a @c QCBOR_TYPE_XXX when it is decoded.
+ * For many standardized tags, QCBOR offers dedicated methods. For
+ * instance, the standard tag for an epoch date can be encoded using
+ * QCBOREncode_AddTDateEpoch(). These methods are easily identifiable
+ * by their names, which always begin with "QCBOREncode_AddT".
  *
- * Tags are registered in the [IANA CBOR Tags Registry]
- * (https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml). There
- * are roughly three options to create a new tag. First, a public
- * specification can be created and the new tag registered with IANA.
- * This is the most formal. Second, the new tag can be registered with
- * IANA with just a short description rather than a full specification.
- * These tags must be greater than 256. Third, a tag can be used without
- * any IANA registration, though the registry should be checked to see
- * that the new value doesn't collide with one that is registered. The
- * value of these tags must be 256 or larger.
+ * ### General Tag Encoding
  *
- * See also @ref CBORTags and @ref Tag-Usage
+ * To encode a any tag, you can use QCBOREncode_AddTagNumber()
+ * followed by other QCBOR encode methods to encode  the tag content.
  *
- * The encoding side of tags not built-in is handled by
- * QCBOREncode_AddTagNumber() and is relatively simple. Tag decoding is more
- * complex and mainly handled by QCBORDecode_GetNext(). Decoding of the
- * structure of tagged data not built-in (if there is any) has to be
- * implemented by the caller.
+ * - Minimal Example: For a simple tag, you might only call
+ *   QCBOREncode_AddTagNumber() followed by QCBOREncode_AddInt64().
+ *
+ * - Complex Example: For more complex structures,
+ *   QCBOREncode_AddTagNumber() might precede a call to
+ *   QCBOREncode_OpenMap() and the encoding of all the items in the
+ *   map. Or, QCBOREncode_AddTagNumber() might precede a call to a library
+ *   function that creates a complex message like a COSE_Encrypt.
+ *
+ * Tags can nest, so there might be sequential calls to
+ * QCBOREncode_AddTagNumber(). While deep nesting is rare andthere is no
+ * limit for encoding, QCBOR decoding is limited to a
+ * depth of @ref QCBOR_MAX_TAGS_PER_ITEM.
+ *
+ * ### Borrowing Tag Content
+ *
+ * As described in @ref AreTagsOptional, it is often the case that tag
+ * content for a particular tag is encoded without the tag number.
+ * This is "borrowing" tag content. It is similar to implicit types in
+ * ASN.1 where the type is inferred by context.
+ *
+ * For the standard tags supported by QCBOR, their methods include an
+ * argument to control this behavior:
+ *
+ * - @ref QCBOR_ENCODE_AS_TAG : Includes the tag number.
+ * - @ref QCBOR_ENCODE_AS_BORROWED : Omits the tag number.
+ *
+ * For tags other than the standard ones supported by QCBOR methods,
+ * the names of which starts with "QCBOREncode_AddT", all that is
+ * needed to encode borrowed tag content is to not call
+ * QCBOREncode_AddTagNumber(). This of course assumes the protocol can
+ * be unambiguously decoded without the tag number.
  */
 
 
 /**
- * Output the full CBOR tag. See @ref CBORTags, @ref Tag-Usage and
- * @ref Tags-Overview.
+ * Output the full CBOR tag. See @ref CBORTags.
  */
 #define QCBOR_ENCODE_AS_TAG      0
 
 /**
  * Output only the 'borrowed' content format for the relevant tag.
- * See @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
+ * See @ref CBORTags..
  */
 #define QCBOR_ENCODE_AS_BORROWED 1
 
@@ -113,27 +128,27 @@
  * @brief Add a tag number.
  *
  * @param[in] pCtx  The encoding context to add the tag to.
- * @param[in] uTag  The tag to add
+ * @param[in] uTagNumber  The tag number to add.
  *
- * This outputs a CBOR major type 6 item that tags the next data item
- * that is output usually to indicate it is some new data type.
+ * This outputs a CBOR major type 6 item, a tag number that indicates
+ * the next item is a different type.  See @ref TagEncoding.
  *
  * For many of the common standard tags, a function to encode data
  * using it is provided and this is not needed. For example,
  * QCBOREncode_AddTDateEpoch() already exists to output integers
- * representing dates with the right tag.
+ * representing epochs dates.
  *
- * The tag is applied to the next data item added to the encoded
- * output. That data item that is to be tagged can be of any major
- * CBOR type. Any number of tags can be added to a data item by
- * calling this multiple times before the data item is added.
+ * The tag number is applied to the next data item added to the
+ * encoded output. That data item that is to be tagged can be of any
+ * major CBOR type. Any number of tag numbers can be added to a data
+ * item by calling this multiple times before the data item is added.
  *
- * See @ref Tags-Overview for discussion of creating new non-standard
- * tags. See QCBORDecode_GetNext() for discussion of decoding custom
- * tags.
+ * See also @ref TagEncoding.
  */
 static void
-QCBOREncode_AddTagNumber(QCBOREncodeContext *pCtx, uint64_t uTag);
+QCBOREncode_AddTagNumber(QCBOREncodeContext *pCtx, uint64_t uTagNumber);
+
+
 
 
 /**
@@ -199,7 +214,7 @@
  *  @param[in] nDays            Number of days before or after 1970-01-0.
  *
  * This date format is described in
- * [RFC 8943] (https://www.rfc-editor.org/rfc/rfc8943.html).
+ * [RFC 8943](https://www.rfc-editor.org/rfc/rfc8943.html).
  *
  * The preferred integer serialization rules apply here so the date
  * will be encoded in a minimal number of bytes. Until about the year
@@ -236,8 +251,8 @@
  *                             @ref QCBOR_ENCODE_AS_BORROWED.
  * @param[in] Bytes            Pointer and length of the binary UUID.
  *
- * A binary UUID as defined in [RFC 4122]
- * (https://www.rfc-editor.org/rfc/rfc4122.html) is added to the
+ * A binary UUID as defined in 
+ * [RFC 4122](https://www.rfc-editor.org/rfc/rfc4122.html) is added to the
  * output.
  *
  * It is output as CBOR major type 2, a binary string, with tag @ref
@@ -271,8 +286,8 @@
  *                             @ref QCBOR_ENCODE_AS_BORROWED.
  * @param[in] URI              Pointer and length of the URI.
  *
- * The format of URI must be per [RFC 3986]
- * (https://www.rfc-editor.org/rfc/rfc3986.html).
+ * The format of URI must be per 
+ * [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986.html).
  *
  * It is output as CBOR major type 3, a text string, with tag @ref
  * CBOR_TAG_URI indicating the text string is a URI.
@@ -310,8 +325,8 @@
  *                             @ref QCBOR_ENCODE_AS_BORROWED.
  * @param[in] B64Text          Pointer and length of the base-64 encoded text.
  *
- * The text content is Base64 encoded data per [RFC 4648]
- * (https://www.rfc-editor.org/rfc/rfc4648.html).
+ * The text content is Base64 encoded data per 
+ * [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648.html).
  *
  * It is output as CBOR major type 3, a text string, with tag @ref
  * CBOR_TAG_B64 indicating the text string is Base64 encoded.
@@ -345,7 +360,7 @@
  * @param[in] B64Text          Pointer and length of the base64url encoded text.
  *
  * The text content is base64URL encoded text as per
- * [RFC 4648] (https://www.rfc-editor.org/rfc/rfc4648.html).
+ * [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648.html).
  *
  * It is output as CBOR major type 3, a text string, with tag
  * @ref CBOR_TAG_B64URL indicating the text string is a Base64url
@@ -413,8 +428,8 @@
  *                             @ref QCBOR_ENCODE_AS_BORROWED.
  * @param[in] MIMEData         Pointer and length of the MIME data.
  *
- * The text content is in MIME format per [RFC 2045]
- * (https://www.rfc-editor.org/rfc/rfc2045.html) including the headers.
+ * The text content is in MIME format per 
+ * [RFC 2045](https://www.rfc-editor.org/rfc/rfc2045.html) including the headers.
  *
  * It is output as CBOR major type 2, a binary string, with tag
  * @ref CBOR_TAG_BINARY_MIME indicating the string is MIME data.  This
@@ -462,10 +477,9 @@
  * @param[in] szDate           Null-terminated string with date to add.
  *
  * The string szDate should be in the form of
- * [RFC 3339] (https://www.rfc-editor.org/rfc/rfc3339.html) as defined
- * by section 3.3 in [RFC 4287] (https://www.rfc-editor.org/rfc/rfc4287.html).
- * This is as described in section 3.4.1 in [RFC 8949]
- * (https://www.rfc-editor.org/rfc/rfc8949.html#section3.1.4).
+ * [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) as defined
+ * by section 3.3 in [RFC 4287](https://www.rfc-editor.org/rfc/rfc4287.html).
+ * This is as described in section 3.4.1 in [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html#section3.1.4).
  *
  * Note that this function doesn't validate the format of the date
  * string at all. If you add an incorrect format date string, the
@@ -505,10 +519,10 @@
  * @param[in] szDate           Null-terminated string with date to add.
  *
  * This date format is described in
- * [RFC 8943] (https://www.rfc-editor.org/rfc/rfc8943.html), but that mainly
+ * [RFC 8943](https://www.rfc-editor.org/rfc/rfc8943.html), but that mainly
  * references RFC 3339.  The string szDate must be in the forrm
  * specified the ABNF for a full-date in
- * [RFC 3339] (https://www.rfc-editor.org/rfc/rfc3339.html). Examples of this
+ * [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html). Examples of this
  * are "1985-04-12" and "1937-01-01".  The time and the time zone are
  * never included.
  *
@@ -576,7 +590,7 @@
 
 /** @deprecated Use QCBOREncode_AddTagNumber() instead. */
 static void
-QCBOREncode_AddTag(QCBOREncodeContext *pCtx, uint64_t uTag);
+QCBOREncode_AddTag(QCBOREncodeContext *pCtx, uint64_t uTagNumber);
 
 /** @deprecated Use QCBOREncode_AddTURI() instead. */
 static void
@@ -675,21 +689,22 @@
 
 
 /* ========================================================================= *
- *    BEGINNING OF PRIVATE INLINE IMPLEMENTATION                             *
+ *    BEGINNING OF PRIVATE INLINE IMPLEMENTATION    
+ *    Note that the entire qcbor_tag_encode implementation is line.
  * ========================================================================= */
 
 
 static inline void
-QCBOREncode_AddTagNumber(QCBOREncodeContext *pMe, const uint64_t uTag)
+QCBOREncode_AddTagNumber(QCBOREncodeContext *pMe, const uint64_t uTagNumber)
 {
-   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_TAG, uTag, 0);
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_TAG, uTagNumber, 0);
 }
 
 
 static inline void
-QCBOREncode_AddTag(QCBOREncodeContext *pMe, const uint64_t uTag)
+QCBOREncode_AddTag(QCBOREncodeContext *pMe, const uint64_t uTagNumber)
 {
-   QCBOREncode_AddTagNumber(pMe, uTag);
+   QCBOREncode_AddTagNumber(pMe, uTagNumber);
 }