<?xml version="1.0" encoding="UTF-8"?>

<!-- ====================================================================== -->
<!-- = chapter-9.xml                                                      = -->
<!-- = afnix programmer's guide chapter 9                                 = -->
<!-- ====================================================================== -->
<!-- = This  program  is  free  software; you  can redistribute it and/or = -->
<!-- = modify it provided that this copyright notice is kept intact.      = -->
<!-- = 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. In no event = -->
<!-- = shall  the  copyright  holder be liable for any  direct, indirect, = -->
<!-- = incidental  or special  damages arising  in any way out of the use = -->
<!-- = of this software.                                                  = -->
<!-- ====================================================================== -->
<!-- = copyright (c) 2005-2007 - amaury darsch                            = -->
<!-- ====================================================================== -->

<chapter volume="1" number="9">
  <title>Librarian and resolver</title>

  <p>
  This chapter covers the use of the <command>axl</command> librarian
  utility as well as the <code>Librarian</code> object. The file path
  resolver is also described as a mean to search for a particular file
  to execute in a program.
  </p>

  <!-- librarian object -->
  <section>
    <title>Librarian object</title>

    <p>
    A <em>librarian file</em> is a special file that acts as a
    containers for various files. A librarian file is created with the
    <command>axl</command> -- <afnix/> cross librarian --
    utility. Once a librarian file is created, it can be added to the
    interpreter resolver. The file access is later performed
    automatically by name with the standard interpreter
    <code>load</code> method.
    </p>

    <!-- creating a librarian -->
    <subsect>
      <title>Creating a librarian</title>

      <p>
      The <command>axl</command> utility is the preferred way to
      create a librarian. Given a set of files, <command>axl</command>
      combines them into a single one.
      </p>

      <example>
      zsh: axl -h
      usage: axl [options] [files]
             [-h]      print this help message
             [-v]      print version information
             [-c]      create a new librarian
             [-x]      extract from the librarian
             [-s]      get file names from the librarian
             [-t]      report librarian contents
             [-f] lib  set the librarian file name
      </example>

      <p>
      The <option>-c</option> option creates a new librarian. The
      librarian file name is specified with the <option>-f</option>
      option.
      </p>

      <example>
      zsh: axl -c -f librarian.axl file-1.als file-2.als
      </example>

      <p>
      The previous command combines <file>file-1.als</file> and
      <file>file-2.als</file> into a single file called
      <file>librarian.axl</file> . Note that any file can be included
      in a librarian.
      </p>
    </subsect>

    <!-- using the librarian -->
    <subsect>
      <title>Using the librarian</title>

      <p>
      Once a librarian is created, the interpreter <option>-i</option>
      option can be used to specify it. The <option>-i</option> option
      accepts either a directory name or a librarian file. Once the
      librarian has been opened, the interpreter <code>load</code>
      method can be used as usual.
      </p>

      <example>
      zsh&gt; axi -i librarian.axl
      afnix&gt; interp:load "file-1.als"
      afnix&gt; interp:load "file-2.als"
      </example>
      
      <p>
      The librarian acts like a <em>file archive</em>. The interpreter
      file resolver takes care to extract the file from the librarian
      when the <code>load</code> method is invoked.
      </p>
    </subsect>
      
    <!-- librarian contents -->
    <subsect>
      <title>Librarian contents</title>

      <p>
      The <command>axl</command> utility provides the
      <option>-t</option> and <option>-s</option> options to look at the
      librarian contents. The <option>-s</option> option returns all
      file name in the librarian. The <option>-t</option> option
      returns a one line description for each file in the librarian.
      </p>

      <example>
      zsh: axl -t -f librarian.axl
      --------       1234 file-1.als
      --------       5678 file-2.als
      </example>
      
      <p>
      The one line report contains the file flags, the file size and
      the file name. The file flags are not used at this time. One
      possible use in the future is for example, an <em>auto-load
      bit</em> or any other useful things.
      </p>
    </subsect>

    <!-- librarian extraction -->
    <subsect>
      <title>Librarian extraction</title>
      
      <p>
      The <option>-x</option> option permits to extract file from the
      librarian. Without any file argument, all files are
      extracted. With some file arguments, only those specified files
      are extracted.
      </p>

      <example>
      zsh: axl -x -f librarian.axl
      zsh: axl -x -f librarian.axl file-1.als
      </example>
    </subsect>
  </section>

  <!-- librarian object -->
  <section>
    <title>Librarian object</title>

    <p>
    The <code>Librarian</code> object can be used within an
    <afnix/> program as a convenient way to create a collection of
    files or to extract some of them.
    </p>

    <!-- output librarian -->
    <subsect>
      <title>Output librarian</title>
      
      <p>
      The <code>Librarian</code> object is a standard <afnix/>
      object. Its predicate is <code>librarian-p</code>. Without
      argument, a librarian is created in <em>output mode</em>. With a
      string argument, the librarian is opened in <em>input mode</em>,
      with the file name argument. The output mode is used to create a
      new librarian by adding file into it. The input mode is created
      to read file from the librarian.
      </p>

      <example>
      # create a new librarian
      const lbr (Librarian)
      # add a file into it
      lbr:add "file-1.als"
      # write it
      lbr:write "librarian.axl"
      </example>

      <p>
      The <code>add</code> method adds a new file into the
      librarian. The <code>write</code> method the full librarian as a
      single file those name is <code>write</code> method argument.
      </p>
    </subsect>

    <!-- input librarian -->
    <subsect>
      <title>Input librarian</title>

      <p>
      With an argument, the librarian object is created in input
      mode. Once created, file can be read or extracted. The
      <code>length</code> method -- which also work with an output
      librarian --  returns the number of files in the librarian. The
      <code>exists-p</code> predicate returns true if the file name
      argument exists in the librarian. The <code>get-names</code> 
      method returns a vector of file names in this librarian. The
      <code>extract</code> method returns an input stream object for
      the specific file name.
      </p>

      <example>
      # open a librarian for reading
      const lbr (Librarian "librarian.axl")
      # get the number of files
      println (lbr:length)
      # extract the first file
      const is (lbr:extract "file-1.als")
      # is is an input stream - dump each line
      while (is:valid-p) (println (is:readln))
      </example>

      <p>
      Most of the time, the librarian object is used to extract file
      dynamically. Because a librarian is mapped into the memory at
      the right offset, there is no worry to use big librarian, even
      for a small file. Note that any type of file can be used, text
      or binaries.
      </p>
    </subsect>
  </section>

  <!-- file resolver -->
  <section>
    <title>File resolver</title>

    <p>
    The <afnix/> <em>file resolver</em> is a special object used by
    the interpreter to resolve file path based on the search path. The
    resolver uses a mixed list of directories and librarian files in
    its search path. When a file path needs to be resolved, the search
    path is scanned until a matched is found. Because the librarian
    resolution is integrated inside the resolver, there is no need to
    worry about file extraction. That process is done
    automatically. The resolver can also be used inside an <afnix/>
    program to perform any kind of file path resolution.
    </p>

    <!-- resolver object -->
    <subsect>
      <title>Resolver object</title>

      <p>
      The resolver object is created without argument. The
      <code>add</code> method adds a directory path or a librarian
      file to the resolver. The <code>valid</code> method checks for
      the existence of a file. The <code>lookup</code> method returns
      an input stream object associated with the object.
      </p>

      <example>
      # create a new resolver
      const rslv (Resolver)
      assert true (resolver-p rslv)

      # add the local directory on the search path
      rslv:add "."

      # check if file test.als exists
      # if this is ok - print its  contents
      if (rslv:valid-p "test.als") {
        const is (rslv:lookup "test.als")
	while (is:valid-p) (println (is:readln))
      }
      </example>
    </subsect>
  </section>
</chapter>
