# encoding: utf-8
=begin

 * Name: SiSU

 * Description: a framework for document structuring, publishing and search

 * Author: Ralph Amissah

 * Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
   2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Ralph Amissah,
   All Rights Reserved.

 * License: GPL 3 or later:

   SiSU, a framework for document structuring, publishing and search

   Copyright (C) Ralph Amissah

   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   Software Foundation, either version 3 of the License, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
   more details.

   You should have received a copy of the GNU General Public License along with
   this program. If not, see <http://www.gnu.org/licenses/>.

   If you have Internet connection, the latest version of the GPL should be
   available at these locations:
   <http://www.fsf.org/licensing/licenses/gpl.html>
   <http://www.gnu.org/licenses/gpl.html>

   <http://www.sisudoc.org/sisu/en/manifest/gpl.fsf.html>

 * SiSU uses:
   * Standard SiSU markup syntax,
   * Standard SiSU meta-markup syntax, and the
   * Standard SiSU object citation numbering and system

 * Hompages:
   <http://www.jus.uio.no/sisu>
   <http://www.sisudoc.org>

 * Git
   <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=summary>
   <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=blob;f=lib/sisu/v5/dp.rb;hb=HEAD>

 * Ralph Amissah
   <ralph@amissah.com>
   <ralph.amissah@gmail.com>

 ** Description: document parameters extracted from input files for program use

