def add_defaults (properties):
    """ Given a set of properties, add default values for features not
        represented in the set.
        Note: if there's there's ordinary feature F1 and composite feature
        F2, which includes some value for F1, and both feature have default values,
        then the default value of F1 will be added, not the value in F2. This might
        not be right idea: consider

          feature variant : debug ... ;
               <variant>debug : .... <runtime-debugging>on
          feature <runtime-debugging> : off on ;

          Here, when adding default for an empty property set, we'll get

            <variant>debug <runtime_debugging>off

          and that's kind of strange.
    """
    if __debug__:
        from .property import Property
        assert is_iterable_typed(properties, Property)
    # create a copy since properties will be modified
    result = list(properties)

    # We don't add default for conditional properties.  We don't want
    # <variant>debug:<define>DEBUG to be takes as specified value for <variant>
    handled_features = set(p.feature for p in properties if not p.condition)

    missing_top = [f for f in __all_top_features if not f in handled_features]
    more = defaults(missing_top)
    result.extend(more)
    handled_features.update(p.feature for p in more)

    # Add defaults for subfeatures of features which are present
    for p in result[:]:
        subfeatures = [s for s in p.feature.subfeatures if not s in handled_features]
        more = defaults(__select_subfeatures(p, subfeatures))
        handled_features.update(h.feature for h in more)
        result.extend(more)

    return result