'(Re-)read all files new or changed since last update.
Store all environment docnames in the canonical format (ie using SEP as
a separator in place of os.path.sep).'

def update(self, config, srcdir, doctreedir):

    config_changed = False
    if (self.config is None):
        msg = '[new    config]    '
        config_changed = True
    else:
        for confval in config.filter('env'):
            if (self.config[confval.name] != confval.value):
                msg = '[config    changed]    '
                config_changed = True
                break
        else:
            msg = ''
        if (self.config.extensions != config.extensions):
            msg = '[extensions    changed]    '
            config_changed = True
    self.srcdir = srcdir
    self.doctreedir = doctreedir
    self.find_files(config, self.app.builder)
    self.config = config
    self._nitpick_ignore = set(self.config.nitpick_ignore)
    logger.info(bold('updating    environment:    '), nonl=True)
    (added, changed, removed) = self.get_outdated_files(config_changed)
    for docs in self.app.emit('env-get-outdated', self, added, changed, removed):
        changed.update((set(docs) & self.found_docs))
    if (added or removed):
        changed.update((self.glob_toctrees & self.found_docs))
    msg += ('%s    added,    %s    changed,    %s    removed' % (len(added), len(changed), len(removed)))
    logger.info(msg)
    for docname in removed:
        self.app.emit('env-purge-doc', self, docname)
        self.clear_doc(docname)
    docnames = sorted((added | changed))
    self.app.emit('env-before-read-docs', self, docnames)
    par_ok = False
    if (parallel_available and (len(docnames) > 5) and (self.app.parallel > 1)):
        for ext in itervalues(self.app.extensions):
            if (ext.parallel_read_safe is None):
                logger.warning(__("the    %s    extension    does    not    declare    if    it    is    safe    for    parallel    reading,    assuming    it    isn't    -    please    ask    the    extension    author    to    check    and    make    it    explicit"), ext.name)
                logger.warning('doing    serial    read')
                break
            elif (ext.parallel_read_safe is False):
                break
        else:
            par_ok = True
    if par_ok:
        self._read_parallel(docnames, self.app, nproc=self.app.parallel)
    else:
        self._read_serial(docnames, self.app)
    if (config.master_doc not in self.all_docs):
        raise SphinxError(('master    file    %s    not    found' % self.doc2path(config.master_doc)))
    for retval in self.app.emit('env-updated', self):
        if (retval is not None):
            docnames.extend(retval)
    return sorted(docnames)