=end
module SiSU_Param
  begin
    require 'uri'
    require 'pstore'
  rescue LoadError
    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
      error('uri or pstore NOT FOUND (LoadError)')
  end
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'dp_make'                            # dp_make.rb
  require_relative 'dp_identify_markup'                 # dp_identify_markup.rb
  @@date=SiSU_Env::InfoDate.new
  @@proc=
    @@filename_txt=
    @@filename_texinfo=
    @@filename_lout_portrait=
    @@filename_lout_landscape=
    @@filename_html_scroll=
    @@filename_html_index=
    @@filename_html_segtoc=
    @@filename_semantic=
    @@filename_rss=
    @@newfile=
    @@drr=
    nil
  @doc={
    initialise: nil,
    markup: '',
    lnks: '',
    stmp: '',
    req: {},
  }
  @@yaml=@@yamladdr=nil
  @@trigger=nil
  @@lv,@@flag={},{}
  @@tex_backslash="\\\\"
  class Parameters
    @@publisher='SiSU scribe'
    @@md=@@fns=@@pth=nil
    def initialize(opt)
      @opt=opt
      @cX||=SiSU_Screen::Ansi.new(@opt.act[:color_state][:set])
      @fns=if @opt.act[:psql][:set] == [:on] #revisit CHECK
        opt.fns
      else opt.fns.gsub(/\.ssm$/,'.ssm.sst')
      end
      SiSU_Param::Instantiate.new.param_instantiate
      @env=SiSU_Env::InfoEnv.new(@fns)
      @pstorefile="#{@env.processing_path.ao}/#{@fns}.pstore"
    end
    def get
      if @opt.f_pth \
      and @opt.f_pth[:pth] != Dir.pwd #BUG check
        # you may need to change Dir.pwd to @opt.f_pth[:pth] where the latter
        # has a path value that is different, however, f_pth is not always set!
        Dir.chdir(@opt.f_pth[:pth])
      end
      if @@fns !=@fns \
      or @@pth !=Dir.pwd               #@opt.f_pth[:pth]
        @@fns,@@pth=@fns,Dir.pwd       #@opt.f_pth[:pth]
        @@md=nil
      end
      if @@md.nil? \
      or @opt.act[:maintenance][:set]==:on #not particularly helpful, as current cycle is through output types, with files changing, only helpful if deal with a file all output types before going to next file
        if File.exist?(@pstorefile)
          param_msg='Parameters from pstore'
          store=PStore.new(@pstorefile)
          store.transaction do
            @md=store['md']
          end
          @md
        else
          param_msg='Parameters extracted'
          fns_array=@env.read_source_file(@opt.fns)
          @md=SiSU_Param::Parameters::Instructions.new(fns_array,@opt).extract
          @md
        end
        if defined? @md.title.main # on removal check problems with -U
          if (@opt.act[:verbose][:set]==:on \
          || @opt.act[:verbose_plus][:set]==:on \
          || @opt.act[:maintenance][:set]==:on)
            SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              param_msg,
              @md.title.main
            ).txt_grey
          end
        end
        @@md=@md
      else @@md
      end
      @@md.opt=@opt
      @@md
    end
    class MdDefault
      def rights(author,date)
        @author,@date=author,date
        def assignment(author)
          'copyright not explicitly stated, ' \
          + 'program "assigning" copyright to author: ' \
          + author
        end
        def all
          s=nil
          if @author
            #puts assignment(@author)
            s ||=((@date =~/((?:1[4-9]|2[01])\d{2})/ ) \
            ? ("Copyright (C) #{$1} #{@author}")
            : ('Copyright (C)' + @author))                     #matches years 1400 through 21\d\d
          end
          s
        end
        def copyright_and_license
          s=nil
          if @author
            #puts assignment(@author)
            s ||=((@date =~/((?:1[4-9]|2[01])\d{2})/ ) \
            ? ("Copyright (C) #{$1} #{@author}")
            : ('Copyright (C)' + @author))                     #matches years 1400 through 21\d\d
          end
          s
        end
        def text
          all
        end
        def copyright
          def all
            s=nil
            if @author
              s ||=((@date =~/((?:1[4-9]|2[01])\d{2})/ ) \
              ? ("Copyright (C) #{$1} #{@author}")
              : ('Copyright (C)' + @author))                     #matches years 1400 through 21\d\d
            end
            s
          end
          def text
            all
          end
          self
        end
        self
      end
    end
    class MdMake < SiSU_Param_Make::MdMake
    end
    class Md
      def initialize(str,opt,env)
        @s,@opt,@env=str,opt,env
      end
      def validate_length(s,l,n)
        #s=(s.length <= l) ? s : nil
        s=if s.is_a?(String) \
        and s.length <= l
          s
        elsif s.is_a?(NilClass)
          nil
        elsif s.class !=String
          STDERR.puts "#{n} is #{s.class}: programming error, String expected #{__FILE__}:#{__LINE__}"
          s
        else
          SiSU_Screen::Ansi.new(
            'v',
            "*WARN* #{n} length #{s.length} exceeds set db field length #{l}, metadata dropped",
            @opt.fns
          ).warn unless @opt.act[:quiet][:set]==:on
          nil
        end
      end
      def name_format(name)
        if name
          name=name.strip
          @name_a_h=[]
          authors=name.scan(/[^;]+/)
          authors.each_with_index do |a,i|
            b=((a =~/\s*\|\s*/) ? (a.split(/\|/)) : [a])
            if b[0] =~/"(.+?)"/
              @name_a_h << { the: $1 }
            else
              x=b[0].scan(/[^,]+/)
              if x.length==1
                @name_a_h << { the: x[0].strip }
              elsif x.length==2
                @name_a_h << { the: x[0].strip, others: x[1].strip }
              else #p x.length
              end
            end
            b.delete_at(0)
            b.each do |d|
              k,c=nil
              k,c=/^(\S+)\s+(.*)/.match(d)[1,2] if d
              @name_a_h[i][:hon]=c.strip if k=='hon'
              @name_a_h[i][:affiliation]=c.strip if k=='affiliation'
              @name_a_h[i][:nationality]=c.strip if k=='nationality'
            end
          end
          l=@name_a_h.length
          name_str=''
          @name_a_h.each_with_index do |a,i|
            name_str += if a[:others]
              z=(((l - i) > 1) ? ', ' : '')
              "#{a[:others].strip} #{a[:the].strip}" + z
            else
              z=(((l - i) > 2) ? ', ' : '')
              "#{a[:the].strip}" + z
            end
          end
          { name_a_h: @name_a_h, name_str: name_str }
        else nil
        end
      end
      def build_hash(arr)
        @h={}
        arr.each_with_index do |x,i|
          a,b=nil,nil
          if x =~/^%\s/ #ignore comment
          elsif x =~/:(\S+?):\s+(.+)/
            a,b=/:(\S+?):\s+(.+)\Z/m.match(x)[1,2]
            b=b.gsub(/\s*<br(?: \/)?>\s*/,' \\\\\\ ')
            b=if b =~/\n/m
              (b =~/;\n/m) \
              ? (b.split(/;\s*\n\s*/).join(';'))
              : (b.split(/\s*\n\s*/).join(' '))
            else
              b
            end
          elsif i == 0
            a='main'
            b=x
          else
          end
          @h[a]=b
        end
        @h
      end
      def title
        a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
        @h=build_hash(a)
        def main
          s=@h['main']
          l,n=Db[:col_title_part],'title.main'
          validate_length(s,l,n)
        end
        def sub
          s=@h['subtitle']
          l,n=Db[:col_title_part],'title.subtitle'
          validate_length(s,l,n)
        end
        def edition
          s=@h['edition']
          l,n=Db[:col_title_edition],'title.edition'
          validate_length(s,l,n)
        end
        def note
          s=@h['note']
          l,n=Db[:col_info_note],'title.note'
          validate_length(s,l,n)
        end
        def short
          s=@h['short'] \
          ? @h['short']
          : @h['main']
          l,n=Db[:col_title_part],'title.short'
          validate_length(s,l,n)
        end
        def full
          s=@h['subtitle'] \
          ? (@h['main'] + ' - ' + @h['subtitle'])
          : @h['main']
          l,n=Db[:col_title],'title.full'
          validate_length(s,l,n)
        end
        def language
          s=@h['language']
          l,n=Db[:col_language],'title.language'
          validate_length(s,l,n)
        end
        def language_char # look into, this must be set, from 1 directory stub (.fi), 2 filename (~fi), [3 (not used) document header (@title:\n  :language_char: fi)]
          s=@h['language_char']
          l,n=Db[:col_language_char],'title.language_char'
          validate_length(s,l,n)
        end
        self
      end
      def creator #there are sub categories that need to be catered for and sometimes more than one author etc.; implement array.to_s.length validation test later, current test on string approximate as string is not used
        a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
        @h=build_hash(a)
        def author
          @h['author']=(@h['author'] \
          ? @h['author']
          : @h['main'])
          names=name_format(@h['author'])
          s=names[:name_str]
          l,n=Db[:col_name],'creator.author'
          validate_length(s,l,n)
        end
        def author_detail
          s=@h['author'] \
          ? @h['author']
          : @h['main']
          names=name_format(s)
          names[:name_a_h]
        end
        def editor
          names=@h['editor'] \
          ? name_format(@h['editor'])
          : nil
          s=(names.is_a?(Hash)) \
          ? names[:name_str]
          : nil
          s=if s
            l,n=Db[:col_name],'creator.editor'
            validate_length(s,l,n)
          else nil
          end
        end
        def editor_detail
          names=@h['editor'] \
          ? name_format(@h['editor'])
          : nil
          (names.is_a?(Hash)) \
          ? names[:name_a_h]
          : nil
        end
        def contributor
          names=@h['contributor'] \
          ? name_format(@h['contributor'])
          : nil
          s=(names.is_a?(Hash)) \
          ? names[:name_str]
          : nil
          s=if s
            l,n=Db[:col_name],'creator.author'
            validate_length(s,l,n)
          else nil
          end
        end
        def contributor_detail
          names=@h['contributor'] \
          ? name_format(@h['contributor'])
          : nil
          (names.is_a?(Hash)) \
          ? names[:name_a_h]
          : nil
        end
        def illustrator
          names=@h['illustrator'] \
          ? name_format(@h['illustrator'])
          : nil
          s=(names.is_a?(Hash)) \
          ? names[:name_str]
          : nil
          s=if s
            l,n=Db[:col_name],'creator.illustrator'
            validate_length(s,l,n)
          else nil
          end
        end
        def illustrator_detail
          names=@h['illustrator'] \
          ? name_format(@h['illustrator'])
          : nil
          (names.is_a?(Hash)) \
          ? names[:name_a_h]
          : nil
        end
        def photographer
          names=@h['photographer'] \
          ? name_format(@h['photographer'])
          : nil
          s=(names.is_a?(Hash)) \
          ? names[:name_str]
          : nil
          s=if s
            l,n=Db[:col_name],'creator.photographer'
            validate_length(s,l,n)
          else nil
          end
        end
        def photographer_detail
          names=@h['photographer'] \
          ? name_format(@h['photographer'])
          : nil
          (names.is_a?(Hash)) \
          ? names[:name_a_h]
          : nil
        end
        def translator
          names=@h['translator'] \
          ? name_format(@h['translator'])
          : nil
          s=(names.is_a?(Hash)) \
          ? names[:name_str]
          : nil
          s=if s
            l,n=Db[:col_name],'creator.translator'
            validate_length(s,l,n)
          else nil
          end
        end
        def translator_detail
          names=@h['translator'] \
          ? name_format(@h['translator'])
          : nil
          (names.is_a?(Hash)) \
          ? names[:name_a_h]
          : nil
        end
        def audio
          names=@h['audio'] \
          ? name_format(@h['audio'])
          : nil
          s=(names.is_a?(Hash)) \
          ? names[:name_str]
          : nil
          s=if s
            l,n=Db[:col_name],'creator.audio'
            validate_length(s,l,n)
          else nil
          end
        end
        def audio_detail
          names=@h['audio'] \
          ? name_format(@h['audio'])
          : nil
          (names.is_a?(Hash)) \
          ? names[:name_a_h]
          : nil
        end
        def digitized_by
          names=@h['digitized_by'] \
          ? name_format(@h['digitized_by'])
          : nil
          s=(names.is_a?(Hash)) \
          ? names[:name_str]
          : nil
          s=if s
            l,n=Db[:col_name],'creator.digitized_by'
            validate_length(s,l,n)
          else nil
          end
        end
        def digitized_by_detail
          names=@h['digitized_by'] \
          ? name_format(@h['digitized_by'])
          : nil
          (names.is_a?(Hash)) \
          ? names[:name_a_h]
          : nil
        end
        def prepared_by
          names=@h['prepared_by'] \
          ? name_format(@h['prepared_by'])
          : nil
          s=(names.is_a?(Hash)) \
          ? names[:name_str]
          : nil
          s=if s
            l,n=Db[:col_name],'creator.prepared_by'
            validate_length(s,l,n)
          else nil
          end
        end
        def prepared_by_detail
          names=@h['prepared_by'] \
          ? name_format(@h['prepared_by'])
          : nil
          names=name_format(@h['prepared_by'])
          (names.is_a?(Hash)) \
          ? names[:name_a_h]
          : nil
        end
        self
      end
      def rights
        a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
        @h=build_hash(a)
        def copyright
          def text #you may wish to expand to take from all
            s=if @h['copyright'] then @h['copyright']
            elsif @h['text']     then @h['text']
            elsif @h['main']     then @h['main']
            else
              SiSU_Screen::Ansi.new(
                @opt.act[:color_state][:set],
                'WARNING Document Copyright missing; provide @rights: :copyright:'
              ).warn unless @opt.act[:quiet][:set]==:on
              ''
            end
            l,n=Db[:col_info_note],'rights.copyright.text'
            validate_length(s,l,n)
          end
          def translation
            s=@h['translation'] \
            ? @h['translation']
            : nil
            l,n=Db[:col_info_note],'rights.copyright.translation'
            validate_length(s,l,n)
          end
          def illustrations
            s=@h['illustrations'] \
            ? @h['illustrations']
            : nil
            l,n=Db[:col_info_note],'rights.copyright.illustrations'
            validate_length(s,l,n)
          end
          def photographs
            s=@h['photographs'] \
            ? @h['photographs']
            : nil
            l,n=Db[:col_info_note],'rights.copyright.photographs'
            validate_length(s,l,n)
          end
          def digitization
            s=@h['digitization'] \
            ? @h['digitization']
            : nil
            l,n=Db[:col_info_note],'rights.copyright.digitization'
            validate_length(s,l,n)
          end
          def audio
            s=@h['audio'] \
            ? @h['audio']
            : nil
            l,n=Db[:col_info_note],'rights.copyright.audio'
            validate_length(s,l,n)
          end
          self
        end
        def license
          s=@h['license'] \
          ? @h['license']
          : nil
          l,n=Db[:col_info_note],'rights.license'
          validate_length(s,l,n)
        end
        def sep(str)
          ' \\\\ '
        end
        def copyright_and_license
          s=if @h['copyright_and_license'] then @h['copyright_and_license']
          else
            s=''
            if defined? copyright.text \
            and copyright.text \
            and not copyright.text.empty?
              v=sep(copyright.text)
              s +=copyright.text + v
            end
            if defined? copyright.license \
            and copyright.license \
            and not copyright.license.empty?
              s +=copyright.license
            end
            if s.empty?
              SiSU_Screen::Ansi.new(
                @opt.act[:color_state][:set],
                'WARNING Document Rights information missing; provide @rights: :copyright:'
              ).warn unless @opt.act[:quiet][:set]==:on
            else
              l,n=Db[:col_info_note],'rights.all'
              validate_length(s,l,n)
            end
            s=s.gsub(/ [\\]+\s+$/,'')
          end
          s
        end
        def all
          s=if @h['all'] then @h['all']
          else
            s=''
            if defined? copyright.text \
            and copyright.text \
            and not copyright.text.empty?
              v=sep(copyright.text)
              s +='Copyright: ' + copyright.text + v
            end
            if defined? copyright.translation \
            and copyright.translation \
            and not copyright.translation.empty?
              v=sep(copyright.translation)
              s +='translation: ' + copyright.translation + v
            end
            if defined? copyright.illustrations \
            and copyright.illustrations \
            and not copyright.illustrations.empty?
              v=sep(copyright.illustrations)
              s +='illustrations: ' + copyright.illustrations + v
            end
            if defined? copyright.photographs \
            and copyright.photographs \
            and not copyright.photographs.empty?
              v=sep(copyright.photographs)
              s +='photographs: ' + copyright.photographs + v
            end
            if defined? copyright.digitization \
            and copyright.digitization \
            and not copyright.digitization.empty?
              v=sep(copyright.digitization)
              s +='digitization: ' + copyright.digitization + v
            end
            if defined? copyright.audio \
            and copyright.audio \
            and not copyright.audio.empty?
              v=sep(copyright.audio)
              s +='audio: ' + copyright.audio + v
            end
            if defined? copyright.license \
            and copyright.license \
            and not copyright.license.empty?
              s +='License: ' + copyright.license
            end
            if s.empty?
              SiSU_Screen::Ansi.new(
                @opt.act[:color_state][:set],
                'WARNING Document Rights information missing; provide @rights: :copyright:'
              ).warn unless @opt.act[:quiet][:set]==:on
            else
              l,n=Db[:col_info_note],'rights.all'
              validate_length(s,l,n)
            end
            s=s.gsub(/ [\\]+\s+$/,'')
          end
          s
        end
        self
      end
      def identifier
        a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
        @h=build_hash(a)
        def oclc
          s=@h['oclc']
          l,n=Db[:col_library],'identifier.oclc'
          validate_length(s,l,n)
        end
        def isbn
          s=@h['isbn']
          l,n=Db[:col_small],'identifier.isbn'
          validate_length(s,l,n)
        end
        def pg
          s=@h['pg']
          l,n=Db[:col_small],'identifier.pg'
          validate_length(s,l,n)
        end
        self
      end
      def classify
        a=@s.split(/(\n%\s.+?$|[ ]*)(?:\n[ ]*(?=:)|\Z)/m)
        @h=build_hash(a)
        def topic_register
          s=@h['topic_register']
          l,n=Db[:col_info_note],'classify.topic_register'
          validate_length(s,l,n)
        end
        def subject
          s=@h['subject']
          l,n=Db[:col_txt_long],'classify.subject'
          validate_length(s,l,n)
        end
        def keywords
          s=@h['keywords']
          l,n=Db[:col_txt_long],'classify.keywords'
          validate_length(s,l,n)
        end
        def loc
          s=@h['loc']
          l,n=Db[:col_library],'classify.loc'
          validate_length(s,l,n)
        end
        def dewey
          s=@h['dewey']
          l,n=Db[:col_library],'classify.dewey'
          validate_length(s,l,n)
        end
        self
      end
      def publisher
        a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
        @h=build_hash(a)
        s=@h['main']
        l,n=Db[:col_name],'publisher'
        validate_length(s,l,n)
      end
      def date
        a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
        @h=build_hash(a)
        def added_to_site
          s=@h['added_to_site']
          l,n=Db[:col_date_text],'date.added_to_site'
          validate_length(s,l,n)
        end
        def available
          s=@h['available']
          l,n=Db[:col_date_text],'date.available'
          validate_length(s,l,n)
        end
        def created
          s=@h['created']
          l,n=Db[:col_date_text],'date.created'
          validate_length(s,l,n)
        end
        def issued
          s=@h['issued']
          l,n=Db[:col_date_text],'date.issued'
          validate_length(s,l,n)
        end
        def modified
          s=@h['modified']
          l,n=Db[:col_date_text],'date.modified'
          validate_length(s,l,n)
        end
        def published
          s=@h['published']=(@h['published'] ? @h['published'] : @h['main'])
          l,n=Db[:col_date_text],'date.published'
          validate_length(s,l,n)
        end
        def valid
          s=@h['valid']
          l,n=Db[:col_date_text],'date.valid'
          validate_length(s,l,n)
        end
        self
      end
      #def language                     # as things stand this should really be populated from title.language and original.language, resolve
      #  a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
      #  @h=build_hash(a)
      #  def document
      #    s=@h['document']=(@h['document'] ? @h['document'] : @h['main'])
      #    l,n=Db[:col_language],'language.document'
      #    validate_length(s,l,n)
      #  end
      #  def document_char
      #    s=@h['document_char']=(@h['document_char'] ? @h['document_char'] : nil)
      #    l,n=Db[:col_language_char],'language.document_char'
      #    validate_length(s,l,n)
      #  end
      #  def original
      #    s=@h['original']
      #    l,n=Db[:col_language],'language.original'
      #    validate_length(s,l,n)
      #  end
      #  def original_char
      #    s=@h['original_char']
      #    l,n=Db[:col_language_char],'language.original_char'
      #    validate_length(s,l,n)
      #  end
      #  self
      #end
      def current_publisher
        @s
      end
      def original
        a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
        @h=build_hash(a)
        def publisher
          s=@h['publisher']
          l,n=Db[:col_name],'original.publisher'
          validate_length(s,l,n)
        end
        def language
          s=@h['language']
          l,n=Db[:col_language],'original.language'
          validate_length(s,l,n)
        end
        def language_char
          s=@h['language_char']
          l,n=Db[:col_language_char],'original.language_char'
          validate_length(s,l,n)
        end
        def source
          s=@h['source']
          l,n=Db[:col_name],'original.source'
          validate_length(s,l,n)
        end
        def institution
          s=@h['institution']
          l,n=Db[:col_name],'original.institution'
          validate_length(s,l,n)
        end
        def nationality
          s=@h['nationality']
          l,n=Db[:col_language],'original.nationality'
          validate_length(s,l,n)
        end
        self
      end
      def notes
        a=@s.split(/\n%\s.+?$|[ ]*\n[ ]*/m)
        @h=build_hash(a)
        def description
          s=@h['description']
          l,n=Db[:col_info_note],'notes.description'
          validate_length(s,l,n)
        end
        def abstract
          s=@h['abstract']
          l,n=Db[:col_info_note],'notes.abstract'
          validate_length(s,l,n)
        end
        def comment
          s=@h['comment']
          l,n=Db[:col_info_note],'notes.comment'
          validate_length(s,l,n)
        end
        def coverage
          s=@h['coverage']
          l,n=Db[:col_info_note],'notes.coverage'
          validate_length(s,l,n)
        end
        def relation
          s=@h['relation']
          l,n=Db[:col_info_note],'notes.relation'
          validate_length(s,l,n)
        end
        def source
          s=@h['source']
          l,n=Db[:col_txt_long],'notes.source'
          validate_length(s,l,n)
        end
        def history
          s=@h['history']
          l,n=Db[:col_txt_long],'notes.history'
          validate_length(s,l,n)
        end
        def type
          s=@h['type']
          l,n=Db[:col_txt_long],'notes.relation'
          validate_length(s,l,n)
        end
        def format
          s=@h['format']
          l,n=Db[:col_txt_short],'notes.format'
          validate_length(s,l,n)
        end
        def prefix
          @h['prefix']
        end
        self
      end
    end
    class Instructions
      @doc={ lv: [] }
      @doc[:fns],@doc[:fnb],@doc[:scr_suffix]='','',''
      @@publisher='SiSU scribe'
      attr_accessor :make,:env,:path,:file,:fn,:fns,:fno,:fnb,:fnn,:fnt,:fnl,:flv,:fnz,:fnstex,:ocn,:sfx_src,:pdf,:file_type,:dir_out,:dir_tex,:dir_lout,:txt_path,:sisu,:sisu_version,:ruby_version,:title,:subtitle,:full_title,:html_title,:subtitle_tex,:creator,:classify,:author_home,:author,:author_title,:author_nationality,:authors,:authorship,:translator,:illustrator,:prepared_by,:digitized_by,:subject,:description,:publisher,:current_publisher,:contributor,:date,:date_created,:date_issued,:date_available,:date_valid,:date_modified,:date_translated,:date_added_to_site,:date_scheme,:date_created_scheme,:date_issued_scheme,:date_available_scheme,:date_valid_scheme,:date_modified_scheme,:type,:format,:identifier,:source,:language,:language_original,:relation,:coverage,:rights,:keywords,:comments,:abstract,:cls_loc,:cls_dewey,:cls_pg,:cls_isbn,:papersize,:papersize_array,:toc,:lv0,:lv1,:lv2,:lv3,:lv4,:lv5,:lv6,:lvs,:pagenew,:pagebreak,:pageline,:num_top,:bold_match_list,:italics_match_list,:substitution_match_list,:emphasis_set_to,:toc_lev_limit,:flag_endnotes,:flag_auto_endnotes,:flag_separate_endnotes,:flag_separate_endnotes_make,:markup,:markup_instruction,:flag_tables,:vocabulary,:doc_css,:yaml,:lnk,:links,:prefix_a,:prefix_b,:suffix,:information,:contact,:icon,:image,:ad_url,:ad_png,:ad_alt,:ad_began,:flag_promo,:promo,:ad_home,:stmp,:stmpd,:sc_filename,:sc_number,:sc_date,:sc_time,:sc_info,:yamladdr,:locale,:wc_lines,:wc_words,:wc_bytes,:file_encoding,:filesize,:user,:home,:hostname,:pwd,:firstseg,:programs,:author_copymark,:i18n,:lang,:lang_code_insert,:en,:notes,:dgst,:generated,:tags,:tag_array,:concord_make,:seg_names,:seg_autoname_safe,:set_header_title,:set_heading_top,:set_heading_seg,:heading_seg_first,:heading_seg_first_flag,:base_program,:ec,:opt,:sem_tag,:book_idx,:topic_register,:topic_register_array,:original,:writing_focus,:audio,:daisy,:home_button_image,:home_button_links,:footer_links,:cover_image,:man_section
      def initialize(fns_array,opt)
        @env=@path,@file=@fn=@fns=@fno=@fnb=@fnn=@fnt=@fnl=@flv=@fnz=@fnstex=@ocn=@sfx_src=@pdf=@file_type=@dir_out=@dir_tex=@dir_lout=@txt_path=@make=@flag_endnotes=@flag_auto_endnotes=@flag_separate_endnotes=@flag_separate_endnotes_make=@sisu=@sisu_version=@ruby_version=@title=@subtitle=@full_title=@html_title=@subtitle_tex=@creator=@classify=@author_home=@author=@author_title=@author_nationality=@translator=@illustrator=@prepared_by=@digitized_by=@subject=@description=@publisher=@current_publisher=@contributor=@date=@date_created=@date_issued=@date_available=@date_valid=@date_modified=@date_translated=@date_added_to_site=@date_scheme=@date_created_scheme=@date_issued_scheme=@date_available_scheme=@date_valid_scheme=@date_modified_scheme=@type=@format=@identifier=@source=@language=@language_original=@relation=@coverage=@rights=@keywords=@comments=@abstract=@cls_loc=@cls_dewey=@cls_pg=@cls_isbn=@papersize=@toc=@lv0=@lv1=@lv2=@lv3=@lv4=@lv5=@lv6=@pagenew=@pagebreak=@pageline=@num_top=@bold_match_list=@italics_match_list=@substitution_match_list=@emphasis_set_to=@toc_lev_limit=@flag_tables=@vocabulary=@doc_css=@yaml=@lnk=@links=@prefix_a=@prefix_b=@suffix=@information=@contact=@icon=@ad_url=@ad_png=@ad_alt=@ad_began=@promo=@ad_home=@stmp=@stmpd=@sc_filename=@sc_number=@sc_date=@sc_time=@sc_info=@yamladdr=@locale=@wc_lines=@wc_words=@wc_bytes=@file_encoding=@filesize=@firstseg=@programs=@author_copymark=@i18n=@lang=@lang_code_insert=@en=@notes=@dgst=@generated=@heading_seg_first=@base_program=@topic_register=@original=@writing_focus=@audio=@home_button_image=@home_button_links=@cover_image=@man_section=nil
        @data,      @path,  @fns,   @fno,   @opt=
          fns_array,opt.pth,opt.fns,opt.fno,opt #@data used as data
        @flag_tables,@set_header_title,@set_heading_top,@set_heading_seg,@heading_seg_first_flag,@flag_promo,@book_idx=
          false,     false,            false,           false,           false,                  false,      false
        @seg_autoname_safe=true
        @daisy,@sem_tag=false,false
        @authorship,@markup_instruction,@image='','','','' #check which other values should be set to empty rather than nil
        @markup=@markup_instruction #use @markup_instruction
        @doc,@fn,@make_italic,@tag_hash,@ec={},{},{},{},{},{}
        @flv,@lang,@seg_names,@tags,@tag_array,@tag_a,@ec[:image],@ec[:audio],@ec[:multimedia]=Array.new(9){[]}
        @authors,@topic_register_array,@papersize_array=[],[],[]
        @lvs=[nil,0,0,0,0,0,0]
        @emphasis_set_to='bold'
        @lang_code_insert=SiSU_Env::FilenameLanguageCodeInsert.new(@opt).language_code_insert
        @footer_links= { left: { say: '', url: '' }, center: { say: '', url: '' } }
        @rgx_image=/(?:^|[^_\\])\{(?:\s*|\~\^\s+)(\S+?\.(?:png|jpg|gif)\b)/m
        @rgx_audio=/\{\s*(\S+?\.(?:mp3|ogg))/
        @rgx_mm=/\{\s*(\S+?\.(?:ogg|mpeg))/ #expand and distinguish ogg
        Dir.chdir(@opt.f_pth[:pth])
        begin
        rescue
          SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@fns).location do
            __LINE__.to_s + ':' + __FILE__
          end
        ensure
        end
        @header_make_links_append=:no
        common_makes=(defined? @opt.make_instructions_pod) \
        && @opt.make_instructions_pod !=nil \
        && @opt.make_instructions_pod[:makeset]==true \
        ? @opt.make_instructions_pod
        : @opt.make_instructions
        if common_makes[:makeset]
          @pagenew=common_makes[:pagenew]
          @pagebreak=common_makes[:pagebreak]
          @pageline=common_makes[:pageline]
          @toc=common_makes[:toc]
          @lv0=common_makes[:lv0]
          @lv1=common_makes[:lv1]
          @lv2=common_makes[:lv2]
          @lv3=common_makes[:lv3]
          @lv4=common_makes[:lv4]
          @lv5=common_makes[:lv5]
          @lv6=common_makes[:lv6]
          @num_top=common_makes[:num_top]
          @i18n=common_makes[:i18n]
          @man_section=common_makes[:man_section]
          @emphasis_set_to=common_makes[:emphasis_set_to]
          @bold_match_list=common_makes[:bold_match_list]
          @italics_match_list=common_makes[:italics_match_list]
          @substitution_match_list=common_makes[:substitution_match_list]
          @footer_links=common_makes[:footer_links]
          @home_button_links=common_makes[:home_button_links]
          @home_button_image=common_makes[:home_button_image]
          @cover_image=common_makes[:cover_image]
          @lnk=@links=common_makes[:links]
          @header_make_links_append=common_makes[:links_append]
        end
      end
      #protected
      def extract
        begin
          @user,@home,@hostname,@pwd=ENV['USER'],ENV['HOME'],ENV['HOSTNAME'],ENV['PWD']
          @programs,@wc,@language,@language_original={},{},{},{}
          @en={ sum: 0, mark: 0, note: 0, mismatch: 0 }
          @prog=SiSU_Env::InfoSettings.new
          @sys=SiSU_Env::SystemCall.new
          @env=SiSU_Env::InfoEnv.new(@fns) #watch
          if (@opt.act[:verbose_plus][:set]==:on \
          || @opt.act[:maintenance][:set]==:on)
            puts 'system locale: ' + @sys.locale
          end
          if @prog.wc \
          and @sys.wc
            wc=%x{wc #{fns}}
            wca=wc.scan(/\d+/)
            @wc_lines,@wc_words,@wc_bytes=wca[0].to_i,wca[1].to_i,wca[2].to_i
          else
            fns_a=@data.dup
            tmp=fns_a.join
            fns_a=tmp.scan(/\S+/)
            @wc_words=fns_a.length
            fns_a=tmp=nil
          end
          @concord_make=(@wc_words > @env.concord_max) ? false : true
          @locale=@sys.locale
          @file_encoding=@sys.file_encoding(fns,@opt.act)
          # programs set here for things that affect output appearance only
          @programs[:pdf]=SiSU_Env::SystemCall.new.program_found?('pdflatex')
          if @opt.act[:psql][:set] == [:ok]
            m=/((.+?)(?:\~\w\w(?:_\w\w)?)?)\.((?:-|ssm\.)?sst|ssm|ssi)$/ #watch added match for sss
            @fnn,@fnb,@fnt=@fns[m,1],@fns[m,2],@fns[m,3]
            @flv=@env.document_language_versions_found[:f]
          else
            m=/((.+?)(?:\~\w\w(?:_\w\w)?)?)\.((?:-|ssm\.)?sst|ssm)$/ #watch added match for sss
            @fnn,@fnb,@fnt=@fns[m,1],@fns[m,2],@fns[m,3]
            @flv=@env.document_language_versions_found[:f]
            @fnz=(@fns =~/\.(?:ssm\.sst|ssm)$/) ? (@fnn + '.ssm.txz') : (@fnn + '.sst.txz')
          end
          @papersize=@env.papersize #'A4' #default size #get first from SiSU_Env:: # @env is probably no longer most appropriate name! as default info is more general
          @sfx_src=@fns[m,2]
          if @fns =~ /(?:-|ssm\.)?sst$/ \
          and not @opt.act[:psql][:set] == [:ok]
            @env_out_root=@env.path.output
            @dir_out="#{@env.path.output}/#{@fnb}"
            @dir_tex=@env.processing_path.tex
            @dir_lout=@env.processing_path.lout
            @@publisher='SiSU http://www.jus.uio.no/sisu'
          end
          @txt_path=@txt_path ||= @env.path.output
          @stmp=%{#{@fns}}[/^(.+?)\..*/m,1]
          @fnstex=@fns.gsub(/_/,'\_\-').gsub(/\./,'.\-')
          @flag_endnotes,@flag_auto_endnotes,@flag_separate_endnotes=false,false,false
          @flag_separate_endnotes_make=true
          ver=SiSU_Env::InfoVersion.instance
          @sisu_version=ver.get_version
          @ruby_version=ver.rbversion
          @generated=Time.now
          fns_array=@data.dup
          skip unless fns_array                                                    # consider
          @code_flag=false
          fns_array.each do |para|                                               #% scan document
            if para !~/^%+\s/ \
            and para =~/<![abcdeghijklmnopqrstuvwxyz]/i # <!f not included
              raise "Old markup style in file #{@fns}, current version #{@sisu_version[:project]} #{@sisu_version[:version]} #{@sisu_version[:date_stamp]} #{@sisu_version[:date]}:\n\t\t#{para}\n\n"
            end
            @code_flag=case para
            when /^code\{\s*$/ then true
            when /^\}code\s*$/ then false
            else                    @code_flag
            end
            regx_header=/^@\S+?:[+-]?\s/
            if para =~regx_header \
            and not @code_flag #or para=~/^(?:1|:?A)~/
              case para
              when /^@title:(.+)/m                                               #% * header metadata - title
                @title=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).title
              when /^@creator:(.+)/m                                             #% * header metadata - creator
                @creator=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).creator
                @authorship=@author=@creator.author
                @authors=@creator.author_detail
              when /^@date:(.+)/m                                                #% * header metadata - date
                @date=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).date
              when /^@publisher:\s+(.+)/m                                        #% * header metadata - publisher
                @publisher=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).current_publisher
                @current_publisher=@publisher
              when /^@rights:(.+)/m                                              #% * header metadata - rights
                @rights=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).rights
              when /^@classify:(.+)/m                                            #% * header metadata - classify
                @classify=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).classify
              when /^@identifier:(.+)/m                                          #% * header metadata - identifier
                @identifier=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).identifier
              when /^@original:(.+)/m                                            #% * header metadata - original (document)
                @original=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).original
                @source=@original.source
              when /^@notes?:\s(.+)\Z/m                                          #% * header metadata - notes
                @notes=SiSU_Param::Parameters::Md.new($1.strip,@opt,@env).notes
              when /^@links:\s+(.+?)\Z/m                                         #% * header metadata - links
                links=SiSU_Param::Parameters::MdMake.new($1.strip,@opt,@env).make_links.links
                @lnk=@links=if @header_make_links_append == :yes
                  (links) \
                    ? (links + @links)
                    : @links
                else
                  (links) \
                    ? (links)
                    : @links
                end
              when /^@make:(.+)/m                                                #% * header processing - make
                @make=SiSU_Param::Parameters::MdMake.new($1.strip,@opt,@env).make
                makes=SiSU_Param_Make::MakeHead.new(@make).make_instruct
                @pagenew=(makes[:pagenew]) \
                  ? (makes[:pagenew]) \
                  : @pagenew
                @pagebreak=(makes[:pagebreak]) \
                  ? (makes[:pagebreak]) \
                  : @pagebreak
                @pageline=(makes[:pageline]) \
                  ? (makes[:pageline]) \
                  : @pageline
                @toc=(makes[:toc]) ? (makes[:toc]) : @toc
                @lv0=(makes[:lv0]) ? (makes[:lv0]) : @lv0
                @lv1=(makes[:lv1]) ? (makes[:lv1]) : @lv1
                @lv2=(makes[:lv2]) ? (makes[:lv2]) : @lv2
                @lv3=(makes[:lv3]) ? (makes[:lv3]) : @lv3
                @lv4=(makes[:lv4]) ? (makes[:lv4]) : @lv4
                @lv5=(makes[:lv5]) ? (makes[:lv5]) : @lv5
                @lv6=(makes[:lv6]) ? (makes[:lv6]) : @lv6
                @num_top=
                  (makes[:num_top]) \
                  ? (makes[:num_top]) \
                  : @num_top
                @substitution_match_list=
                  (makes[:substitution_match_list]) \
                  ? (makes[:substitution_match_list]) \
                  : @substitution_match_list
                @bold_match_list=
                  (makes[:bold_match_list]) \
                  ? (makes[:bold_match_list]) \
                  : @bold_match_list
                @italics_match_list=
                  (makes[:italics_match_list]) \
                  ? (makes[:italics_match_list]) \
                  : @italics_match_list
                @emphasis_set_to=
                  (makes[:emphasis_set_to]) \
                  ? (makes[:emphasis_set_to]) \
                  : @emphasis_set_to
                @i18n=
                  (makes[:i18n]) \
                  ? (makes[:i18n]) \
                  : @i18n
                @man_section=
                  (makes[:man_section]) \
                  ? (makes[:man_section]) \
                  : @man_section
                @footer_links=
                  (makes[:footer_links]) \
                  ? (makes[:footer_links]) \
                  : @footer_links
                @home_button_links=
                  (makes[:home_button_links]) \
                  ? (makes[:home_button_links]) \
                  : @home_button_links
                @home_button_image=
                  (makes[:home_button_image]) \
                  ? (makes[:home_button_image]) \
                  : @home_button_image
                @cover_image=
                  (makes[:cover_image]) \
                  ? (makes[:cover_image]) \
                  : @cover_image
              end
              @lv0 ||=/^0~/
              @lv1 ||=/^1~/
              @lv2 ||=/^2~/
              @lv3 ||=/^3~/
              @lv4 ||=/^4~/
              @lv5 ||=/^5~/
              @lv6 ||=/^6~/
            else                                                                 #% *
              l_0=l_1=l_2=l_3=l_4=l_5=''
              if defined? @make.headings[0]
                l_0=if defined? @make.headings[0][0] \
                and @make.headings[0][0] =~/\S+/
                  "|^#{@make.headings[0][0]}"
                end
                l_1=if defined? @make.headings[0][1] \
                and @make.headings[0][1] =~/\S+/
                  "|^#{@make.headings[0][1]}"
                end
                l_2=if defined? @make.headings[0][2] \
                and @make.headings[0][2] =~/\S+/
                  "|^#{@make.headings[0][2]}"
                end
                l_3=if defined? @make.headings[0][3] \
                and @make.headings[0][3] =~/\S+/
                  "|^#{@make.headings[0][3]}"
                end
                l_4=if defined? @make.headings[0][4] \
                and @make.headings[0][4] =~/\S+/
                  "|^#{@make.headings[0][4]}"
                end
                l_5=if defined? @make.headings[0][5] \
                and @make.headings[0][5] =~/\S+/
                  "|^#{@make.headings[0][5]}"
                end
              end
              case para
              #when /^:?A~/
              when /^:?B~#{l_0}/
                @lvs[1]=1
              when /^:?C~#{l_1}/
                @lvs[2]=1
              when /^:?D~#{l_2}/
                @lvs[3]=1
              when /^1~#{l_3}/
                @lvs[4]=1
              when /^2~#{l_4}/
                @lvs[5]=1
              when /^3~#{l_5}/
                @lvs[6]=1
              end
              if para =~ /^:?A~/                                                  #% processing
                if not defined? @title.full.nil?
                  tf=para[/^:A~\S*(.+)$/m,1]
                  tf="@title: #{tf}"
                  @title=SiSU_Param::Parameters::Md.new(tf.strip,@opt,@env).title
                end
                creator=(@creator.is_a?(SiSU_Param::Parameters::Md) \
                && defined? @creator.author \
                && @creator.author.is_a?(String)) \
                ? " #{@creator.author}"
                : ''
                title=@title.full.gsub(/\s*(?:<p>|<p \/>|<br>|<br \/>)\s*/,' ').
                  gsub(/~\{.+?\}~/,'')
                SiSU_Screen::Ansi.new(
                  @opt.act[:color_state][:set],
                  'Document Parameters',
                  %{#{title}#{creator}}
                ).txt_grey if @opt.act[:verbose][:set]==:on
              end
              if not @book_idx \
              and para =~/^=\{(.+?)\}[\s`]*\Z/m
                @book_idx=true
              end
              unless @code_flag
                case para
                when /~\{\s+.+?\}~/m                                             #% processing
                  en=para.scan(/~\{.+?\}~/m)
                  en.each { |e| @en[:sum] +=1 }
                when /~\^(?:\s|$)/m                                              #% processing
                  mk=para.scan(/~\^(?:\s|$)/)
                  mk.each { |e| @en[:mark] +=1 }
                when /^\^~\s+\S/ then @en[:note] +=1                             #% processing
                end
              end
              if para =~/~\{|\^~ |~\^|\{.+?\[[1-6]\]\}\S+?\.ss[tm]/m
                @flag_auto_endnotes,@flag_endnotes=true,true
              end
              if para =~/^(?:table\{|\{table)/i
                @flag_tables=true
              end
            end
            if para =~/^:?A~/
              @set_heading_top=true
            end
            if para =~/^1~/
              m=nil
              if para =~/^1~(\S+)\s+(.+)$/
                m,t=$1,$2
              elsif para =~/^1~\s+(.+)$/
                t=$1
              end
              unless @heading_seg_first_flag                                     # extract first segment name
                @heading_seg_first=t
                @heading_seg_first_flag=true
              end
              if m                                                               # list all segment names
                @seg_names << m
                @set_heading_seg=true
                if m=~/^\d{1,3}/ \
                and m !~/^0/
                  @seg_autoname_safe=false
                end
              end
            end
            para=para.gsub(/<:=(\S+?)>/,'{ c_\1.png 14x14 }image')               # embedded symbol (image)
            if para !~/^%+\s/ \
            and para =~@rgx_image
              @ec[:image] << para.scan(@rgx_image).uniq
            end
            @ec[:audio] << para.scan(@rgx_audio).uniq if para =~@rgx_audio #embedded content
            @ec[:multimedia] << para.scan(@rgx_mm).uniq if para =~@rgx_mm #embedded content
            unless @sem_tag
              @sem_tag=true if para=~/[:;]\{.+?\}[:;][a-z+]/ #refix later
            end
          end                                                                    #% here endeth the document loop
          unless @make
            if (@opt.act[:verbose_plus][:set]==:on \
            || @opt.act[:maintenance][:set]==:on)
              SiSU_Screen::Ansi.new(
                @opt.act[:color_state][:set],
                '@make:',
                'header absent'
              ).warn
            end
            @make=SiSU_Param::Parameters::MdMake.new('@make: ',@opt,@env).make
          end
          if @cover_image \
          and @cover_image.is_a?(Hash) \
          and (@cover_image[:cover] =~@rgx_image \
            or @cover_image[:cover] =~/\S+?.(?:jpg|png|gif)/)
            @ec[:image] << @cover_image[:cover]
          end
          if @home_button_image \
          and @home_button_image.is_a?(Hash) \
          and (@home_button_image =~@rgx_image \
            or @home_button_image =~/\S+?\.(?:jpg|png|gif)/)
            @ec[:image] << @home_button_image
          end
          if @ec[:image].length > 0
            @ec[:image]=@ec[:image].flatten.uniq
            @ec[:image].delete_if {|x| x =~/https?:\/\// }
            @ec[:image]=@ec[:image].sort
          end
          @ec[:audio]=@ec[:audio].uniq.flatten.sort
          @ec[:multimedia]=@ec[:multimedia].uniq.flatten.sort
          unless @rights
            if defined? @creator.author \
            and @creator.author.is_a?(String) \
            and defined? @date.published \
            and @date.published.is_a?(String)
              @rights=SiSU_Param::Parameters::MdDefault.new.rights(@creator.author,@date.published)
            elsif defined? @creator.author \
            and @creator.author.is_a?(String)
              @rights=SiSU_Param::Parameters::MdDefault.new.rights("[#{@creator.author}]",'')
            end
          end
          if defined? @classify.topic_register \
          and @classify.topic_register.is_a?(String) \
          and @classify.topic_register.length >3
             topic_register=@classify.topic_register
             u=topic_register.scan(/[^;]+/m).sort
             v=[]
             u.each do |l|
               v << l.scan(/[^:]+/m)
             end
             v.each do |s|
               s[-1]=s[-1].scan(/[^|]+/m) if s[-1] =~/[|]/m
               @topic_register_array << s
             end
             @topic_register_array
          end
          if @i18n
            @i18n=@i18n.uniq
            @i18n << 'en' unless @i18n.find_index("en")
          else
            @i18n=[ 'en' ]
          end
          translated=[]
          translate_list=[@pagenew,@pagebreak,@pageline,@num_top,@toc_lev_limit]
          translate_list.each do |t|
            translate=t.to_s if t
            translated << if translate
              translate.gsub!(/3/,'6')
              translate.gsub!(/2/,'5')
              translate.gsub!(/1/,'4')
              translate.gsub!(/:?C/,'3')
              translate.gsub!(/:?B/,'2')
              translate.gsub!(/:?A/,'1')
              # looks like an ok substituion for the above but is not, causes problems, check why
              #translate=translate.gsub(/3/,'6').
              #  gsub(/2/,'5').
              #  gsub(/1/,'4').
              #  gsub(/:?C/,'3').
              #  gsub(/:?B/,'2').
              #  gsub(/:?A/,'1')
              translate=(translate =~/^\d+$/) \
              ? translate.to_i
              : translate
            else nil
            end
          end
          @pagenew,@pagebreak,@pageline,@num_top,@toc_lev_limit=translated
          @markup=@markup.gsub(/page_new\s*=\s*([\dA-C])/,"page_new=#{@pagenew}").
            gsub(/page_break\s*=\s*([\dA-C])/,"page_break=#{@pagebreak}").
            gsub(/page_line\s*=\s*([\dA-C])/,"page_line=#{@pageline}").
            gsub(/num_top\s*=\s*([\dA-C])/,"num_top=#{@num_top}").
            gsub(/toc_lev_limit\s*=\s*([\dA-C])/,"toc_lev_limit=#{@toc_lev_limit}")
          papersize_array_rc=@papersize.downcase.scan(/(?:a4|letter|legal|book|a5|b5)/)
          papersize_array_opt=[
            ((@opt.act[:pdf_a4][:set]==:on)     ? 'a4'     : ''),
            ((@opt.act[:pdf_a5][:set]==:on)     ? 'a5'     : ''),
            ((@opt.act[:pdf_b5][:set]==:on)     ? 'b5'     : ''),
            ((@opt.act[:pdf_letter][:set]==:on) ? 'letter' : ''),
            ((@opt.act[:pdf_legal][:set]==:on)  ? 'legal'  : ''),
          ] - [""]
          @papersize_array=(papersize_array_opt.length > 0) \
          ? papersize_array_opt
          : papersize_array_rc
          fn=@opt.fno #decide what to do a filesize on .ssm tells very little about actual document size
          @filesize=(File.size(fn)).to_s
          if @sys.openssl !=false \
          and FileTest.file?(@env.source_file_with_path)
            @dgst=[]
            case @env.digest(@opt).type
            when :sha512
              dgst=@sys.sha512(@env.source_file_with_path)
              @dgst=dgst[1].length==128 ? dgst : nil
              puts 'check document (sha512) digest' if not @dgst
            when :sha256
              dgst=@sys.sha256(@env.source_file_with_path)
              @dgst=dgst[1].length==64 ? dgst : nil
              puts 'check document (sha256) digest' if not @dgst
            when :md5
              dgst=@sys.md5(@env.source_file_with_path)
              @dgst=dgst[1].length==32 ? dgst : nil
              puts 'check document (md5) digest' if not @dgst
            else
              dgst=@sys.sha256(@env.source_file_with_path)
              @dgst=dgst[1].length==64 ? dgst : nil
              puts 'check document (sha256) digest' if not @dgst
            end
          elsif not FileTest.file?(@env.source_file_with_path)
            #puts SiSU_Utils::CodeMarker.new(__LINE__,__FILE__).set(:fuchsia)
          end
          @publisher ||= "#{@@publisher} (this copy)"
          fn_set_lang=SiSU_Env::StandardiseLanguage.new(@opt.lng).language
          unless @language[:code] \
          and @language[:name]
            lang=@env.i18n.language #default language settings for directory by name, or in sysrc.yml
            @language[:code] ||= lang.code
            @language[:name] ||= lang.title
          end
          unless fn_set_lang[:d]==true #decide, naming convention overrides other settings, within document, etc.
            @language[:code]=fn_set_lang[:c]
            @language[:name]=fn_set_lang[:n]
          end
          @fnl=@env.i18n.lang_filename(fn_set_lang[:c])
          @lang=@lang.uniq
          @fn=SiSU_Env::EnvCall.new(@fns).lang(fn_set_lang[:c])
          if @en[:note] > 0 \
          and @en[:sum] > 0
            if @en[:sum] > 0
            else
              SiSU_Screen::Ansi.new(
                @opt.act[:color_state][:set],
                '*WARN* both endnote styles used',
                "~{ #{@en[:sum]} }~ and ^~ #{@en[:mark]}"
              ).warn unless @opt.act[:quiet][:set]==:on
            end
          end
          if @en[:mark] != @en[:note] \
          and @en[:note] > 0
            @en[:mismatch]=@en[:note] - @en[:mark]
            SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              '*WARN* endnote number mismatch',
              "endnotes: #{@en[:note]} != endnote reference marks: #{@en[:mark]} (difference = #{@en[:mismatch]})"
            ).warn unless @opt.act[:quiet][:set]==:on
            footnote_conversion_errors=File.new("#{Dir.pwd}/footnote_conversion_errors.txt",'a')
            footnote_conversion_errors <<
              "#{@fns}:\n\tendnotes: #{@en[:note]} != endnote reference marks: #{@en[:mark]} (difference = #{@en[:mismatch]})\n"
          end
          if not @title \
          or not defined? @title.main \
          or @title.main !~/[\S]/
            if @fns =~/\.ssm$/ \
            and  @opt.inspect =~/P/
              #@title=Md.new('Text Insert',@opt,@env).title
            else
              SiSU_Screen::Ansi.new(
                @opt.act[:color_state][:set],
                'WARNING: Document Title missing',
                'please provide @title:'
              ).warn unless @opt.act[:quiet][:set]==:on
            end
          end
          if @author !~/[\S]/
            if @fns =~/\.ssm$/ \
            and  @opt.inspect =~/P/
              #@creator=SiSU_Param::Md.new('Text Insert',@opt,@env).creator
            else
              SiSU_Screen::Ansi.new(
                @opt.act[:color_state][:set],
                'WARNING: Document Author missing',
                'please provide @creator: :author:'
              ).warn unless @opt.act[:quiet][:set]==:on
            end
          end
          @struct={}
          doc_struct=Hash.new(0)
          if @lv1.nil?
            fns_array.each do |para|
              if para =~/^(Part|Chapter|Section|Article)\b/i
                case para
                when /^(Part|PART)\b/
                  @struct[:part]=doc_struct[:part]
                  doc_struct[:part]=doc_struct[:part] + 1
                when /^(Chapter|CHAPTER)\b/
                  @struct[:chapter]=doc_struct[:chapter]
                  doc_struct[:chapter]=doc_struct[:chapter] + 1
                when /^(Section|SECTION)\b/
                  @struct[:section]=doc_struct[:section]
                  doc_struct[:section]=doc_struct[:section] + 1
                when /^(Article|ARTICLE)\b/
                  @struct[:article]=doc_struct[:article]
                  doc_struct[:article]=doc_struct[:article] + 1
                when /^(Clause|CLAUSE)\b/
                  @struct[:clause]=doc_struct[:clause]
                  doc_struct[:clause]=doc_struct[:clause] + 1
                when /^\d\..*[^\.]$/
                  @struct[:number]=doc_struct[:number]
                  doc_struct[:number]=doc_struct[:number] + 1
                end
              end
            end
            if doc_struct[:article] > 2                                            #%~level 4
              @lv4=/^(?:Article|ARTICLE)\b/
            elsif doc_struct[:chapter] > 2 \
            and doc_struct[:article] \
            and doc_struct[:article] < 3
              @lv4=/^(?:Chapter|CHAPTER)\b/
            elsif doc_struct[:clause] > 2
              @lv4=/^(?:Clause|CLAUSE)\b/
            elsif doc_struct[:number] > 2
              @lv4="^\d\..*[^\.]$"
            end
            if doc_struct[:section] > 2                                           #%~level 3
              @lv3=/^(?:Section|SECTION)\b/
            end
            if doc_struct[:chapter] > 2 \
            and doc_struct[:article] \
            and doc_struct[:article] > 2
              @lv2=/^(?:Chapter|CHAPTER)\b/
            end
            if doc_struct[:part] > 2 \
            and @lv[2].nil?
              @lv2=/^(?:Part|PART)\b/
            end
            if doc_struct[:part] > 2 \
            and @lv[2].inspect !~/Part/ \
            and @lv[1].nil?
              @lv1=/^(Part|PART)\b/
            end
          end
          @lnk=@lnk.compact if @lnk
          @lv0 ||=/^0~/
          @lv1 ||=/^1~/
          @lv2 ||=/^2~/
          @lv3 ||=/^3~/
          @lv4 ||=/^4~/
          @lv5 ||=/^5~/
          @lv6 ||=/^6~/
          @data=nil #else whole file's contents are stored in md pstore & is not required to be... big waste actually
          @file=SiSU_Env::FileOp.new(self) #watch
          Store.new(self,@env).store                                             #% pstore
          self
        rescue
          if @opt.act[:harvest][:set]==:on
            exit
          end
        end
      end
      private
      class Store
        def initialize(md,env)
          @md,@env=md,env
        end
        def store
          begin
            pstorefile="#{@env.processing_path.ao}/#{@md.fns}.pstore"
            File.unlink(pstorefile) if FileTest.file?(pstorefile)
            if (@md.opt.act[:verbose_plus][:set]==:on \
            || @md.opt.act[:maintenance][:set]==:on)
              SiSU_Screen::Ansi.new(
                @md.opt.act[:color_state][:set],
                "PStore -> #{pstorefile}"
              ).txt_grey
            end
            store=PStore.new(pstorefile)
            store.transaction do
              store['md']=@md
              store.commit
            end
            @@md=@md=nil
          rescue
            SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
              __LINE__.to_s + ':' + __FILE__
            end
          ensure
          end
        end
      end
    end
  end
  class Instantiate
    def param_instantiate
      @@date=SiSU_Env::InfoDate.new
      @@proc=
        @@filename_txt=
        @@filename_texinfo=
        @@filename_lout_portrait=
        @@filename_lout_landscape=
        @@filename_html_scroll=
        @@filename_html_index=
        @@filename_html_segtoc=
        @@filename_semantic=
        @@filename_rss=
        @@newfile=
        @@drr=
        nil
      @doc={
       initialise: nil,
       markup: '',
       lnks: '',
       stmp: '',
       prefix_a: '',
       prefix_b: '',
       req: {}
      }
      @@yaml=@@yamladdr=nil
      @@flag={}
      @@publisher='SiSU scribe'
    end
  end
end
__END__
