AutoDoc-2025.10.16/0000755000175100017510000000000015074117054013060 5ustar runnerrunnerAutoDoc-2025.10.16/doc/0000755000175100017510000000000015074117054013625 5ustar runnerrunnerAutoDoc-2025.10.16/doc/manual.lab0000644000175100017510000001671015074117054015567 0ustar runnerrunner\GAPDocLabFile{autodoc} \makelabel{autodoc:Title page}{}{X7D2C85EC87DD46E5} \makelabel{autodoc:Abstract}{}{X7AA6C5737B711C89} \makelabel{autodoc:Copyright}{}{X81488B807F2A1CF1} \makelabel{autodoc:Acknowledgements}{}{X82A988D47DFAFCFA} \makelabel{autodoc:Table of Contents}{}{X8537FEB07AF2BEC8} \makelabel{autodoc:Getting started using AutoDoc}{1}{X7A0D7AA484F466E1} \makelabel{autodoc:Creating a package manual from scratch}{1.1}{X7BFBC6907B26AA95} \makelabel{autodoc:Documenting code with AutoDoc}{1.2}{X87A00EED866E22E8} \makelabel{autodoc:Using AutoDoc in an existing GAPDoc manual}{1.3}{X7FA614637B807F4D} \makelabel{autodoc:Using AutoDoc on a complete GAPDoc manual}{1.3.1}{X7F3CEB097AF47C1E} \makelabel{autodoc:Setting different GAPDoc options}{1.3.2}{X7D0DDF2284F2D24A} \makelabel{autodoc:Checklist for converting an existing GAPDoc manual to use AutoDoc}{1.3.3}{X83448D91868D7994} \makelabel{autodoc:Scaffolds}{1.4}{X8524193D824CDE0D} \makelabel{autodoc:Generating a title page}{1.4.1}{X7CF22DE28478316F} \makelabel{autodoc:Generating the main XML file}{1.4.2}{X7CD72CC780874FD5} \makelabel{autodoc:What data is used from PackageInfo.g?}{1.4.3}{X799956EA85D3FC15} \makelabel{autodoc:AutoDoc worksheets}{1.5}{X80ED3C2A78146AD1} \makelabel{autodoc:AutoDoc documentation comments}{2}{X87668C487B1A2094} \makelabel{autodoc:Documenting declarations}{2.1}{X871482CE838C68F6} \makelabel{autodoc:@Description descr}{2.1.1}{X7F1D85188262A827} \makelabel{autodoc:@Returns retval}{2.1.2}{X7DCAB2F87E8FAE90} \makelabel{autodoc:@Arguments args}{2.1.3}{X81DAA454857F7971} \makelabel{autodoc:@Group grpname}{2.1.4}{X8677FE8F80C00B14} \makelabel{autodoc:@Label label}{2.1.5}{X7B0E20A27D64DF6F} \makelabel{autodoc:@ChapterInfo chapter, section}{2.1.8}{X78938EE37A532FFA} \makelabel{autodoc:Other documentation comments}{2.2}{X8152FEF9844B1ACD} \makelabel{autodoc:@Chapter name}{2.2.1}{X823E613385D09F6F} \makelabel{autodoc:@Section name}{2.2.2}{X78AA98BA7E0635D0} \makelabel{autodoc:@Subsection name}{2.2.3}{X7FD77434802A3580} \makelabel{autodoc:@BeginGroup [grpname]}{2.2.4}{X7D3060C17EDBCED1} \makelabel{autodoc:@EndGroup}{2.2.5}{X7C17EB007FD42C87} \makelabel{autodoc:@GroupTitle title}{2.2.6}{X82FB96F37FAE8167} \makelabel{autodoc:@Level lvl}{2.2.7}{X7BF81EAF80D1A4B5} \makelabel{autodoc:@ResetLevel}{2.2.8}{X7C6723D57F424215} \makelabel{autodoc:@BeginExample and @EndExample}{2.2.9}{X83D6DA3B83D3436C} \makelabel{autodoc:@BeginExampleSession and @EndExampleSession}{2.2.10}{X861E2E778510CAF7} \makelabel{autodoc:@BeginLog and @EndLog}{2.2.11}{X81A2D44D834C0A17} \makelabel{autodoc:@BeginLogSession and @EndLogSession}{2.2.12}{X7BADE876794FF309} \makelabel{autodoc:@DoNotReadRestOfFile}{2.2.13}{X78DC644E8519280C} \makelabel{autodoc:@BeginChunk name, @EndChunk, and @InsertChunk name}{2.2.14}{X83C01F9B7FA1C973} \makelabel{autodoc:@BeginCode name, @EndCode, and @InsertCode name}{2.2.15}{X7D3671AF86B995B9} \makelabel{autodoc:@LatexOnly text, @BeginLatexOnly, and @EndLatexOnly}{2.2.16}{X8033B34F80A12A10} \makelabel{autodoc:@NotLatex text, @BeginNotLatex, and @EndNotLatex}{2.2.17}{X7EF303147F1BCC22} \makelabel{autodoc:Title page commands}{2.3}{X841E3AD584F5385C} \makelabel{autodoc:Plain text files}{2.4}{X828AE38F80CB02E7} \makelabel{autodoc:Grouping}{2.5}{X7D7A38F87BC40C48} \makelabel{autodoc:A family of operations}{2.5.1}{X79BF060F8436C586} \makelabel{autodoc:Level}{2.6}{X8209AFDE8209AFDE} \makelabel{autodoc:Markdown-like formatting of text in AutoDoc}{2.7}{X79558A2F7FE187B4} \makelabel{autodoc:Lists}{2.7.1}{X7B256AE5780F140A} \makelabel{autodoc:Math modes}{2.7.2}{X871412737A0E12E2} \makelabel{autodoc:Emphasize}{2.7.3}{X7ED0330479146EFC} \makelabel{autodoc:Inline code}{2.7.4}{X838CCDEB7E0ECEE2} \makelabel{autodoc:Deprecated commands}{2.8}{X78CA9E5C7F494C19} \makelabel{autodoc:AutoDoc worksheets}{3}{X80ED3C2A78146AD1} \makelabel{autodoc:Worksheets}{3.1}{X801D4A2F8292704C} \makelabel{autodoc:AutoDoc}{4}{X7CBD8AAF7DCEF352} \makelabel{autodoc:The AutoDoc() function}{4.1}{X863584DB8497D8BA} \makelabel{autodoc:Examples}{4.2}{X7A489A5D79DA9E5C} \makelabel{autodoc:Bibliography}{Bib}{X7A6F98FD85F02BFE} \makelabel{autodoc:References}{Bib}{X7A6F98FD85F02BFE} \makelabel{autodoc:Index}{Ind}{X83A0356F839C696F} \makelabel{autodoc:makedoc.g}{1.1}{X7BFBC6907B26AA95} \makelabel{autodoc:}{1.3.3}{X83448D91868D7994} \makelabel{autodoc:}{1.3.3}{X83448D91868D7994} \makelabel{autodoc:}{1.3.3}{X83448D91868D7994} \makelabel{autodoc:}{1.3.3}{X83448D91868D7994} \makelabel{autodoc:}{1.3.3}{X83448D91868D7994} \makelabel{autodoc:}{1.3.3}{X83448D91868D7994} \makelabel{autodoc:}{1.3.3}{X83448D91868D7994} \makelabel{autodoc:@Description descr}{2.1.1}{X7F1D85188262A827} \makelabel{autodoc:@Returns retval}{2.1.2}{X7DCAB2F87E8FAE90} \makelabel{autodoc:@Arguments args}{2.1.3}{X81DAA454857F7971} \makelabel{autodoc:@Group grpname}{2.1.4}{X8677FE8F80C00B14} \makelabel{autodoc:@Label label}{2.1.5}{X7B0E20A27D64DF6F} \makelabel{autodoc:AProperty testlabel}{2.1.6}{X83B63B847B5199CF} \makelabel{autodoc:AProperty for IsObject}{2.1.7}{X78A9022A7D5CB20E} \makelabel{autodoc:@ChapterInfo}{2.1.8}{X78938EE37A532FFA} \makelabel{autodoc:@Chapter}{2.2.1}{X823E613385D09F6F} \makelabel{autodoc:@ChapterLabel}{2.2.1}{X823E613385D09F6F} \makelabel{autodoc:@ChapterTitle}{2.2.1}{X823E613385D09F6F} \makelabel{autodoc:@Section}{2.2.2}{X78AA98BA7E0635D0} \makelabel{autodoc:@SectionLabel}{2.2.2}{X78AA98BA7E0635D0} \makelabel{autodoc:@SectionTitle}{2.2.2}{X78AA98BA7E0635D0} \makelabel{autodoc:@Subsection}{2.2.3}{X7FD77434802A3580} \makelabel{autodoc:@SubsectionLabel}{2.2.3}{X7FD77434802A3580} \makelabel{autodoc:@SubsectionTitle}{2.2.3}{X7FD77434802A3580} \makelabel{autodoc:@BeginGroup}{2.2.4}{X7D3060C17EDBCED1} \makelabel{autodoc:@EndGroup}{2.2.5}{X7C17EB007FD42C87} \makelabel{autodoc:@GroupTitle}{2.2.6}{X82FB96F37FAE8167} \makelabel{autodoc:@Level}{2.2.7}{X7BF81EAF80D1A4B5} \makelabel{autodoc:@ResetLevel}{2.2.8}{X7C6723D57F424215} \makelabel{autodoc:@BeginExample}{2.2.9}{X83D6DA3B83D3436C} \makelabel{autodoc:@EndExample}{2.2.9}{X83D6DA3B83D3436C} \makelabel{autodoc:@BeginExampleSession}{2.2.10}{X861E2E778510CAF7} \makelabel{autodoc:@EndExampleSession}{2.2.10}{X861E2E778510CAF7} \makelabel{autodoc:@BeginLog}{2.2.11}{X81A2D44D834C0A17} \makelabel{autodoc:@EndLog}{2.2.11}{X81A2D44D834C0A17} \makelabel{autodoc:@BeginLogSession}{2.2.12}{X7BADE876794FF309} \makelabel{autodoc:@EndLogSession}{2.2.12}{X7BADE876794FF309} \makelabel{autodoc:@DoNotReadRestOfFile}{2.2.13}{X78DC644E8519280C} \makelabel{autodoc:@BeginChunk name}{2.2.14}{X83C01F9B7FA1C973} \makelabel{autodoc:@EndChunk}{2.2.14}{X83C01F9B7FA1C973} \makelabel{autodoc:@InsertChunk name}{2.2.14}{X83C01F9B7FA1C973} \makelabel{autodoc:@BeginCode name}{2.2.15}{X7D3671AF86B995B9} \makelabel{autodoc:@EndCode}{2.2.15}{X7D3671AF86B995B9} \makelabel{autodoc:@InsertCode name}{2.2.15}{X7D3671AF86B995B9} \makelabel{autodoc:@LatexOnly text}{2.2.16}{X8033B34F80A12A10} \makelabel{autodoc:@BeginLatexOnly}{2.2.16}{X8033B34F80A12A10} \makelabel{autodoc:@EndLatexOnly}{2.2.16}{X8033B34F80A12A10} \makelabel{autodoc:@NotLatex text}{2.2.17}{X7EF303147F1BCC22} \makelabel{autodoc:@BeginNotLatex}{2.2.17}{X7EF303147F1BCC22} \makelabel{autodoc:@EndNotLatex}{2.2.17}{X7EF303147F1BCC22} \makelabel{autodoc:FirstOperation for IsInt}{2.5.1}{X79BF060F8436C586} \makelabel{autodoc:SecondOperation for IsInt, IsGroup}{2.5.1}{X79BF060F8436C586} \makelabel{autodoc:ThirdOperation for IsGroup, IsInt}{2.5.1}{X79BF060F8436C586} \makelabel{autodoc:AutoDocWorksheet}{3.1.1}{X809FE4137C08B28D} \makelabel{autodoc:AutoDoc}{4.1.1}{X7CBD8AAF7DCEF352} \makelabel{autodoc:InfoAutoDoc}{4.1.2}{X81F946A785BA3D6E} AutoDoc-2025.10.16/doc/chap4.txt0000644000175100017510000004750615074117054015401 0ustar runnerrunner 4 AutoDoc 4.1 The AutoDoc() function 4.1-1 AutoDoc AutoDoc( [packageOrDirectory][,] [optrec] )  function Returns: nothing This is the main function of the AutoDoc package. It can perform any combination of the following tasks: 1 It can (re)generate a scaffold for your package manual. That is, it can produce two XML files in GAPDoc format to be used as part of your manual: First, a file named doc/PACKAGENAME.xml (with your package's name substituted) which is used as main XML file for the package manual, i.e. this file sets the XML doctype and defines various XML entities, includes other XML files (both those generated by AutoDoc as well as additional files created by other means), tells GAPDoc to generate a table of contents and an index, and more. Secondly, it creates a file doc/title.xml containing a title page for your documentation, with information about your package (name, description, version), its authors and more, based on the data in your PackageInfo.g. 2 It can scan your package for AutoDoc based documentation (by using AutoDoc tags and the Autodoc command. This will produce further XML files to be used as part of the package manual. 3 It can use GAPDoc to generate PDF, text and HTML (with MathJaX enabled) documentation from the GAPDoc XML files it generated as well as additional such files provided by you. For this, it invokes MakeGAPDocDoc (GAPDoc: MakeGAPDocDoc) to convert the XML sources, and it also instructs GAPDoc to copy supplementary files (such as CSS style files) into your doc directory (see CopyHTMLStyleFiles (GAPDoc: CopyHTMLStyleFiles)). For more information and some examples, please refer to Chapter 1. The parameters have the following meanings: packageOrDirectory The purpose of this parameter is twofold: to determine the package directory in which AutoDoc will operate, and to find the metadata concerning the package being documented. The parameter is either a string, an IsDirectory object, or omitted. If it is a string, AutoDoc interprets it as the name of a package, uses the metadata of the first package known to GAP with that name, and uses the InstallationPath specified in that metadata as the package directory. If packageOrDirectory is an IsDirectory object, this is used as package directory; if the argument is omitted, then the current directory is used. In the last two cases, the specified directory must contain a PackageInfo.g file, and AutoDoc extracts all needed metadata from that. The IsDirectory form is for example useful if you have multiple versions of the package around and want to make sure the documentation of the correct version is built. Note that when using AutoDocWorksheet (see 3.1), there is no parameter corresponding to packageOrDirectory and so the package directory is always the current directory, and there is no metadata. optrec optrec can be a record with some additional options. The following are currently supported: dir This should either be a string, in which case it must be a path relative to the specified package directory, or a Directory() object. (Thus, the only way to designate an absolute directory is with a Directory() object.) This option specifies where the package documentation (e.g. the GAPDoc XML or the manual PDF, etc.) files are stored and/or will be generated. Default value: "doc/". scaffold This controls whether and how to generate scaffold XML files for the package documentation. The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.scaffold is missing but the package's info record in PackageInfo.g has an AutoDoc entry. In all other cases (in particular if opt.scaffold is false), scaffolding is disabled. If scaffolding is enabled, and PackageInfo.AutoDoc exists, then it is assumed to be a record, and its contents are used as default values for the scaffold settings. If opt.scaffold is a record, it may contain the following entries. includes A list of XML files to be included in the body of the main XML file. If you specify this list and also are using AutoDoc to document your operations with AutoDoc comments, you can add _AutoDocMainFile.xml to this list to control at which point the documentation produced by AutoDoc is inserted. If you do not do this, it will be added after the last of your own XML files. index By default, the scaffold creates an index. If you do not want an index, set this to false. appendix This entry is similar to opt.scaffold.includes but is used to specify files to include after the main body of the manual, i.e. typically appendices. bib The name of a bibliography file, in BibTeX or XML format. If this key is not set, but there is a file doc/PACKAGENAME.bib then it is assumed that you want to use this as your bibliography. entities A record whose keys are taken as entity names, set to the corresponding (string) values. For example, if you pass the record SomePackage,    rec( SomePackage := "SomePackage",  RELEASEYEAR := "2015" )  then the following entity definitions are added to the XML preamble:   SomePackage'>    This allows you to write &SomePackage; and &RELEASEYEAR; in your documentation, which will be replaced by respective values specified in the entities definition. TitlePage A record whose entries are used to embellish the generated title page for the package manual with extra information, such as a copyright statement or acknowledgments. To this end, the names of the record components are used as XML element names, and the values of the components are outputted as content of these XML elements. For example, you could pass the following record to set a custom acknowledgements text:    rec( Acknowledgements := "Many thanks to ..." )  For a list of valid entries in the title page, please refer to the GAPDoc manual, specifically section 'GAPDoc: TitlePage'. MainPage If scaffolding is enabled, by default a main XML file is generated (this is the file which contains the XML doctype and more). If you do not want this (e.g. because you have a handwritten main XML file), but still want AutoDoc to generate a title page for you, you can set this option to false document_class Sets the document class of the resulting PDF. The value can either be a string which has to be the name of the new document class, a list containing this string, or a list of two strings. Then the first one has to be the document class name, the second one the option string ( contained in [ ] ) in LaTeX. latex_header_file Replaces the standard header from GAPDoc completely with the header in this LaTeX file. Please be careful here, and look at GAPDoc's latexheader.tex file for an example. autodoc This controls whether and how to generate additional XML documentation files by scanning for AutoDoc documentation comments. The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.autodoc is missing but the package depends (directly) on the AutoDoc package. In all other cases (in particular if opt.autodoc is false), this feature is disabled. If opt.autodoc is a record, it may contain the following entries. files A list of files (given by paths relative to the package directory) to be scanned for AutoDoc documentation comments. Usually it is more convenient to use autodoc.scan_dirs, see below. scan_dirs A list of subdirectories of the package directory (given as relative paths) which AutoDoc then scans for .gi, .gd, .g, and .autodoc files; all of these files are then scanned for AutoDoc documentation comments. Default value: [ ".", "gap", "lib", "examples", "examples/doc" ]. level This defines the level of the created documentation. The default value is 0. When parts of the manual are declared with a higher value they will not be printed into the manual. gapdoc This controls whether and how to invoke GAPDoc to create HTML, PDF and text files from your various XML files. The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.gapdoc is missing. In all other cases (in particular if opt.gapdoc is false), this feature is disabled. If opt.gapdoc is a record, it may contain the following entries. main The name of the main XML file of the package manual. This exists primarily to support packages with existing manual which use a filename here which differs from the default. In particular, specifying this is unnecessary when using scaffolding. Default value: PACKAGENAME.xml. files A list of files (given by paths relative to the package directory) to be scanned for GAPDoc documentation comments. Usually it is more convenient to use gapdoc.scan_dirs, see below. scan_dirs A list of subdirectories of the package directory (given as relative paths) which AutoDoc then scans for .gi, .gd and .g files; all of these files are then scanned for GAPDoc documentation comments. Default value: [ ".", "gap", "lib", "examples", "examples/doc" ]. LaTeXOptions Must be a record with entries which can be understood by SetGapDocLaTeXOptions (GAPDoc: SetGapDocLaTeXOptions). Each entry can be a string, which will be given to GAPDoc directly, or a list containing of two entries: The first one must be the string "file", the second one a filename. This file will be read and then its content is passed to GAPDoc as option with the name of the entry. gap_root_relative_path Either a boolean, or a string containing a relative path. By default (if this option is not set, or is set to false), references in the generated documentation referring to external documentation (such as the GAP manual) are encoded using absolute paths. This is fine as long as the documentation stays on only a single computer, but is problematic when preparing documentation that should be used on multiple computers, e.g., when creating a distribution archive of a GAP package. Thus, if a relative path is provided via this option (or if it is set to true, in which case the relative path ../../.. is used), then AutoDoc and GAPDoc attempt to replace all absolute paths in references to GAP manuals by paths based on this relative path. On a technical level, AutoDoc passes the relative path to the gaproot parameter of MakeGAPDocDoc (GAPDoc: MakeGAPDocDoc) extract_examples Either true or a record. If set to true, then all manual examples are extracted and placed into files tst/PACKAGENAME01.tst, tst/PACKAGENAME02.tst, ... and so on, with one file for each chapter. For chapters with no examples, no file is created. As a record, the entry can have the following entries itself, to specify some options. units This controls how examples are grouped into files. Recognized values are "Chapter" (default), "Section", "Subsection" or "Single". Depending on the value, one file is created for each chapter, each section, each subsection or each example. For all other values only a single file is created. On a technical level, AutoDoc passes the value to the units parameter of ExtractExamples (GAPDoc: ExtractExamples). skip_empty_in_numbering If set to true (the default), the generated files use filenames with strictly sequential numbering; that means that if chapter 1 (or whatever units are being used) contains no examples but chapter 2 does, then the examples for chapter 2 are put into the file tst/PACKAGENAME01.tst. If this option is set to false, then the chapter numbers are used to generate the filenames; so the examples for chapter 2 would be put into the file tst/PACKAGENAME02.tst. 4.1-2 InfoAutoDoc InfoAutoDoc  info class Info class for the AutoDoc package. Set this to 0 to suppress info messages, 1 to allow most messages, and 2 to allow all messages including those that contain file paths. This can be set by calling, for example, SetInfoLevel(InfoPackageManager, 0). Default value 1. 4.2 Examples Some basic examples for using AutoDoc were already shown in Chapter 1. AutoDoc-2025.10.16/doc/chap3.html0000644000175100017510000000701715074117054015516 0ustar runnerrunner GAP (AutoDoc) - Chapter 3: AutoDoc worksheets
Goto Chapter: Top 1 2 3 4 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

3 AutoDoc worksheets
 3.1 Worksheets

3 AutoDoc worksheets

3.1 Worksheets

3.1-1 AutoDocWorksheet
‣ AutoDocWorksheet( list_of_filenames: options )( function )

The intention of these function is to create stand-alone pdf and html files using AutoDoc without having them associated to a package. It uses the same optional records as the AutoDoc command itself, but instead of a package name there should be a filename or a list of filenames containing AutoDoc text from which the documents are created. Please see the AutoDoc command for more information about this and have a look at 1.5 for a simple worksheet example.

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chapInd_mj.html0000644000175100017510000001731615074117054016557 0ustar runnerrunner GAP (AutoDoc) - Index
Goto Chapter: Top 1 2 3 4 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter] 

Index

@Arguments args 2.1-3
@BeginChunk name 2.2-14
@BeginCode name 2.2-15
@BeginExample 2.2-9
@BeginExampleSession 2.2-10
@BeginGroup 2.2-4
@BeginLatexOnly 2.2-16
@BeginLog 2.2-11
@BeginLogSession 2.2-12
@BeginNotLatex 2.2-17
@Chapter 2.2-1
@ChapterInfo 2.1-8
@ChapterLabel 2.2-1
@ChapterTitle 2.2-1
@Description descr 2.1-1
@DoNotReadRestOfFile 2.2-13
@EndChunk 2.2-14
@InsertChunk name 2.2-14
@EndCode 2.2-15
@EndExample 2.2-9
@EndExampleSession 2.2-10
@EndGroup 2.2-5
@EndLatexOnly 2.2-16
@EndLog 2.2-11
@EndLogSession 2.2-12
@EndNotLatex 2.2-17
@Group grpname 2.1-4
@GroupTitle 2.2-6
@InsertCode name 2.2-15
@Label label 2.1-5
@LatexOnly text 2.2-16
@Level 2.2-7
@NotLatex text 2.2-17
@ResetLevel 2.2-8
@Returns ret_val 2.1-2
@Section 2.2-2
@SectionLabel 2.2-2
@SectionTitle 2.2-2
@Subsection 2.2-3
@SubsectionLabel 2.2-3
@SubsectionTitle 2.2-3
1.3-3 1.3-3
AProperty, for IsObject 2.1-7
    testlabel 2.1-6
AutoDoc 4.1-1
AutoDocWorksheet 3.1-1
1.3-3 1.3-3 1.3-3
FirstOperation, for IsInt 2.5-1
InfoAutoDoc 4.1-2
1.3-3
makedoc.g 1.1
1.3-3
SecondOperation, for IsInt, IsGroup 2.5-1
ThirdOperation, for IsGroup, IsInt 2.5-1

 [Top of Book]  [Contents]   [Previous Chapter] 
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/clean0000755000175100017510000000024215074117054014633 0ustar runnerrunner#!/bin/sh rm -f *.{aux,lab,log,dvi,ps,pdf,bbl,ilg,ind,idx,out,html,tex,pnr,txt,blg,toc,six,brf,css,js} _Chapter*.xml title.xml _AutoDocMainFile.xml AutoDoc.xml AutoDoc-2025.10.16/doc/Tutorials.xml0000644000175100017510000005701515074117054016345 0ustar runnerrunner Getting started using &AutoDoc; &AutoDoc; is a ⪆ package which is meant to aid ⪆ package authors in creating and maintaining the documentation of their packages. In this capacity it builds upon the &GAPDoc; package (see https://www.gap-system.org/Packages/gapdoc.html). As such, it is not a replacement for &GAPDoc;, but rather complements it.

In this chapter we describe how to get started using &AutoDoc; for your package. First, we explain in Section how to write a new package manual from scratch.

Then we show in Section how you might benefit from &AutoDoc; even if you already have a complete manual written using &GAPDoc;.

In Section , we explain how you may use &AutoDoc; to generate a title page and the main XML file for your manual.

Finally, Section , explains what &AutoDoc; worksheets are and how to use them.

Creating a package manual from scratch Suppose your package is already up and running, but so far has no manual. Then you can rapidly generate a scaffold for a package manual using the command like this, while running ⪆ from within your package's directory (the one containing the PackageInfo.g file): LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true ) ); This first reads the PackageInfo.g file from the current directory. It extracts information about the package from it (such as its name and version, see Section ). It then creates two XML files doc/NAME_OF_YOUR_PACKAGE.xml and doc/title.xml inside the package directory. Finally, it runs &GAPDoc; on them to produce a nice initial PDF and HTML version of your fresh manual.

To ensure that the ⪆ help system picks up your package manual, you should also add something like the following to your PackageInfo.g:

PackageDoc := rec( BookName := ~.PackageName, ArchiveURLSubset := ["doc"], HTMLStart := "doc/chap0.html", PDFFile := "doc/manual.pdf", SixFile := "doc/manual.six", LongTitle := ~.Subtitle, ), Congratulations, your package now has a minimal working manual. Of course it will be mostly empty for now, but it already should contain some useful information, based on the data in your PackageInfo.g. This includes your package's name, version and description as well as information about its authors. And if you ever change the package data, (e.g. because your email address changed), just re-run the above command to regenerate the two main XML files with the latest information.

Next of course you need to provide actual content (unfortunately, we were not yet able to automate that for you, more research on artificial intelligence is required). To add more content, you have several options: You could add further &GAPDoc; XML files containing extra chapters, sections and so on. Or you could use classic &GAPDoc; source comments. For details on either, please refer to , as well as Section of this manual on how to teach the command to include this extra documentation. Or you could use the special documentation facilities &AutoDoc; provides (see Section ).

You will probably want to re-run the command frequently, e.g. whenever you modified your documentation or your PackageInfo.g. To make this more convenient and reproducible, we recommend putting its invocation into a file makedoc.g in your package makedoc.g directory, with content based on the following example:

LoadPackage( "AutoDoc" ); AutoDoc( rec( autodoc := true ) ); QUIT; Then you can regenerate the package manual from the command line with the following command, executed from within in the package directory: gap makedoc.g
Documenting code with &AutoDoc; To get one of your global functions, operations, attributes etc. to appear in the package manual, simply insert an &AutoDoc; comment of the form #! directly in front of it. For example: #! DeclareOperation( "ToricVariety", [ IsConvexObject ] ); This tiny change is already sufficient to ensure that the operation appears in the manual. In general, you will want to add further information about the operation, such as in the following example: conv. DeclareOperation( "ToricVariety", [ IsConvexObject ] ); ]]> For a thorough description of what you can do with &AutoDoc; documentation comments, please refer to chapter .

Suppose you have not been using &GAPDoc; before but instead used the process described in section to create your manual. Then the following ⪆ command will regenerate the manual and automatically include all newly documented functions, operations etc.:

LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true, autodoc := true ) ); If you are not using the scaffolding feature, e.g. because you already have an existing &GAPDoc; based manual, then you can still use &AutoDoc; documentation comments. Just make sure to first edit the main XML file of your documentation, and insert the line <#Include SYSTEM "_AutoDocMainFile.xml"> in a suitable place. This means that you can mix &AutoDoc; documentation comment freely with your existing documentation; you can even still make use of any existing &GAPDoc; documentation comments in your code. The following command should be useful for you in this case; it still scans the package code for &AutoDoc; documentation comments and the runs &GAPDoc; to produce HTML and PDF output, but does not touch your documentation XML files otherwise. LoadPackage( "AutoDoc" ); AutoDoc( rec( autodoc := true ) );
Using &AutoDoc; in an existing &GAPDoc; manual Even if you already have an existing &GAPDoc; manual, it might be interesting for you to use &AutoDoc; for two purposes:

First off, with &AutoDoc; it is very convenient to regenerate your documentation.

Secondly, the scaffolding feature which generates a title page with all the metadata of your package in a uniform way is very handy. The somewhat tedious process of keeping your title page in sync with your PackageInfo.g is fully automated this way (including the correct version, release data, author information and so on).

There are various examples of packages using &AutoDoc; for this purpose only, e.g. &io; and orb.

Using &AutoDoc; on a complete &GAPDoc; manual Suppose you already have a complete XML manual, with some main and title XML files and some documentation for operations distributed over all your .g, .gd, and .gi files. Suppose the main XML file is named PACKAGENAME.xml and is in the /doc subdirectory of your package. Then you can rebuild your manual by executing the following two &GAP; commands from a &GAP; session started in the root directory of your package:

LoadPackage( "AutoDoc" ); AutoDoc( ); In contrast, the RingsForHomalg package currently uses essentially the following code in its makedoc.g file to achieve the same result: LoadPackage( "GAPDoc" ); SetGapDocLaTeXOptions( "utf8" ); bib := ParseBibFiles( "doc/RingsForHomalg.bib" ); WriteBibXMLextFile( "doc/RingsForHomalgBib.xml", bib ); list := [ "../gap/RingsForHomalg.gd", "../gap/RingsForHomalg.gi", "../gap/Singular.gi", "../gap/SingularBasic.gi", "../examples/RingConstructionsExternalGAP.g", "../examples/RingConstructionsSingular.g", "../examples/RingConstructionsMAGMA.g", "../examples/RingConstructionsMacaulay2.g", "../examples/RingConstructionsSage.g", "../examples/RingConstructionsMaple.g", ]; MakeGAPDocDoc( "doc", "RingsForHomalg", list, "RingsForHomalg" ); GAPDocManualLab( "RingsForHomalg" ); Note that in particular, you do not have to worry about keeping a list of your implementation files up-to-date.

But there is more. &AutoDoc; can create .tst files from the examples in your manual to test your package. This can be achieved via

LoadPackage( "AutoDoc" ); AutoDoc( rec( extract_examples := true ) ); Now files PACKAGENAME01.tst, PACKAGENAME02.tst and so appear in the tst/ subdirectory of your package, and can be tested as usual using respectively . Setting different &GAPDoc; options Sometimes, the default values for the &GAPDoc; command used by &AutoDoc; may not be suitable for your manual.

Suppose your main XML file is not named PACKAGENAME.xml, but rather something else, e.g. main.xml. Then you can tell &AutoDoc; to use this file as the main XML file via

LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( main := "main" ) ) );

As explained above, by default &AutoDoc; scans all .g, .gd and .gi files it can find inside of your package root directory, and in the subdirectories gap, lib, examples and examples/doc as well. If you keep source files with documentation in other directories, you can adjust the list of directories AutoDoc scans via the scan_dirs option. The following example illustrates this by instructing &AutoDoc; to only search in the subdirectory package_sources of the packages root directory.

LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( scan_dirs := [ "package_sources" ] ) ) ); You can also specify an explicit list of files containing documentation, which will be searched in addition to any files located within the scan directories: LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( files := [ "path/to/some/hidden/file.gds" ] ) ) ); Giving such a file does not prevent the standard scan_dirs from being scanned for other files.

Next, &GAPDoc; supports the documentation to be built with relative paths. This means, links to manuals of other packages or the &GAP; library will not be absolute, but relative from your documentation. This can be particularly useful if you want to build a release tarball or move your &GAP; installation around later. Suppose you are starting &GAP; in the root path of your package as always, and the standard call of will then build the documentation in the doc subdirectory of your package. From this directory, the gap root directory has the relative path ../../... Then you can enable the relative paths by

LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( gap_root_relative_path := "../../.." ) ) ); or, since ../../.. is the standard option for gap_root_relative_path, by LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( gap_root_relative_path := true ) ) );
Checklist for converting an existing &GAPDoc; manual to use &AutoDoc; Here is a checklist for authors of a package &PackageName;, which already has a &GAPDoc; based manual, who wish to use &AutoDoc; to build the manual from now on. We assume that the manual is currently built by reading a file makedoc.g and that the main .xml file is named manual.xml.

The files PackageInfo.g, makedoc.g, doc/title.xml and doc/PackageName.xml (if it exists) will be altered by this procedure, so it may be wise to keep backup copies.

You should have copies of the &AutoDoc; files PackageInfo.g and makedoc.g to hand when reading these instructions.

Copy AutoDoc/makedoc.g to PackageName/makedoc.g. Edit PackageName/makedoc.g as follows. Change the header comment to match other files in your package. After LoadPackage("AutoDoc"); add LoadPackage("PackageName");. In the AutoDoc record delete autodoc := true;. In the scaffold record change the includes list to be the list of your .xml files that are contained in manual.xml. If you do not have a bibliography you may delete the bib := "bib.xml", field in the scaffold. Otherwise, edit the file name if you have a different file. If you only have a .bib file (manual.bib or bib.xml.bib say) you should rename this file PackageName.bib. In the LaTeXOptions record, which is in the gapdoc record, enter any &LaTeX; newcommands previously in manual.xml. (If there are none you may safely delete this record.) To illustrate this option, the &AutoDoc; file makedoc.g defines the command \bbZ by \newcommand{\bbZ}{\mathbb{Z}}, which may be used to produce the &LaTeX; formula f : \bbZ^2 \to \bbZ. However, note that this only works in the PDF version of the file. Now edit PackageName/PackageInfo.g as follows. Delete any PKGVERSIONDATA chunk that may be there. One reason for converting your manual to use &AutoDoc; is to stop using entities such as PACKAGENAMEVERSION. Copy the AutoDoc record from AutoDoc/PackageInfo.g to the end of your file (just before the final "));". Replace the Copyright, Abstract and Acknowledgements fields of the TitlePage record with the corresponding material from your manual.xml. (If you do not have an abstract, then delete the Abstract field, etc.) In the entities record enter any entities previously stored in your manual.xml. (Again, if you have none, you may safely delete this record.) To illustrate this option the &AutoDoc; file PackageInfo.g defines entities for the names of packages &io; and &PackageName;. If you are using a GitHub repository, as well as running "git add" on files makedoc.g, PackageInfo.g and doc/PackageName.bib, you should run "git rm -f" on files doc/manual.xml, and doc/title.xml. You should now be ready to run &GAP; and Read("makedoc.g"); in your package root directory.

Scaffolds Generating a title page For most (if not all) &GAP; packages, the title page of the package manual lists information such as the release date, version, names and contact details of the authors, and so on. All this data is also contained in your PackageInfo.g, and whenever you make a change to that file, there is a risk that you forget to update your manual to match. And even if you don't forget it, you of course have to spend some time to adjust the manual. &GAPDoc; can help to a degree with this via entities. Thus, you will sometimes see code like this in PackageInfo.g files: ## ## ## ## <#/GAPDoc> ]]> However, it is still easy to forget both of these versions. And it doesn't solve the problem of updating package authors addresses. Neither of these is a big issue, of course, but there have been plenty examples in the past where people forget either of these two things, and it can be slightly embarrassing. It may even require you to make a new release just to fix the issue, which in our opinion is a sad waste of your valuable time.

So instead of worrying about manually synchronising these things, you can instruct &AutoDoc; to generate a title page for your manual based on the information in your PackageInfo.g. The following commands do just that (in addition to building your manual), by generating a file called doc/title.xml.

LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := rec( MainPage := false ) ) ); Note that this only outputs doc/title.xml but does not touch any other files of your documentation. In particular, you need to explicitly include doc/title.xml from your main XML file.

However, you can also tell &AutoDoc; to maintain the main XML file for you, in which case this is automatic. In fact, this is the default if you enable scaffolding; the above example command explicitly told &AutoDoc; not to generate a main page. Generating the main XML file The following generates a main XML file for your documentation in addition to the title page. The main XML file includes the title page by default, as well as any documentation generated from &AutoDoc; documentation comments.

LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true ) ); You can instruct &AutoDoc; to include additional XML files by giving it a list of filenames, as in the following example: LoadPackage( "AutoDoc" ); AutoDoc(rec( scaffold := rec( includes := [ "somefile.xml", "anotherfile.xml" ] ) )); For more information, please consult the documentation of the function.
What data is used from PackageInfo.g? &AutoDoc; can use data from PackageInfo.g in order to generate a title page. Specifically, the following components of the package info record are taken into account: PackageName This is used to set the <Title> element of the title page. Subtitle This is used to set the <Subtitle> element of the title page. Version This is used to set the <Version> element of the title page, with the string Version prepended. Date This is used to set the <Date> element of the title page. Persons This is used to generate <Author> elements in the generated title page. PackageDoc This is a record (or a list of records) which is used to tell the &GAP; help system about the package manual. Currently &AutoDoc; extracts the value of the PackageDoc.BookName component and then passes that on to &GAPDoc; when creating the HTML, PDF and text versions of the manual. AutoDoc This is a record which can be used to control the scaffolding performed by &AutoDoc;, specifically to provide extra information for the title page. For example, you can set AutoDoc.TitlePage.Copyright to a string which will then be inserted on the generated title page. Using this method you can customize the following title page elements: TitleComment, Abstract, Copyright, Acknowledgements and Colophon.

Note that AutoDoc.TitlePage behaves exactly the same as the scaffold.TitlePage parameter of the function.

AutoDoc worksheets &AutoDoc; worksheets can be used to create HTML and PDF documents using AutoDoc syntax and possibly including &GAP; examples and implementations without having them associated to a package. A file for a worksheet could look like this: #! @Title My first worksheet #! @Author Charlie Brown #! @Chapter Some groups #! @BeginExample S3 := SymmetricGroup( 3 );; S4 := SymmetricGroup( 4 );; #! @EndExample Now, one can create a PDF and HTML document, like a package documentation out of it. Suppose the document above is saved as worksheet.g. Then, when &GAP; is started in the directory of this file, the command AutoDocWorksheet( "worksheet.g" ); will create a subdirectory called doc of the current directory in which it will create the documentation. There are several options to configure the output of the worksheet command, which are identical to the options of the command. It is even possible to test the examples in the worksheet using the extract_examples option of the command.

Since the worksheets do not have a PackageInfo.g to extract information, all possible tags that &GAPDoc; supports for the title page can be set into the document. A fully typed title page can look like this:

#! @Title My first worksheet #! @Subtitle Some small examples #! @Author Charlie Brown #! @Version 0.1 #! @TitleComment Some worksheet #! @Date 01/01/2016 #! @Address TU Kaiserslautern #! @Abstract #! A worksheet showing some small examples about groups. #! @Copyright 2016 Charlie Brown #! @Acknowledgements Woodstock #! @Colophon Some colophon #! @Chapter Some groups #! @BeginExample S3 := SymmetricGroup( 3 );; S4 := SymmetricGroup( 4 );; #! @EndExample
AutoDoc-2025.10.16/doc/bib.xml.bib0000644000175100017510000000125615074117054015642 0ustar runnerrunner @manual{ GAPDoc, author = {L{\"u}beck, F. and Neunh{\"o}ffer, M.}, title = {{GAPDoc (Version 1.5.1)}}, organization = {RWTH Aachen}, year = {2012}, note = {GAP package, \href {http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html} {\texttt{http://www.math.rwth\texttt{\symbol{45}}aachen.de/}\discretionary {}{}{}\texttt{\texttt{\symbol{126}}Frank.Luebeck/}\discretionary {}{}{}\texttt{GAPDoc/}\discretionary {}{}{}\texttt{index.html}}}, printedkey = {LN12} } AutoDoc-2025.10.16/doc/ragged.css0000644000175100017510000000023115074117054015564 0ustar runnerrunner/* times.css Frank Lübeck */ /* Change default CSS to use Times font. */ body { text-align: left; } AutoDoc-2025.10.16/doc/chooser.html0000644000175100017510000000745615074117054016171 0ustar runnerrunner GAPDoc Style Chooser

Setting preferences for GAPDoc manuals

Unfold subsections in menus only by mouse clicks: no (default)     yes

Show GAP examples as in sessions with ColorPrompt(true): yes (default)     no

Display side of table of contents within chapters: right (default)     left

Main document font: Helvetica/sans serif (default)     Times/serif

Paragraph formatting: left-right justified (default)     ragged right

Apply settings to last page.

AutoDoc-2025.10.16/doc/_Chapter_AutoDoc_worksheets.xml0000644000175100017510000000164315074117054021774 0ustar runnerrunner AutoDoc worksheets
Worksheets The intention of these function is to create stand-alone pdf and html files using AutoDoc without having them associated to a package. It uses the same optional records as the &AutoDoc; command itself, but instead of a package name there should be a filename or a list of filenames containing AutoDoc text from which the documents are created. Please see the &AutoDoc; command for more information about this and have a look at for a simple worksheet example.
AutoDoc-2025.10.16/doc/chapBib.html0000644000175100017510000000472115074117054016047 0ustar runnerrunner GAP (AutoDoc) - References
Goto Chapter: Top 1 2 3 4 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

References

[LN12] Lübeck, F. and Neunhöffer, M., GAPDoc (Version 1.5.1), RWTH Aachen (2012)
( GAP package, http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html ).

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chap2_mj.html0000644000175100017510000012433515074117054016206 0ustar runnerrunner GAP (AutoDoc) - Chapter 2: AutoDoc documentation comments
Goto Chapter: Top 1 2 3 4 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

2 AutoDoc documentation comments
 2.1 Documenting declarations
 2.2 Other documentation comments
 2.3 Title page commands
 2.4 Plain text files
 2.5 Grouping
 2.6 Level
 2.7 Markdown-like formatting of text in AutoDoc
 2.8 Deprecated commands

2 AutoDoc documentation comments

You can document declarations of global functions and variables, operations, attributes etc. by inserting AutoDoc comments into your sources before these declaration. An AutoDoc comment always starts with #!. This is also the smallest possible AutoDoc command. If you want your declaration documented, just write #! at the line before the documentation. For example:

#!
DeclareOperation( "AnOperation",
                  [ IsList ] );

This will produce a manual entry for the operation AnOperation.

Inside of AutoDoc comments, AutoDoc commands starting with @ can be used to control the output AutoDoc produces.

2.1 Documenting declarations

In the bare form above, the manual entry for AnOperation will not contain much more than the name of the operation. In order to change this, there are several commands you can put into the AutoDoc comment before the declaration. Currently, the following commands are provided:

2.1-1 @Description descr

Adds the text in the following lines of the AutoDoc to the description of the declaration in the manual. Lines are until the next AutoDoc command or until the declaration is reached.

2.1-2 @Returns ret_val

The string ret_val is added to the documentation, with the text Returns: put in front of it. This should usually give a brief hint about the type or meaning of the value returned by the documented function.

2.1-3 @Arguments args

The string args contains a description of the arguments the function expects, including optional parts, which are denoted by square brackets. The argument names can be separated by whitespace, commas or square brackets for the optional arguments, like grp[, elm] or xx[y[z] ]. If GAP options are used, this can be followed by a colon : and one or more assignments, like n[, r]: tries := 100.

2.1-4 @Group grpname

Adds the following method to a group with the given name. See section 2.5 for more information about groups.

2.1-5 @Label label

Adds label to the function as label. If this is not specified, then for declarations that involve a list of input filters (as is the case for DeclareOperation, DeclareAttribute, etc.), a default label is generated from this filter list.

#! @Label testlabel
DeclareProperty( "AProperty",
                 IsObject );

leads to this:

2.1-6 AProperty
‣ AProperty( arg )( property )

Returns: true or false

while

#!
DeclareProperty( "AProperty",
                 IsObject );

leads to this:

2.1-7 AProperty
‣ AProperty( arg )( property )

Returns: true or false

2.1-8 @ChapterInfo chapter, section

Adds the entry to the given chapter and section. Here, chapter and section are the respective titles.

As an example, a full AutoDoc comment with all options could look like this:

#! @Description
#! Computes the list of lists of degrees of ordinary characters
#! associated to the $p$-blocks of the group $G$
#! with $p$-modular character table <A>modtbl</A>
#! and underlying ordinary character table `ordtbl`.
#! @Returns a list
#! @Arguments modtbl
#! @Group CharacterDegreesOfBlocks
#! @Label chardegblocks
#! @ChapterInfo Blocks, Attributes
DeclareAttribute( "CharacterDegreesOfBlocks",
        IsBrauerTable );

2.2 Other documentation comments

There are also some commands which can be used in AutoDoc comments that are not associated to any declaration. This is useful for additional text in your documentation, examples, mathematical chapters, etc..

2.2-1 @Chapter name

Sets the active chapter, all subsequent functions which do not have an explicit chapter declared in their AutoDoc comment via @ChapterInfo will be added to this chapter. Also all text comments, i.e. lines that begin with #! without a command, and which do not follow after @Description, will be added to the chapter as regular text. Additionally, the chapters label will be set to Chapter_name. Example:

#! @Chapter My chapter
#!  This is my chapter.
#!  I document my stuff in it.

The @ChapterLabel label command can be used to set the label of the chapter to Chapter_label instead of Chapter_name. Additionally, the chapter will be stored as _Chapter_label.xml. The @ChapterTitle title command can be used to set a heading for the chapter that is different from name. Note that the title does not affect the label. If you use all three commands, i.e.,

#! @Chapter name
#! @ChapterLabel label
#! @ChapterTitle title

title is used for the headline, label for cross-referencing, and name for setting the same chapter as active chapter again.

2.2-2 @Section name

Sets an active section like @Chapter sets an active chapter. The section automatically ends with the next @Section or @Chapter command.

#! @Section My first manual section
#!  In this section I am going to document my first method.

The @SectionLabel label command can be used to set the label of the section to Section_label instead of Chapter_chaptername_Section_name. The @SectionTitle title command can be used to set a heading for the section that is different from name.

2.2-3 @Subsection name

Sets an active subsection like @Section sets an active section. The subsection automatically ends with the next @Subsection, @Section or @Chapter command. It also ends with the next documented function. Indeed, internally each function manpage is treated like a subsection.

#! @Subsection My first manual subsection
#!  In this subsection I am going to document my first example.

The @SubsectionLabel label command can be used to set the label of the subsection to Subsection_label instead of Chapter_chaptername_Section_sectionname_Subsection_name. The @SubsectionTitle title command can be used to set a heading for the subsection that is different from name.

2.2-4 @BeginGroup [grpname]

Starts a group. All following documented declarations without an explicit @Group command are grouped together in the same group with the given name. If no name is given, then a new nameless group is generated. The effect of this command is ended when an @EndGroup command is reached.

See section 2.5 for more information about groups.

2.2-5 @EndGroup

Ends the current group.

#! @BeginGroup MyGroup
#!
DeclareAttribute( "GroupedAttribute",
                  IsList );

DeclareOperation( "NonGroupedOperation",
                  [ IsObject ] );

#!
DeclareOperation( "GroupedOperation",
                  [ IsList, IsRubbish ] );
#! @EndGroup

2.2-6 @GroupTitle title

Sets the subsection heading for the current group to title. In the absence of any @GroupTitle command, the heading will be the name of the first entry in the group. See 2.5 for more information.

2.2-7 @Level lvl

Sets the current level of the documentation. All items created after this, chapters, sections, and items, are given the level lvl, until the @ResetLevel command resets the level to 0 or another level is set.

See section 2.6 for more information about levels.

2.2-8 @ResetLevel

Resets the current level to 0.

2.2-9 @BeginExample and @EndExample

@BeginExample marks the start of an example to be put into the manual. It differs from GAPDoc's <Example> (see GAPDoc: Log), in that it expects actual code (not in a comment) interspersed with comments, to allow for examples files that can be both executed by GAP, and parsed by AutoDoc. To achieve this, GAP commands are not preceded by a comment, while output has to be preceded by an AutoDoc comment. The gap> prompt for the display in the manual is added by AutoDoc. @EndExample ends the example block.

To illustrate this command, consider this input:

#! @BeginExample
S5 := SymmetricGroup(5);
#! Sym( [ 1 .. 5 ] )
Order(S5);
#! 120
#! @EndExample

This results in the following output:

gap> S5 := SymmetricGroup(5);
Sym( [ 1 .. 5 ] )
gap> Order(S5);
120

The AutoDoc command @Example is an alias of @BeginExample.

2.2-10 @BeginExampleSession and @EndExampleSession

@BeginExampleSession marks the start of an example to be put into the manual, while @EndExampleSession ends the example block. It is the direct analog of GAPDoc's <Example> (see GAPDoc: Log).

To illustrate this command, consider this input:

#! @BeginExampleSession
#! gap> S5 := SymmetricGroup(5);
#! Sym( [ 1 .. 5 ] )
#! gap> Order(S5);
#! 120
#! @EndExampleSession

This results in the following output:

gap> S5 := SymmetricGroup(5);
Sym( [ 1 .. 5 ] )
gap> Order(S5);
120

It inserts an example into the manual just as @Example would do, but all lines are commented and therefore not executed when the file is read. All lines that should be part of the example displayed in the manual have to start with an AutoDoc comment (#!). The comment will be removed, and, if the following character is a space, this space will also be removed. There is never more than one space removed. To ensure examples are correctly colored in the manual, there should be exactly one space between #! and the gap> prompt. The AutoDoc command @ExampleSession is an alias of @BeginExampleSession.

2.2-11 @BeginLog and @EndLog

Works just like the @BeginExample command, but the example will not be tested. See the GAPDoc manual for more information. The AutoDoc command @Log is an alias of @BeginLog.

2.2-12 @BeginLogSession and @EndLogSession

Works just like the @BeginExampleSession command, but the example will not be tested if manual examples are run. It is the direct analog of GAPDoc's <Log> (see GAPDoc: Log). The AutoDoc command @LogSession is an alias of @BeginLogSession.

2.2-13 @DoNotReadRestOfFile

Prevents the rest of the file from being read by the parser. Useful for unfinished or temporary files.

#! This will appear in the manual

#! @DoNotReadRestOfFile

#! This will not appear in the manual.

2.2-14 @BeginChunk name, @EndChunk, and @InsertChunk name

Text inside a @BeginChunk / @EndChunk part will not be inserted into the final documentation directly. Instead, the text is stored in an internal buffer. That chunk of text can then later on be inserted in any other place by using the @InsertChunk name command. If you do not provide an @EndChunk, the chunk ends at the end of the file.

#! @BeginChunk MyChunk
#! Hello, world.
#! @EndChunk

#! @InsertChunk MyChunk
## The text "Hello, world." is inserted right before this.

You can use this to define an example like this in one file:

#! @BeginChunk Example_Symmetric_Group
#! @BeginExample
S5 := SymmetricGroup(5);
#! Sym( [ 1 .. 5 ] )
Order(S5);
#! 120
#! @EndExample
#! @EndChunk

And then later, insert the example in a different file, like this:

#! @InsertChunk Example_Symmetric_Group

2.2-15 @BeginCode name, @EndCode, and @InsertCode name

Inserts the text between @BeginCode and @EndCode verbatim at the point where @InsertCode is called. This is useful to insert code excerpts directly into the manual.

#! @BeginCode Increment
i := i + 1;
#! @EndCode

#! @InsertCode Increment
## Code is inserted here.

2.2-16 @LatexOnly text, @BeginLatexOnly, and @EndLatexOnly

Code inserted between @BeginLatexOnly and @EndLatexOnly or after @LatexOnly is only inserted in the PDF version of the manual or worksheet. It can hold arbitrary LaTeX-commands.

#! @BeginLatexOnly
#! \include{picture.tex}
#! @EndLatexOnly

#! @LatexOnly \include{picture.tex}

2.2-17 @NotLatex text, @BeginNotLatex, and @EndNotLatex

Code inserted between @BeginNotLatex and @EndNotLatex or after @NotLatex is inserted in the HTML and text versions of the manual or worksheet, but not in the PDF version.

#! @BeginNotLatex
#! For further information see the PDF version of this manual.
#! @EndNotLatex

#! @NotLatex For further information see the PDF version of this manual.

2.3 Title page commands

The following commands can be used to add the corresponding parts to the title page of the document which generated by AutoDoc if scaffolding is enabled.

Those add the following lines at the corresponding point of the title page. Please note that many of those things can be (better) extracted from the PackageInfo.g. In case you set some of those, the extracted or in scaffold defined items will be overwritten. While this is not very useful for documenting packages, they are necessary for worksheets created with AutoDocWorksheet (3.1-1), since worksheets do not have a PackageInfo.g file from which this information could be extracted.

2.4 Plain text files

Files that have the suffix .autodoc and are listed in the autodoc.files option of AutoDoc (4.1-1), resp. are contained in one of the directories listed in autodoc.scan_dirs, are treated as AutoDoc plain text files. These work exactly like AutoDoc comments, except that lines do not need to (and in fact, should not) start with #!.

2.5 Grouping

In GAPDoc, it is possible to make groups of manual items, i.e., when documenting a function, operation, etc., it is possible to group them into suitable chunks. This can be particularly useful if there are several definitions of an operation with several different argument types, all doing more or less the same to the arguments. Then their manual items can be grouped, sharing the same description and return type information. You can give a heading to the group in the manual with the @GroupTitle command; if that is not supplied, then the heading of the first manual item in the group will be used as the heading.

Note that group names are globally unique throughout the whole manual. That is, groups with the same name are in fact merged into a single group, even if they were declared in different source files. Thus you can have multiple @BeginGroup / @EndGroup pairs using the same group name, in different places, and these all will refer to the same group.

Moreover, this means that you can add items to a group via the @Group command in the AutoDoc comment of an arbitrary declaration, at any time.

The following code

#! @BeginGroup Group1
#! @GroupTitle A family of operations

#! @Description
#!  First sentence.
DeclareOperation( "FirstOperation", [ IsInt ] );

#! @Description
#!  Second sentence.
DeclareOperation( "SecondOperation", [ IsInt, IsGroup ] );

#! @EndGroup

## .. Stuff ..

#! @Description
#!  Third sentence.
#! @Group Group1
KeyDependentOperation( "ThirdOperation", IsGroup, IsInt, "prime );

produces the following:

2.5-1 A family of operations
‣ FirstOperation( arg )( operation )
‣ SecondOperation( arg1, arg2 )( operation )
‣ ThirdOperation( arg1, arg2 )( operation )

First sentence. Second sentence. Third sentence.

2.6 Level

Levels can be set to not write certain parts in the manual by default. Every entry has by default the level 0. The command @Level can be used to set the level of the following part to a higher level, for example 1, and prevent it from being printed to the manual by default. However, if one sets the level to a higher value in the autodoc option of AutoDoc, the parts will be included in the manual at the specific place.

#! This text will be printed to the manual.
#! @Level 1
#! This text will be printed to the manual if created with level 1 or higher.
#! @Level 2
#! This text will be printed to the manual if created with level 2 or higher.
#! @ResetLevel
#! This text will be printed to the manual.

2.7 Markdown-like formatting of text in AutoDoc

AutoDoc has some convenient ways to insert special format into text, like math formulas and lists. The syntax for them are inspired by Markdown and LaTeX, but do not follow them strictly. Neither are all features of the Markdown language supported. The following subsections describe what is possible.

2.7-1 Lists

One can create lists of items by beginning a new line with *, +, -, followed by one space. The first item starts the list. When items are longer than one line, the following lines have to be indented by at least two spaces. The list ends when a line which does not start a new item is not indented by two spaces. Of course lists can be nested. Here is an example:

#! The list starts in the next line
#! * item 1
#! * item 2
#!   which is a bit longer
#!   * and also contains a nested list
#!   * with two items
#! * item 3 of the outer list
#! This does not belong to the list anymore.

This is the output:
The list starts in the next line

This does not belong to the list anymore.
The *, -, and + are fully interchangeable and can even be used mixed, but this is not recommended.

2.7-2 Math modes

One can start an inline formula with a $, and also end it with $, just like in LaTeX. This will translate into GAPDocs inline math environment. For display mode one can use $$, also like LaTeX.

#! This is an inline formula: $1+1 = 2$.
#! This is a display formula:
#! $$ \sum_{i=1}^n i. $$

produces the following output:
This is an inline formula: \(1+1 = 2\). This is a display formula:

\[ \sum_{i=1}^n i. \]

2.7-3 Emphasize

One can emphasize text by using two asterisks (**) or two underscores (__) at the beginning and the end of the text which should be emphasized. Example:

#! **This** is very important.
#! This is __also important__.
#! **Naturally, more than one line
#! can be important.**

This produces the following output:
This is very important. This is also important. Naturally, more than one line can be important.

2.7-4 Inline code

One can mark inline code snippets by using backticks (`) at the beginning and the end of the text which should be marked as code. Example:

#! Call function `foobar()` at the start.

This produces the following output:
Call function foobar() at the start.

2.8 Deprecated commands

The following commands used to be supported, but are not anymore.

@EndSection

You can simply remove any use of this, AutoDoc ends sections automatically at the start of any new section or chapter.

@EndSubsection

You can simply remove any use of this, AutoDoc ends subsections automatically at the start of any new subsection, section or chapter.

@BeginAutoDoc and @EndAutoDoc

It suffices to prepend each declaration that is meant to be appear in the manual with a minimal AutoDoc comment #!.

@BeginSystem name, @EndSystem, and @InsertSystem name

Please use the chunk commands from subsection 2.2-14 instead.

@AutoDocPlainText and @EndAutoDocPlainText

Use .autodoc files or AutoDoc comments instead.

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chap0.html0000644000175100017510000003751515074117054015521 0ustar runnerrunner GAP (AutoDoc) - Contents
Goto Chapter: Top 1 2 3 4 Bib Ind
 [Top of Book]  [Contents]   [Next Chapter] 

AutoDoc

Generate documentation from GAP source code

2025.10.16

16 October 2025

Sebastian Gutsche
Email: gutsche@mathematik.uni-siegen.de
Homepage: https://algebra.mathematik.uni-siegen.de/gutsche/
Address:
Department Mathematik
Universität Siegen
Walter-Flex-Straße 3
57072 Siegen
Germany

Max Horn
Email: mhorn@rptu.de
Homepage: https://www.quendi.de/math
Address:
Fachbereich Mathematik
RPTU Kaiserslautern-Landau
Gottlieb-Daimler-Straße 48
67663 Kaiserslautern
Germany

Abstract

AutoDoc is a GAP package whose purpose is to aid GAP package authors in creating and maintaining the documentation of their packages.

Copyright

© 2012-2022 by Sebastian Gutsche and Max Horn

This package may be distributed under the terms and conditions of the GNU Public License Version 2 or (at your option) any later version.

Acknowledgements

This documentation was prepared using the GAPDoc package [LN12].

Contents

1 Getting started using AutoDoc
2 AutoDoc documentation comments
3 AutoDoc worksheets
4 AutoDoc
References
Index

 [Top of Book]  [Contents]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/_Chapter_AutoDoc.xml0000644000175100017510000004212415074117054017515 0ustar runnerrunner AutoDoc
The AutoDoc() function nothing This is the main function of the &AutoDoc; package. It can perform any combination of the following tasks: It can (re)generate a scaffold for your package manual. That is, it can produce two XML files in &GAPDoc; format to be used as part of your manual: First, a file named doc/PACKAGENAME.xml (with your package's name substituted) which is used as main XML file for the package manual, i.e. this file sets the XML doctype and defines various XML entities, includes other XML files (both those generated by &AutoDoc; as well as additional files created by other means), tells &GAPDoc; to generate a table of contents and an index, and more. Secondly, it creates a file doc/title.xml containing a title page for your documentation, with information about your package (name, description, version), its authors and more, based on the data in your PackageInfo.g. It can scan your package for &AutoDoc; based documentation (by using &AutoDoc; tags and the Autodoc command. This will produce further XML files to be used as part of the package manual. It can use &GAPDoc; to generate PDF, text and HTML (with MathJaX enabled) documentation from the &GAPDoc; XML files it generated as well as additional such files provided by you. For this, it invokes to convert the XML sources, and it also instructs &GAPDoc; to copy supplementary files (such as CSS style files) into your doc directory (see ). For more information and some examples, please refer to Chapter .

The parameters have the following meanings: packageOrDirectory The purpose of this parameter is twofold: to determine the package directory in which &AutoDoc; will operate, and to find the metadata concerning the package being documented. The parameter is either a string, an IsDirectory object, or omitted. If it is a string, &AutoDoc; interprets it as the name of a package, uses the metadata of the first package known to &GAP; with that name, and uses the InstallationPath specified in that metadata as the package directory. If packageOrDirectory is an IsDirectory object, this is used as package directory; if the argument is omitted, then the current directory is used. In the last two cases, the specified directory must contain a PackageInfo.g file, and &AutoDoc; extracts all needed metadata from that. The IsDirectory form is for example useful if you have multiple versions of the package around and want to make sure the documentation of the correct version is built.

Note that when using AutoDocWorksheet (see ), there is no parameter corresponding to packageOrDirectory and so the package directory is always the current directory, and there is no metadata. optrec optrec can be a record with some additional options. The following are currently supported: dir This should either be a string, in which case it must be a path relative to the specified package directory, or a Directory() object. (Thus, the only way to designate an absolute directory is with a Directory() object.) This option specifies where the package documentation (e.g. the &GAPDoc; XML or the manual PDF, etc.) files are stored and/or will be generated.
Default value: "doc/".
scaffold This controls whether and how to generate scaffold XML files for the package documentation.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.scaffold is missing but the package's info record in PackageInfo.g has an AutoDoc entry. In all other cases (in particular if opt.scaffold is false), scaffolding is disabled.

If scaffolding is enabled, and PackageInfo.AutoDoc exists, then it is assumed to be a record, and its contents are used as default values for the scaffold settings.

If opt.scaffold is a record, it may contain the following entries.

includes A list of XML files to be included in the body of the main XML file. If you specify this list and also are using &AutoDoc; to document your operations with &AutoDoc; comments, you can add _AutoDocMainFile.xml to this list to control at which point the documentation produced by &AutoDoc; is inserted. If you do not do this, it will be added after the last of your own XML files. index By default, the scaffold creates an index. If you do not want an index, set this to false. appendix This entry is similar to opt.scaffold.includes but is used to specify files to include after the main body of the manual, i.e. typically appendices. bib The name of a bibliography file, in BibTeX or XML format. If this key is not set, but there is a file doc/PACKAGENAME.bib then it is assumed that you want to use this as your bibliography. entities A record whose keys are taken as entity names, set to the corresponding (string) values. For example, if you pass the record SomePackage,

SomePackage", RELEASEYEAR := "2015" )]]> then the following entity definitions are added to the XML preamble: SomePackage'> ]]> This allows you to write &SomePackage; and &RELEASEYEAR; in your documentation, which will be replaced by respective values specified in the entities definition. TitlePage A record whose entries are used to embellish the generated title page for the package manual with extra information, such as a copyright statement or acknowledgments. To this end, the names of the record components are used as XML element names, and the values of the components are outputted as content of these XML elements. For example, you could pass the following record to set a custom acknowledgements text: For a list of valid entries in the title page, please refer to the &GAPDoc; manual, specifically section . MainPage If scaffolding is enabled, by default a main XML file is generated (this is the file which contains the XML doctype and more). If you do not want this (e.g. because you have a handwritten main XML file), but still want &AutoDoc; to generate a title page for you, you can set this option to false document_class Sets the document class of the resulting PDF. The value can either be a string which has to be the name of the new document class, a list containing this string, or a list of two strings. Then the first one has to be the document class name, the second one the option string ( contained in [ ] ) in &LaTeX;. latex_header_file Replaces the standard header from &GAPDoc; completely with the header in this &LaTeX; file. Please be careful here, and look at &GAPDoc;'s latexheader.tex file for an example. autodoc This controls whether and how to generate additional XML documentation files by scanning for &AutoDoc; documentation comments.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.autodoc is missing but the package depends (directly) on the &AutoDoc; package. In all other cases (in particular if opt.autodoc is false), this feature is disabled.

If opt.autodoc is a record, it may contain the following entries.

files A list of files (given by paths relative to the package directory) to be scanned for &AutoDoc; documentation comments. Usually it is more convenient to use autodoc.scan_dirs, see below. scan_dirs A list of subdirectories of the package directory (given as relative paths) which &AutoDoc; then scans for .gi, .gd, .g, and .autodoc files; all of these files are then scanned for &AutoDoc; documentation comments.
Default value: [ ".", "gap", "lib", "examples", "examples/doc" ].
level This defines the level of the created documentation. The default value is 0. When parts of the manual are declared with a higher value they will not be printed into the manual.
gapdoc This controls whether and how to invoke &GAPDoc; to create HTML, PDF and text files from your various XML files.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.gapdoc is missing. In all other cases (in particular if opt.gapdoc is false), this feature is disabled.

If opt.gapdoc is a record, it may contain the following entries.

main The name of the main XML file of the package manual. This exists primarily to support packages with existing manual which use a filename here which differs from the default. In particular, specifying this is unnecessary when using scaffolding.
Default value: PACKAGENAME.xml.
files A list of files (given by paths relative to the package directory) to be scanned for &GAPDoc; documentation comments. Usually it is more convenient to use gapdoc.scan_dirs, see below. scan_dirs A list of subdirectories of the package directory (given as relative paths) which &AutoDoc; then scans for .gi, .gd and .g files; all of these files are then scanned for &GAPDoc; documentation comments.
Default value: [ ".", "gap", "lib", "examples", "examples/doc" ].
LaTeXOptions Must be a record with entries which can be understood by . Each entry can be a string, which will be given to &GAPDoc; directly, or a list containing of two entries: The first one must be the string "file", the second one a filename. This file will be read and then its content is passed to &GAPDoc; as option with the name of the entry. gap_root_relative_path Either a boolean, or a string containing a relative path. By default (if this option is not set, or is set to false), references in the generated documentation referring to external documentation (such as the &GAP; manual) are encoded using absolute paths. This is fine as long as the documentation stays on only a single computer, but is problematic when preparing documentation that should be used on multiple computers, e.g., when creating a distribution archive of a &GAP; package.
Thus, if a relative path is provided via this option (or if it is set to true, in which case the relative path ../../.. is used), then &AutoDoc; and &GAPDoc; attempt to replace all absolute paths in references to &GAP; manuals by paths based on this relative path.

On a technical level, &AutoDoc; passes the relative path to the gaproot parameter of

extract_examples Either true or a record. If set to true, then all manual examples are extracted and placed into files tst/PACKAGENAME01.tst, tst/PACKAGENAME02.tst, ... and so on, with one file for each chapter. For chapters with no examples, no file is created.

As a record, the entry can have the following entries itself, to specify some options. units This controls how examples are grouped into files. Recognized values are "Chapter" (default), "Section", "Subsection" or "Single". Depending on the value, one file is created for each chapter, each section, each subsection or each example. For all other values only a single file is created.

On a technical level, &AutoDoc; passes the value to the units parameter of . skip_empty_in_numbering If set to true (the default), the generated files use filenames with strictly sequential numbering; that means that if chapter 1 (or whatever units are being used) contains no examples but chapter 2 does, then the examples for chapter 2 are put into the file tst/PACKAGENAME01.tst. If this option is set to false, then the chapter numbers are used to generate the filenames; so the examples for chapter 2 would be put into the file tst/PACKAGENAME02.tst.

Info class for the AutoDoc package. Set this to 0 to suppress info messages, 1 to allow most messages, and 2 to allow all messages including those that contain file paths.

This can be set by calling, for example, SetInfoLevel(InfoPackageManager, 0). Default value 1.

Examples

Some basic examples for using AutoDoc were already shown in Chapter .

AutoDoc-2025.10.16/doc/chap0_mj.html0000644000175100017510000004030215074117054016173 0ustar runnerrunner GAP (AutoDoc) - Contents
Goto Chapter: Top 1 2 3 4 Bib Ind
 [Top of Book]  [Contents]   [Next Chapter] 

AutoDoc

Generate documentation from GAP source code

2025.10.16

16 October 2025

Sebastian Gutsche
Email: gutsche@mathematik.uni-siegen.de
Homepage: https://algebra.mathematik.uni-siegen.de/gutsche/
Address:
Department Mathematik
Universität Siegen
Walter-Flex-Straße 3
57072 Siegen
Germany

Max Horn
Email: mhorn@rptu.de
Homepage: https://www.quendi.de/math
Address:
Fachbereich Mathematik
RPTU Kaiserslautern-Landau
Gottlieb-Daimler-Straße 48
67663 Kaiserslautern
Germany

Abstract

AutoDoc is a GAP package whose purpose is to aid GAP package authors in creating and maintaining the documentation of their packages.

Copyright

© 2012-2022 by Sebastian Gutsche and Max Horn

This package may be distributed under the terms and conditions of the GNU Public License Version 2 or (at your option) any later version.

Acknowledgements

This documentation was prepared using the GAPDoc package [LN12].

Contents

1 Getting started using AutoDoc
2 AutoDoc documentation comments
3 AutoDoc worksheets
4 AutoDoc
References
Index

 [Top of Book]  [Contents]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chapBib.txt0000644000175100017510000000046715074117054015725 0ustar runnerrunner References [LN12] Lübeck, F. and Neunhöffer, M., GAPDoc (Version 1.5.1), RWTH Aachen (2012), ( GAP package, http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html ).  AutoDoc-2025.10.16/doc/AutoDoc.tex0000644000175100017510000024120415074117054015710 0ustar runnerrunner% generated by GAPDoc2LaTeX from XML source (Frank Luebeck) \documentclass[a4paper,11pt]{report} \usepackage{a4wide} \newcommand{\bbZ}{\mathbb{Z}} \usepackage[top=37mm,bottom=37mm,left=27mm,right=27mm]{geometry} \sloppy \pagestyle{myheadings} \usepackage{amssymb} \usepackage[utf8]{inputenc} \usepackage{makeidx} \makeindex \usepackage{color} \definecolor{FireBrick}{rgb}{0.5812,0.0074,0.0083} \definecolor{RoyalBlue}{rgb}{0.0236,0.0894,0.6179} \definecolor{RoyalGreen}{rgb}{0.0236,0.6179,0.0894} \definecolor{RoyalRed}{rgb}{0.6179,0.0236,0.0894} \definecolor{LightBlue}{rgb}{0.8544,0.9511,1.0000} \definecolor{Black}{rgb}{0.0,0.0,0.0} \definecolor{linkColor}{rgb}{0.0,0.0,0.554} \definecolor{citeColor}{rgb}{0.0,0.0,0.554} \definecolor{fileColor}{rgb}{0.0,0.0,0.554} \definecolor{urlColor}{rgb}{0.0,0.0,0.554} \definecolor{promptColor}{rgb}{0.0,0.0,0.589} \definecolor{brkpromptColor}{rgb}{0.589,0.0,0.0} \definecolor{gapinputColor}{rgb}{0.589,0.0,0.0} \definecolor{gapoutputColor}{rgb}{0.0,0.0,0.0} %% for a long time these were red and blue by default, %% now black, but keep variables to overwrite \definecolor{FuncColor}{rgb}{0.0,0.0,0.0} %% strange name because of pdflatex bug: \definecolor{Chapter }{rgb}{0.0,0.0,0.0} \definecolor{DarkOlive}{rgb}{0.1047,0.2412,0.0064} \usepackage{fancyvrb} \usepackage{mathptmx,helvet} \usepackage[T1]{fontenc} \usepackage{textcomp} \usepackage[ pdftex=true, bookmarks=true, a4paper=true, pdftitle={Written with GAPDoc}, pdfcreator={LaTeX with hyperref package / GAPDoc}, colorlinks=true, backref=page, breaklinks=true, linkcolor=linkColor, citecolor=citeColor, filecolor=fileColor, urlcolor=urlColor, pdfpagemode={UseNone}, ]{hyperref} \newcommand{\maintitlesize}{\fontsize{50}{55}\selectfont} % write page numbers to a .pnr log file for online help \newwrite\pagenrlog \immediate\openout\pagenrlog =\jobname.pnr \immediate\write\pagenrlog{PAGENRS := [} \newcommand{\logpage}[1]{\protect\write\pagenrlog{#1, \thepage,}} %% were never documented, give conflicts with some additional packages \newcommand{\GAP}{\textsf{GAP}} %% nicer description environments, allows long labels \usepackage{enumitem} \setdescription{style=nextline} %% depth of toc \setcounter{tocdepth}{1} %% command for ColorPrompt style examples \newcommand{\gapprompt}[1]{\color{promptColor}{\bfseries #1}} \newcommand{\gapbrkprompt}[1]{\color{brkpromptColor}{\bfseries #1}} \newcommand{\gapinput}[1]{\color{gapinputColor}{#1}} \begin{document} \logpage{[ 0, 0, 0 ]} \begin{titlepage} \mbox{}\vfill \begin{center}{\maintitlesize \textbf{ AutoDoc \mbox{}}}\\ \vfill \hypersetup{pdftitle= AutoDoc } \markright{\scriptsize \mbox{}\hfill AutoDoc \hfill\mbox{}} {\Huge \textbf{ Generate documentation from \textsf{GAP} source code \mbox{}}}\\ \vfill {\Huge 2025.10.16 \mbox{}}\\[1cm] { 16 October 2025 \mbox{}}\\[1cm] \mbox{}\\[2cm] {\Large \textbf{ Sebastian Gutsche\\ \mbox{}}}\\ {\Large \textbf{ Max Horn\\ \mbox{}}}\\ \hypersetup{pdfauthor= Sebastian Gutsche\\ ; Max Horn\\ } \end{center}\vfill \mbox{}\\ {\mbox{}\\ \small \noindent \textbf{ Sebastian Gutsche\\ } Email: \href{mailto://gutsche@mathematik.uni-siegen.de} {\texttt{gutsche@mathematik.uni\texttt{\symbol{45}}siegen.de}}\\ Homepage: \href{https://algebra.mathematik.uni-siegen.de/gutsche/} {\texttt{https://algebra.mathematik.uni\texttt{\symbol{45}}siegen.de/gutsche/}}\\ Address: \begin{minipage}[t]{8cm}\noindent Department Mathematik\\ Universit{\"a}t Siegen\\ Walter\texttt{\symbol{45}}Flex\texttt{\symbol{45}}Stra{\ss}e 3\\ 57072 Siegen\\ Germany\\ \end{minipage} }\\ {\mbox{}\\ \small \noindent \textbf{ Max Horn\\ } Email: \href{mailto://mhorn@rptu.de} {\texttt{mhorn@rptu.de}}\\ Homepage: \href{https://www.quendi.de/math} {\texttt{https://www.quendi.de/math}}\\ Address: \begin{minipage}[t]{8cm}\noindent Fachbereich Mathematik\\ RPTU Kaiserslautern\texttt{\symbol{45}}Landau\\ Gottlieb\texttt{\symbol{45}}Daimler\texttt{\symbol{45}}Stra{\ss}e 48\\ 67663 Kaiserslautern\\ Germany\\ \end{minipage} }\\ \end{titlepage} \newpage\setcounter{page}{2} {\small \section*{Abstract} \logpage{[ 0, 0, 1 ]} \textsf{AutoDoc} is a \textsf{GAP} package whose purpose is to aid \textsf{GAP} package authors in creating and maintaining the documentation of their packages. \mbox{}}\\[1cm] {\small \section*{Copyright} \logpage{[ 0, 0, 2 ]} {\copyright} 2012\texttt{\symbol{45}}2022 by Sebastian Gutsche and Max Horn This package may be distributed under the terms and conditions of the GNU Public License Version 2 or (at your option) any later version. \mbox{}}\\[1cm] {\small \section*{Acknowledgements} \logpage{[ 0, 0, 3 ]} This documentation was prepared using the \textsf{GAPDoc} package \cite{GAPDoc}. \mbox{}}\\[1cm] \newpage \def\contentsname{Contents\logpage{[ 0, 0, 4 ]}} \tableofcontents \newpage \chapter{\textcolor{Chapter }{Getting started using \textsf{AutoDoc}}}\label{Tutorials} \logpage{[ 1, 0, 0 ]} \hyperdef{L}{X7A0D7AA484F466E1}{} { \textsf{AutoDoc} is a \textsf{GAP} package which is meant to aid \textsf{GAP} package authors in creating and maintaining the documentation of their packages. In this capacity it builds upon the \textsf{GAPDoc} package (see \href{https://www.gap-system.org/Packages/gapdoc.html} {\texttt{https://www.gap\texttt{\symbol{45}}system.org/Packages/gapdoc.html}}). As such, it is not a replacement for \textsf{GAPDoc}, but rather complements it. In this chapter we describe how to get started using \textsf{AutoDoc} for your package. First, we explain in Section \ref{Tut:Scratch} how to write a new package manual from scratch. Then we show in Section \ref{Tut:IntegrateExisting} how you might benefit from \textsf{AutoDoc} even if you already have a complete manual written using \textsf{GAPDoc}. In Section \ref{Tut:Scaffolds}, we explain how you may use \textsf{AutoDoc} to generate a title page and the main XML file for your manual. Finally, Section \ref{Tut:AutoDocWorksheet}, explains what \textsf{AutoDoc} worksheets are and how to use them. \section{\textcolor{Chapter }{Creating a package manual from scratch}}\label{Tut:Scratch} \logpage{[ 1, 1, 0 ]} \hyperdef{L}{X7BFBC6907B26AA95}{} { Suppose your package is already up and running, but so far has no manual. Then you can rapidly generate a ``scaffold'' for a package manual using the \texttt{AutoDoc} (\ref{AutoDoc}) command like this, while running \textsf{GAP} from within your package's directory (the one containing the \texttt{PackageInfo.g} file): \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true ) ); \end{Verbatim} This first reads the \texttt{PackageInfo.g} file from the current directory. It extracts information about the package from it (such as its name and version, see Section \ref{Tut:Scaffolds:Title}). It then creates two XML files \texttt{doc/NAME{\textunderscore}OF{\textunderscore}YOUR{\textunderscore}PACKAGE.xml} and \texttt{doc/title.xml} inside the package directory. Finally, it runs \textsf{GAPDoc} on them to produce a nice initial PDF and HTML version of your fresh manual. To ensure that the \textsf{GAP} help system picks up your package manual, you should also add something like the following to your \texttt{PackageInfo.g}: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] PackageDoc := rec( BookName := ~.PackageName, ArchiveURLSubset := ["doc"], HTMLStart := "doc/chap0.html", PDFFile := "doc/manual.pdf", SixFile := "doc/manual.six", LongTitle := ~.Subtitle, ), \end{Verbatim} Congratulations, your package now has a minimal working manual. Of course it will be mostly empty for now, but it already should contain some useful information, based on the data in your \texttt{PackageInfo.g}. This includes your package's name, version and description as well as information about its authors. And if you ever change the package data, (e.g. because your email address changed), just re\texttt{\symbol{45}}run the above command to regenerate the two main XML files with the latest information. Next of course you need to provide actual content (unfortunately, we were not yet able to automate \emph{that} for you, more research on artificial intelligence is required). To add more content, you have several options: You could add further \textsf{GAPDoc} XML files containing extra chapters, sections and so on. Or you could use classic \textsf{GAPDoc} source comments. For details on either, please refer to (\textbf{GAPDoc: Distributing a Document into Several Files}), as well as Section \ref{Tut:IntegrateExisting} of this manual on how to teach the \texttt{AutoDoc} (\ref{AutoDoc}) command to include this extra documentation. Or you could use the special documentation facilities \textsf{AutoDoc} provides (see Section \ref{Tut:AdvancedAutoDoc}). You will probably want to re\texttt{\symbol{45}}run the \texttt{AutoDoc} (\ref{AutoDoc}) command frequently, e.g. whenever you modified your documentation or your \texttt{PackageInfo.g}. To make this more convenient and reproducible, we recommend putting its invocation into a file \texttt{makedoc.g} in your package \index{makedoc.g@\texttt{makedoc.g}} directory, with content based on the following example: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( autodoc := true ) ); QUIT; \end{Verbatim} Then you can regenerate the package manual from the command line with the following command, executed from within in the package directory: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] gap makedoc.g \end{Verbatim} } \section{\textcolor{Chapter }{Documenting code with \textsf{AutoDoc}}}\label{Tut:AdvancedAutoDoc} \logpage{[ 1, 2, 0 ]} \hyperdef{L}{X87A00EED866E22E8}{} { To get one of your global functions, operations, attributes etc. to appear in the package manual, simply insert an \textsf{AutoDoc} comment of the form \texttt{\#!} directly in front of it. For example: \begin{Verbatim}[commandchars=@|A,fontsize=\small,frame=single,label=] #! DeclareOperation( "ToricVariety", [ IsConvexObject ] ); \end{Verbatim} This tiny change is already sufficient to ensure that the operation appears in the manual. In general, you will want to add further information about the operation, such as in the following example: \begin{Verbatim}[commandchars=|BE,fontsize=\small,frame=single,label=] #! @Arguments conv #! @Returns a toric variety #! @Description #! Creates a toric variety out #! of the convex object conv. DeclareOperation( "ToricVariety", [ IsConvexObject ] ); \end{Verbatim} For a thorough description of what you can do with \textsf{AutoDoc} documentation comments, please refer to chapter \ref{Comments}. Suppose you have not been using \textsf{GAPDoc} before but instead used the process described in section \ref{Tut:Scratch} to create your manual. Then the following \textsf{GAP} command will regenerate the manual and automatically include all newly documented functions, operations etc.: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true, autodoc := true ) ); \end{Verbatim} If you are not using the scaffolding feature, e.g. because you already have an existing \textsf{GAPDoc} based manual, then you can still use \textsf{AutoDoc} documentation comments. Just make sure to first edit the main XML file of your documentation, and insert the line \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] <#Include SYSTEM "_AutoDocMainFile.xml"> \end{Verbatim} in a suitable place. This means that you can mix \textsf{AutoDoc} documentation comment freely with your existing documentation; you can even still make use of any existing \textsf{GAPDoc} documentation comments in your code. The following command should be useful for you in this case; it still scans the package code for \textsf{AutoDoc} documentation comments and the runs \textsf{GAPDoc} to produce HTML and PDF output, but does not touch your documentation XML files otherwise. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( autodoc := true ) ); \end{Verbatim} } \section{\textcolor{Chapter }{Using \textsf{AutoDoc} in an existing \textsf{GAPDoc} manual}}\label{Tut:IntegrateExisting} \logpage{[ 1, 3, 0 ]} \hyperdef{L}{X7FA614637B807F4D}{} { Even if you already have an existing \textsf{GAPDoc} manual, it might be interesting for you to use \textsf{AutoDoc} for two purposes: First off, with \textsf{AutoDoc} it is very convenient to regenerate your documentation. Secondly, the scaffolding feature which generates a title page with all the metadata of your package in a uniform way is very handy. The somewhat tedious process of keeping your title page in sync with your \texttt{PackageInfo.g} is fully automated this way (including the correct version, release data, author information and so on). There are various examples of packages using \textsf{AutoDoc} for this purpose only, e.g. \textsf{io} and \textsf{orb}. \subsection{\textcolor{Chapter }{Using \textsf{AutoDoc} on a complete \textsf{GAPDoc} manual}}\label{Tut:IntegrateExisting:EverythingThere} \logpage{[ 1, 3, 1 ]} \hyperdef{L}{X7F3CEB097AF47C1E}{} { Suppose you already have a complete XML manual, with some main and title XML files and some documentation for operations distributed over all your \texttt{.g}, \texttt{.gd}, and \texttt{.gi} files. Suppose the main XML file is named \texttt{PACKAGENAME.xml} and is in the \texttt{/doc} subdirectory of your package. Then you can rebuild your manual by executing the following two \textsf{GAP} commands from a \textsf{GAP} session started in the root directory of your package: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( ); \end{Verbatim} In contrast, the \textsf{RingsForHomalg} package currently uses essentially the following code in its \texttt{makedoc.g} file to achieve the same result: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "GAPDoc" ); SetGapDocLaTeXOptions( "utf8" ); bib := ParseBibFiles( "doc/RingsForHomalg.bib" ); WriteBibXMLextFile( "doc/RingsForHomalgBib.xml", bib ); list := [ "../gap/RingsForHomalg.gd", "../gap/RingsForHomalg.gi", "../gap/Singular.gi", "../gap/SingularBasic.gi", "../examples/RingConstructionsExternalGAP.g", "../examples/RingConstructionsSingular.g", "../examples/RingConstructionsMAGMA.g", "../examples/RingConstructionsMacaulay2.g", "../examples/RingConstructionsSage.g", "../examples/RingConstructionsMaple.g", ]; MakeGAPDocDoc( "doc", "RingsForHomalg", list, "RingsForHomalg" ); GAPDocManualLab( "RingsForHomalg" ); \end{Verbatim} Note that in particular, you do not have to worry about keeping a list of your implementation files up\texttt{\symbol{45}}to\texttt{\symbol{45}}date. But there is more. \textsf{AutoDoc} can create \texttt{.tst} files from the examples in your manual to test your package. This can be achieved via \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( extract_examples := true ) ); \end{Verbatim} Now files \texttt{PACKAGENAME01.tst}, \texttt{PACKAGENAME02.tst} and so appear in the \texttt{tst/} subdirectory of your package, and can be tested as usual using \texttt{Test} (\textbf{Reference: Test}) respectively \texttt{TestDirectory} (\textbf{Reference: TestDirectory}). } \subsection{\textcolor{Chapter }{Setting different \textsf{GAPDoc} options}}\label{Tut:IntegrateExisting:GapDocOptions} \logpage{[ 1, 3, 2 ]} \hyperdef{L}{X7D0DDF2284F2D24A}{} { Sometimes, the default values for the \textsf{GAPDoc} command used by \textsf{AutoDoc} may not be suitable for your manual. Suppose your main XML file is \emph{not} named \texttt{PACKAGENAME.xml}, but rather something else, e.g. \texttt{main.xml}. Then you can tell \textsf{AutoDoc} to use this file as the main XML file via \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( main := "main" ) ) ); \end{Verbatim} As explained above, by default \textsf{AutoDoc} scans all \texttt{.g}, \texttt{.gd} and \texttt{.gi} files it can find inside of your package root directory, and in the subdirectories \texttt{gap}, \texttt{lib}, \texttt{examples} and \texttt{examples/doc} as well. If you keep source files with documentation in other directories, you can adjust the list of directories AutoDoc scans via the \texttt{scan{\textunderscore}dirs} option. The following example illustrates this by instructing \textsf{AutoDoc} to only search in the subdirectory \texttt{package{\textunderscore}sources} of the packages root directory. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( scan_dirs := [ "package_sources" ] ) ) ); \end{Verbatim} You can also specify an explicit list of files containing documentation, which will be searched in addition to any files located within the scan directories: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( files := [ "path/to/some/hidden/file.gds" ] ) ) ); \end{Verbatim} Giving such a file does not prevent the standard \texttt{scan{\textunderscore}dirs} from being scanned for other files. Next, \textsf{GAPDoc} supports the documentation to be built with relative paths. This means, links to manuals of other packages or the \textsf{GAP} library will not be absolute, but relative from your documentation. This can be particularly useful if you want to build a release tarball or move your \textsf{GAP} installation around later. Suppose you are starting \textsf{GAP} in the root path of your package as always, and the standard call of \texttt{AutoDoc} (\ref{AutoDoc}) will then build the documentation in the \texttt{doc} subdirectory of your package. From this directory, the gap root directory has the relative path \texttt{../../..}. Then you can enable the relative paths by \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( gap_root_relative_path := "../../.." ) ) ); \end{Verbatim} or, since \texttt{../../..} is the standard option for \texttt{gap{\textunderscore}root{\textunderscore}relative{\textunderscore}path}, by \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( gap_root_relative_path := true ) ) ); \end{Verbatim} } \subsection{\textcolor{Chapter }{ Checklist for converting an existing \textsf{GAPDoc} manual to use \textsf{AutoDoc} }}\label{Tut:Checklist} \logpage{[ 1, 3, 3 ]} \hyperdef{L}{X83448D91868D7994}{} { Here is a checklist for authors of a package \textsf{PackageName}, \emph{which already has a \textsf{GAPDoc} based manual}, who wish to use \textsf{AutoDoc} to build the manual from now on. We assume that the manual is currently built by reading a file \texttt{makedoc.g} and that the main \texttt{.xml} file is named \texttt{manual.xml}. The files \texttt{PackageInfo.g}, \texttt{makedoc.g}, \texttt{doc/title.xml} and \texttt{doc/PackageName.xml} (if it exists) will be altered by this procedure, so it may be wise to keep backup copies. You should have copies of the \textsf{AutoDoc} files \texttt{PackageInfo.g} and \texttt{makedoc.g} to hand when reading these instructions. \begin{itemize} \item Copy \texttt{AutoDoc/makedoc.g} to \texttt{PackageName/makedoc.g}. \item Edit \texttt{PackageName/makedoc.g} as follows. \begin{itemize} \item Change the header comment to match other files in your package. \item After \texttt{LoadPackage("AutoDoc");} add \texttt{LoadPackage("PackageName");}. \item In the \texttt{AutoDoc} record delete \texttt{autodoc := true;}. \item \index{Scaffold record in makedoc.g@} In the \texttt{scaffold} record change the \texttt{includes} list to be the list of your \texttt{.xml} files that are contained in \texttt{manual.xml}. \item \index{Bibliography field in makedoc.g@} If you do not have a bibliography you may delete the \texttt{bib := "bib.xml",} field in the scaffold. Otherwise, edit the file name if you have a different file. If you only have a \texttt{.bib} file (\texttt{manual.bib} or \texttt{bib.xml.bib} say) you should rename this file \texttt{PackageName.bib}. \item \index{LaTeXOptions record in makedoc.g@} In the \texttt{LaTeXOptions} record, which is in the \texttt{gapdoc} record, enter any {\LaTeX} \texttt{newcommands} previously in \texttt{manual.xml}. (If there are none you may safely delete this record.) To illustrate this option, the \textsf{AutoDoc} file \texttt{makedoc.g} defines the command \texttt{\texttt{\symbol{92}}bbZ} by \texttt{\texttt{\symbol{92}}newcommand\texttt{\symbol{123}}\texttt{\symbol{92}}bbZ\texttt{\symbol{125}}\texttt{\symbol{123}}\texttt{\symbol{92}}mathbb\texttt{\symbol{123}}Z\texttt{\symbol{125}}\texttt{\symbol{125}}}, which may be used to produce the {\LaTeX} formula $f : \bbZ^2 \to \bbZ$. However, note that this only works in the PDF version of the file. \end{itemize} \item Now edit \texttt{PackageName/PackageInfo.g} as follows. \begin{itemize} \item Delete any \texttt{PKGVERSIONDATA} chunk that may be there. One reason for converting your manual to use \textsf{AutoDoc} is to stop using entities such as \texttt{PACKAGENAMEVERSION}. \item Copy the \texttt{AutoDoc} record from \texttt{AutoDoc/PackageInfo.g} to the end of your file (just before the final \texttt{"));"}. \item \index{Copyright field in PackageInfo.g@} \index{Abstract field in PackageInfo.g@} \index{Acknowledgements field in PackageInfo.g@} Replace the \texttt{Copyright}, \texttt{Abstract} and \texttt{Acknowledgements} fields of the \texttt{TitlePage} record with the corresponding material from your \texttt{manual.xml}. (If you do not have an abstract, then delete the \texttt{Abstract} field, etc.) \item \index{Entities record in makedoc.g@} In the \texttt{entities} record enter any entities previously stored in your \texttt{manual.xml}. (Again, if you have none, you may safely delete this record.) To illustrate this option the \textsf{AutoDoc} file \texttt{PackageInfo.g} defines entities for the names of packages \textsf{io} and \textsf{PackageName}. \end{itemize} \item If you are using a GitHub repository, as well as running "\texttt{git add}" on files \texttt{makedoc.g}, \texttt{PackageInfo.g} and \texttt{doc/PackageName.bib}, you should run "\texttt{git rm \texttt{\symbol{45}}f}" on files \texttt{doc/manual.xml}, and \texttt{doc/title.xml}. \end{itemize} You should now be ready to run \textsf{GAP} and \texttt{Read("makedoc.g");} in your package root directory. } } \section{\textcolor{Chapter }{Scaffolds}}\label{Tut:Scaffolds} \logpage{[ 1, 4, 0 ]} \hyperdef{L}{X8524193D824CDE0D}{} { \subsection{\textcolor{Chapter }{Generating a title page}}\label{Tut:Scaffolds:Title} \logpage{[ 1, 4, 1 ]} \hyperdef{L}{X7CF22DE28478316F}{} { For most (if not all) \textsf{GAP} packages, the title page of the package manual lists information such as the release date, version, names and contact details of the authors, and so on. All this data is also contained in your \texttt{PackageInfo.g}, and whenever you make a change to that file, there is a risk that you forget to update your manual to match. And even if you don't forget it, you of course have to spend some time to adjust the manual. \textsf{GAPDoc} can help to a degree with this via entities. Thus, you will sometimes see code like this in \texttt{PackageInfo.g} files: \begin{Verbatim}[commandchars=@|B,fontsize=\small,frame=single,label=] Version := "1.2.3", Date := "20/01/2015", ## <#GAPDoc Label="PKGVERSIONDATA"> ## ## ## ## <#/GAPDoc> \end{Verbatim} However, it is still easy to forget both of these versions. And it doesn't solve the problem of updating package authors addresses. Neither of these is a big issue, of course, but there have been plenty examples in the past where people forget either of these two things, and it can be slightly embarrassing. It may even require you to make a new release just to fix the issue, which in our opinion is a sad waste of your valuable time. So instead of worrying about manually synchronising these things, you can instruct \textsf{AutoDoc} to generate a title page for your manual based on the information in your \texttt{PackageInfo.g}. The following commands do just that (in addition to building your manual), by generating a file called \texttt{doc/title.xml}. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := rec( MainPage := false ) ) ); \end{Verbatim} Note that this only outputs \texttt{doc/title.xml} but does not touch any other files of your documentation. In particular, you need to explicitly include \texttt{doc/title.xml} from your main XML file. However, you can also tell \textsf{AutoDoc} to maintain the main XML file for you, in which case this is automatic. In fact, this is the default if you enable scaffolding; the above example command explicitly told \textsf{AutoDoc} not to generate a main page. } \subsection{\textcolor{Chapter }{Generating the main XML file}}\label{Tut:Scaffolds:Main} \logpage{[ 1, 4, 2 ]} \hyperdef{L}{X7CD72CC780874FD5}{} { The following generates a main XML file for your documentation in addition to the title page. The main XML file includes the title page by default, as well as any documentation generated from \textsf{AutoDoc} documentation comments. \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true ) ); \end{Verbatim} You can instruct \textsf{AutoDoc} to include additional XML files by giving it a list of filenames, as in the following example: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] LoadPackage( "AutoDoc" ); AutoDoc(rec( scaffold := rec( includes := [ "somefile.xml", "anotherfile.xml" ] ) )); \end{Verbatim} For more information, please consult the documentation of the \texttt{AutoDoc} (\ref{AutoDoc}) function. } \subsection{\textcolor{Chapter }{What data is used from \texttt{PackageInfo.g}?}}\label{Tut:PackageInfo} \logpage{[ 1, 4, 3 ]} \hyperdef{L}{X799956EA85D3FC15}{} { \textsf{AutoDoc} can use data from \texttt{PackageInfo.g} in order to generate a title page. Specifically, the following components of the package info record are taken into account: \begin{description} \item[{PackageName}] This is used to set the \texttt{{\textless}Title{\textgreater}} element of the title page. \item[{Subtitle}] This is used to set the \texttt{{\textless}Subtitle{\textgreater}} element of the title page. \item[{Version}] This is used to set the \texttt{{\textless}Version{\textgreater}} element of the title page, with the string ``Version '' prepended. \item[{Date}] This is used to set the \texttt{{\textless}Date{\textgreater}} element of the title page. \item[{Persons}] This is used to generate \texttt{{\textless}Author{\textgreater}} elements in the generated title page. \item[{PackageDoc}] This is a record (or a list of records) which is used to tell the \textsf{GAP} help system about the package manual. Currently \textsf{AutoDoc} extracts the value of the \texttt{PackageDoc.BookName} component and then passes that on to \textsf{GAPDoc} when creating the HTML, PDF and text versions of the manual. \item[{AutoDoc}] This is a record which can be used to control the scaffolding performed by \textsf{AutoDoc}, specifically to provide extra information for the title page. For example, you can set \texttt{AutoDoc.TitlePage.Copyright} to a string which will then be inserted on the generated title page. Using this method you can customize the following title page elements: \texttt{TitleComment}, \texttt{Abstract}, \texttt{Copyright}, \texttt{Acknowledgements} and \texttt{Colophon}. Note that \texttt{AutoDoc.TitlePage} behaves exactly the same as the \texttt{scaffold.TitlePage} parameter of the \texttt{AutoDoc} (\ref{AutoDoc}) function. \end{description} } } \section{\textcolor{Chapter }{AutoDoc worksheets}}\label{Tut:AutoDocWorksheet} \logpage{[ 1, 5, 0 ]} \hyperdef{L}{X80ED3C2A78146AD1}{} { \textsf{AutoDoc} worksheets can be used to create HTML and PDF documents using AutoDoc syntax and possibly including \textsf{GAP} examples and implementations without having them associated to a package. A file for a worksheet could look like this: \begin{Verbatim}[commandchars=|DF,fontsize=\small,frame=single,label=] #! @Title My first worksheet #! @Author Charlie Brown #! @Chapter Some groups #! @BeginExample S3 := SymmetricGroup( 3 );; S4 := SymmetricGroup( 4 );; #! @EndExample \end{Verbatim} Now, one can create a PDF and HTML document, like a package documentation out of it. Suppose the document above is saved as \texttt{worksheet.g}. Then, when \textsf{GAP} is started in the directory of this file, the command \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] AutoDocWorksheet( "worksheet.g" ); \end{Verbatim} will create a subdirectory called \texttt{doc} of the current directory in which it will create the documentation. There are several options to configure the output of the worksheet command, which are identical to the options of the \texttt{AutoDoc} (\ref{AutoDoc}) command. It is even possible to test the examples in the worksheet using the \texttt{extract{\textunderscore}examples} option of the \texttt{AutoDoc} (\ref{AutoDoc}) command. Since the worksheets do not have a \texttt{PackageInfo.g} to extract information, all possible tags that \textsf{GAPDoc} supports for the title page can be set into the document. A fully typed title page can look like this: \begin{Verbatim}[commandchars=|FH,fontsize=\small,frame=single,label=] #! @Title My first worksheet #! @Subtitle Some small examples #! @Author Charlie Brown #! @Version 0.1 #! @TitleComment Some worksheet #! @Date 01/01/2016 #! @Address TU Kaiserslautern #! @Abstract #! A worksheet showing some small examples about groups. #! @Copyright 2016 Charlie Brown #! @Acknowledgements Woodstock #! @Colophon Some colophon #! @Chapter Some groups #! @BeginExample S3 := SymmetricGroup( 3 );; S4 := SymmetricGroup( 4 );; #! @EndExample \end{Verbatim} } } \chapter{\textcolor{Chapter }{\textsf{AutoDoc} documentation comments}}\label{Comments} \logpage{[ 2, 0, 0 ]} \hyperdef{L}{X87668C487B1A2094}{} { You can document declarations of global functions and variables, operations, attributes etc. by inserting \emph{\textsf{AutoDoc}} comments into your sources before these declaration. An \textsf{AutoDoc} comment always starts with \texttt{\#!}. This is also the smallest possible \textsf{AutoDoc} command. If you want your declaration documented, just write \texttt{\#!} at the line before the documentation. For example: \begin{Verbatim}[commandchars=@|B,fontsize=\small,frame=single,label=] #! DeclareOperation( "AnOperation", [ IsList ] ); \end{Verbatim} This will produce a manual entry for the operation \texttt{AnOperation}. Inside of \textsf{AutoDoc} comments, \emph{\textsf{AutoDoc} commands} starting with \texttt{@} can be used to control the output \textsf{AutoDoc} produces. \section{\textcolor{Chapter }{Documenting declarations}}\logpage{[ 2, 1, 0 ]} \hyperdef{L}{X871482CE838C68F6}{} { In the bare form above, the manual entry for \texttt{AnOperation} will not contain much more than the name of the operation. In order to change this, there are several commands you can put into the \textsf{AutoDoc} comment before the declaration. Currently, the following commands are provided: \subsection{\textcolor{Chapter }{\texttt{@Description \mbox{\texttt{\mdseries\slshape descr}}}}}\label{@Description} \logpage{[ 2, 1, 1 ]} \hyperdef{L}{X7F1D85188262A827}{} { \index{"@Description@\texttt{"@Description \mbox{\texttt{\mdseries\slshape descr}}}} Adds the text in the following lines of the \textsf{AutoDoc} to the description of the declaration in the manual. Lines are until the next \textsf{AutoDoc} command or until the declaration is reached. } \subsection{\textcolor{Chapter }{\texttt{@Returns \mbox{\texttt{\mdseries\slshape ret{\textunderscore}val}}}}}\label{@Returns} \logpage{[ 2, 1, 2 ]} \hyperdef{L}{X7DCAB2F87E8FAE90}{} { \index{"@Returns@\texttt{"@Returns \mbox{\texttt{\mdseries\slshape ret{\textunderscore}val}}}} The string \mbox{\texttt{\mdseries\slshape ret{\textunderscore}val}} is added to the documentation, with the text ``Returns: '' put in front of it. This should usually give a brief hint about the type or meaning of the value returned by the documented function. } \subsection{\textcolor{Chapter }{\texttt{@Arguments \mbox{\texttt{\mdseries\slshape args}}}}}\label{@Arguments} \logpage{[ 2, 1, 3 ]} \hyperdef{L}{X81DAA454857F7971}{} { \index{"@Arguments@\texttt{"@Arguments \mbox{\texttt{\mdseries\slshape args}}}} The string \mbox{\texttt{\mdseries\slshape args}} contains a description of the arguments the function expects, including optional parts, which are denoted by square brackets. The argument names can be separated by whitespace, commas or square brackets for the optional arguments, like ``grp[, elm]'' or ``xx[y[z] ]''. If \textsf{GAP} options are used, this can be followed by a colon : and one or more assignments, like ``n[, r]: tries := 100''. } \subsection{\textcolor{Chapter }{\texttt{@Group \mbox{\texttt{\mdseries\slshape grpname}}}}}\label{@Group} \logpage{[ 2, 1, 4 ]} \hyperdef{L}{X8677FE8F80C00B14}{} { \index{"@Group@\texttt{"@Group \mbox{\texttt{\mdseries\slshape grpname}}}} Adds the following method to a group with the given name. See section \ref{Groups} for more information about groups. } \subsection{\textcolor{Chapter }{\texttt{@Label \mbox{\texttt{\mdseries\slshape label}}}}}\label{@Label} \logpage{[ 2, 1, 5 ]} \hyperdef{L}{X7B0E20A27D64DF6F}{} { \index{"@Label@\texttt{"@Label \mbox{\texttt{\mdseries\slshape label}}}} Adds label to the function as label. If this is not specified, then for declarations that involve a list of input filters (as is the case for \texttt{DeclareOperation}, \texttt{DeclareAttribute}, etc.), a default label is generated from this filter list. } \begin{Verbatim}[commandchars=|BC,fontsize=\small,frame=single,label=] #! @Label testlabel DeclareProperty( "AProperty", IsObject ); \end{Verbatim} leads to this: \subsection{\textcolor{Chapter }{AProperty (testlabel)}} \logpage{[ 2, 1, 6 ]}\nobreak \hyperdef{L}{X83B63B847B5199CF}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AProperty({\mdseries\slshape arg})\index{AProperty@\texttt{AProperty}!testlabel} \label{AProperty:testlabel} }\hfill{\scriptsize (property)}}\\ \textbf{\indent Returns:\ } \texttt{true} or \texttt{false} } while \begin{Verbatim}[commandchars=@|B,fontsize=\small,frame=single,label=] #! DeclareProperty( "AProperty", IsObject ); \end{Verbatim} leads to this: \subsection{\textcolor{Chapter }{AProperty (for IsObject)}} \logpage{[ 2, 1, 7 ]}\nobreak \hyperdef{L}{X78A9022A7D5CB20E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AProperty({\mdseries\slshape arg})\index{AProperty@\texttt{AProperty}!for IsObject} \label{AProperty:for IsObject} }\hfill{\scriptsize (property)}}\\ \textbf{\indent Returns:\ } \texttt{true} or \texttt{false} } \subsection{\textcolor{Chapter }{\texttt{@ChapterInfo \mbox{\texttt{\mdseries\slshape chapter}}, \mbox{\texttt{\mdseries\slshape section}}}}}\label{@ChapterInfo} \logpage{[ 2, 1, 8 ]} \hyperdef{L}{X78938EE37A532FFA}{} { \index{"@ChapterInfo@\texttt{"@ChapterInfo}} Adds the entry to the given chapter and section. Here, \mbox{\texttt{\mdseries\slshape chapter}} and \mbox{\texttt{\mdseries\slshape section}} are the respective titles. } As an example, a full \textsf{AutoDoc} comment with all options could look like this: \begin{Verbatim}[commandchars=|EF,fontsize=\small,frame=single,label=] #! @Description #! Computes the list of lists of degrees of ordinary characters #! associated to the $p$-blocks of the group $G$ #! with $p$-modular character table modtbl #! and underlying ordinary character table `ordtbl`. #! @Returns a list #! @Arguments modtbl #! @Group CharacterDegreesOfBlocks #! @Label chardegblocks #! @ChapterInfo Blocks, Attributes DeclareAttribute( "CharacterDegreesOfBlocks", IsBrauerTable ); \end{Verbatim} } \section{\textcolor{Chapter }{Other documentation comments}}\logpage{[ 2, 2, 0 ]} \hyperdef{L}{X8152FEF9844B1ACD}{} { There are also some commands which can be used in \textsf{AutoDoc} comments that are not associated to any declaration. This is useful for additional text in your documentation, examples, mathematical chapters, etc.. \subsection{\textcolor{Chapter }{\texttt{@Chapter \mbox{\texttt{\mdseries\slshape name}}}}}\label{@Chapter} \logpage{[ 2, 2, 1 ]} \hyperdef{L}{X823E613385D09F6F}{} { \index{"@Chapter@\texttt{"@Chapter}} \index{"@ChapterLabel@\texttt{"@ChapterLabel}} \index{"@ChapterTitle@\texttt{"@ChapterTitle}} Sets the active chapter, all subsequent functions which do not have an explicit chapter declared in their \textsf{AutoDoc} comment via \texttt{@ChapterInfo} will be added to this chapter. Also all text comments, i.e. lines that begin with \#! without a command, and which do not follow after \texttt{@Description}, will be added to the chapter as regular text. Additionally, the chapters label will be set to \texttt{Chapter{\textunderscore}}\mbox{\texttt{\mdseries\slshape name}}. Example: \begin{Verbatim}[commandchars=|AB,fontsize=\small,frame=single,label=] #! @Chapter My chapter #! This is my chapter. #! I document my stuff in it. \end{Verbatim} The \texttt{@ChapterLabel} \mbox{\texttt{\mdseries\slshape label}} command can be used to set the label of the chapter to \texttt{Chapter{\textunderscore}}\mbox{\texttt{\mdseries\slshape label}} instead of \texttt{Chapter{\textunderscore}}\mbox{\texttt{\mdseries\slshape name}}. Additionally, the chapter will be stored as \texttt{{\textunderscore}Chapter{\textunderscore}}\mbox{\texttt{\mdseries\slshape label}}\texttt{.xml}. The \texttt{@ChapterTitle} \mbox{\texttt{\mdseries\slshape title}} command can be used to set a heading for the chapter that is different from \mbox{\texttt{\mdseries\slshape name}}. Note that the title does not affect the label. If you use all three commands, i.e., \begin{Verbatim}[commandchars=|AB,fontsize=\small,frame=single,label=] #! @Chapter name #! @ChapterLabel label #! @ChapterTitle title \end{Verbatim} \texttt{title} is used for the headline, \texttt{label} for cross\texttt{\symbol{45}}referencing, and \texttt{name} for setting the same chapter as active chapter again. } \subsection{\textcolor{Chapter }{\texttt{@Section \mbox{\texttt{\mdseries\slshape name}}}}}\label{@Section} \logpage{[ 2, 2, 2 ]} \hyperdef{L}{X78AA98BA7E0635D0}{} { \index{"@Section@\texttt{"@Section}} \index{"@SectionLabel@\texttt{"@SectionLabel}} \index{"@SectionTitle@\texttt{"@SectionTitle}} Sets an active section like \texttt{@Chapter} sets an active chapter. The section automatically ends with the next \texttt{@Section} or \texttt{@Chapter} command. \begin{Verbatim}[commandchars=|AB,fontsize=\small,frame=single,label=] #! @Section My first manual section #! In this section I am going to document my first method. \end{Verbatim} The \texttt{@SectionLabel} \mbox{\texttt{\mdseries\slshape label}} command can be used to set the label of the section to \texttt{Section{\textunderscore}}\mbox{\texttt{\mdseries\slshape label}} instead of \texttt{Chapter{\textunderscore}chaptername{\textunderscore}Section{\textunderscore}}\mbox{\texttt{\mdseries\slshape name}}. The \texttt{@SectionTitle} \mbox{\texttt{\mdseries\slshape title}} command can be used to set a heading for the section that is different from \mbox{\texttt{\mdseries\slshape name}}. } \subsection{\textcolor{Chapter }{\texttt{@Subsection \mbox{\texttt{\mdseries\slshape name}}}}}\label{@Subsection} \logpage{[ 2, 2, 3 ]} \hyperdef{L}{X7FD77434802A3580}{} { \index{"@Subsection@\texttt{"@Subsection}} \index{"@SubsectionLabel@\texttt{"@SubsectionLabel}} \index{"@SubsectionTitle@\texttt{"@SubsectionTitle}} Sets an active subsection like \texttt{@Section} sets an active section. The subsection automatically ends with the next \texttt{@Subsection}, \texttt{@Section} or \texttt{@Chapter} command. It also ends with the next documented function. Indeed, internally each function ``manpage'' is treated like a subsection. \begin{Verbatim}[commandchars=|AB,fontsize=\small,frame=single,label=] #! @Subsection My first manual subsection #! In this subsection I am going to document my first example. \end{Verbatim} The \texttt{@SubsectionLabel} \mbox{\texttt{\mdseries\slshape label}} command can be used to set the label of the subsection to \texttt{Subsection{\textunderscore}}\mbox{\texttt{\mdseries\slshape label}} instead of \texttt{Chapter{\textunderscore}chaptername{\textunderscore}Section{\textunderscore}sectionname{\textunderscore}Subsection{\textunderscore}}\mbox{\texttt{\mdseries\slshape name}}. The \texttt{@SubsectionTitle} \mbox{\texttt{\mdseries\slshape title}} command can be used to set a heading for the subsection that is different from \mbox{\texttt{\mdseries\slshape name}}. } \subsection{\textcolor{Chapter }{\texttt{@BeginGroup \mbox{\texttt{\mdseries\slshape [grpname]}}}}}\label{@BeginGroup} \logpage{[ 2, 2, 4 ]} \hyperdef{L}{X7D3060C17EDBCED1}{} { \index{"@BeginGroup@\texttt{"@BeginGroup}} Starts a group. All following documented declarations without an explicit \texttt{@Group} command are grouped together in the same group with the given name. If no name is given, then a new nameless group is generated. The effect of this command is ended when an \texttt{@EndGroup} command is reached. See section \ref{Groups} for more information about groups. } \subsection{\textcolor{Chapter }{\texttt{@EndGroup}}}\label{@EndGroup} \logpage{[ 2, 2, 5 ]} \hyperdef{L}{X7C17EB007FD42C87}{} { \index{"@EndGroup@\texttt{"@EndGroup}} Ends the current group. \begin{Verbatim}[commandchars=|CF,fontsize=\small,frame=single,label=] #! @BeginGroup MyGroup #! DeclareAttribute( "GroupedAttribute", IsList ); DeclareOperation( "NonGroupedOperation", [ IsObject ] ); #! DeclareOperation( "GroupedOperation", [ IsList, IsRubbish ] ); #! @EndGroup \end{Verbatim} } \subsection{\textcolor{Chapter }{@GroupTitle \mbox{\texttt{\mdseries\slshape title}}}}\label{@GroupTitle} \logpage{[ 2, 2, 6 ]} \hyperdef{L}{X82FB96F37FAE8167}{} { \index{"@GroupTitle@\texttt{"@GroupTitle}} Sets the subsection heading for the current group to \mbox{\texttt{\mdseries\slshape title}}. In the absence of any \texttt{@GroupTitle} command, the heading will be the name of the first entry in the group. See \ref{Groups} for more information. } \subsection{\textcolor{Chapter }{\texttt{@Level \mbox{\texttt{\mdseries\slshape lvl}}}}}\label{@Level} \logpage{[ 2, 2, 7 ]} \hyperdef{L}{X7BF81EAF80D1A4B5}{} { \index{"@Level@\texttt{"@Level}} Sets the current level of the documentation. All items created after this, chapters, sections, and items, are given the level \mbox{\texttt{\mdseries\slshape lvl}}, until the \texttt{@ResetLevel} command resets the level to 0 or another level is set. See section \ref{Level} for more information about levels. } \subsection{\textcolor{Chapter }{\texttt{@ResetLevel}}}\label{@ResetLevel} \logpage{[ 2, 2, 8 ]} \hyperdef{L}{X7C6723D57F424215}{} { \index{"@ResetLevel@\texttt{"@ResetLevel}} Resets the current level to 0. } \subsection{\textcolor{Chapter }{\texttt{@BeginExample} and \texttt{@EndExample}}}\label{@BeginExample} \logpage{[ 2, 2, 9 ]} \hyperdef{L}{X83D6DA3B83D3436C}{} { \index{"@BeginExample@\texttt{"@BeginExample}} \index{"@EndExample@\texttt{"@EndExample}} \texttt{@BeginExample} marks the start of an example to be put into the manual. It differs from \textsf{GAPDoc}'s \texttt{{\textless}Example{\textgreater}} (see (\textbf{GAPDoc: Log})), in that it expects actual code (not in a comment) interspersed with comments, to allow for examples files that can be both executed by \textsf{GAP}, and parsed by \textsf{AutoDoc}. To achieve this, \textsf{GAP} commands are not preceded by a comment, while output has to be preceded by an \textsf{AutoDoc} comment. The \texttt{gap{\textgreater}} prompt for the display in the manual is added by \textsf{AutoDoc}. \texttt{@EndExample} ends the example block. To illustrate this command, consider this input: \begin{Verbatim}[commandchars=|AC,fontsize=\small,frame=single,label=] #! @BeginExample S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) Order(S5); #! 120 #! @EndExample \end{Verbatim} This results in the following output: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@S5 := SymmetricGroup(5);| Sym( [ 1 .. 5 ] ) !gapprompt@gap>| !gapinput@Order(S5);| 120 \end{Verbatim} The \textsf{AutoDoc} command \texttt{@Example} is an alias of \texttt{@BeginExample}. } \subsection{\textcolor{Chapter }{\texttt{@BeginExampleSession} and \texttt{@EndExampleSession}}}\label{@BeginExampleSession} \logpage{[ 2, 2, 10 ]} \hyperdef{L}{X861E2E778510CAF7}{} { \index{"@BeginExampleSession@\texttt{"@BeginExampleSession}} \index{"@EndExampleSession@\texttt{"@EndExampleSession}} \texttt{@BeginExampleSession} marks the start of an example to be put into the manual, while \texttt{@EndExampleSession} ends the example block. It is the direct analog of \textsf{GAPDoc}'s \texttt{{\textless}Example{\textgreater}} (see (\textbf{GAPDoc: Log})). To illustrate this command, consider this input: \begin{Verbatim}[commandchars=|AC,fontsize=\small,frame=single,label=] #! @BeginExampleSession #! gap> S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) #! gap> Order(S5); #! 120 #! @EndExampleSession \end{Verbatim} This results in the following output: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=Example] !gapprompt@gap>| !gapinput@S5 := SymmetricGroup(5);| Sym( [ 1 .. 5 ] ) !gapprompt@gap>| !gapinput@Order(S5);| 120 \end{Verbatim} It inserts an example into the manual just as \texttt{@Example} would do, but all lines are commented and therefore not executed when the file is read. All lines that should be part of the example displayed in the manual have to start with an \textsf{AutoDoc} comment (\texttt{\#!}). The comment will be removed, and, if the following character is a space, this space will also be removed. There is never more than one space removed. To ensure examples are correctly colored in the manual, there should be exactly one space between \texttt{\#!} and the \texttt{gap{\textgreater}} prompt. The \textsf{AutoDoc} command \texttt{@ExampleSession} is an alias of \texttt{@BeginExampleSession}. } \subsection{\textcolor{Chapter }{\texttt{@BeginLog} and \texttt{@EndLog}}}\label{@BeginLog} \logpage{[ 2, 2, 11 ]} \hyperdef{L}{X81A2D44D834C0A17}{} { \index{"@BeginLog@\texttt{"@BeginLog}} \index{"@EndLog@\texttt{"@EndLog}} Works just like the \texttt{@BeginExample} command, but the example will not be tested. See the \textsf{GAPDoc} manual for more information. The \textsf{AutoDoc} command \texttt{@Log} is an alias of \texttt{@BeginLog}. } \subsection{\textcolor{Chapter }{\texttt{@BeginLogSession} and \texttt{@EndLogSession}}}\label{@BeginLogSession} \logpage{[ 2, 2, 12 ]} \hyperdef{L}{X7BADE876794FF309}{} { \index{"@BeginLogSession@\texttt{"@BeginLogSession}} \index{"@EndLogSession@\texttt{"@EndLogSession}} Works just like the \texttt{@BeginExampleSession} command, but the example will not be tested if manual examples are run. It is the direct analog of \textsf{GAPDoc}'s \texttt{{\textless}Log{\textgreater}} (see (\textbf{GAPDoc: Log})). The \textsf{AutoDoc} command \texttt{@LogSession} is an alias of \texttt{@BeginLogSession}. } \subsection{\textcolor{Chapter }{\texttt{@DoNotReadRestOfFile}}}\label{@DoNotReadRestOfFile} \logpage{[ 2, 2, 13 ]} \hyperdef{L}{X78DC644E8519280C}{} { \index{"@DoNotReadRestOfFile@\texttt{"@DoNotReadRestOfFile}} Prevents the rest of the file from being read by the parser. Useful for unfinished or temporary files. \begin{Verbatim}[commandchars=|AB,fontsize=\small,frame=single,label=] #! This will appear in the manual #! @DoNotReadRestOfFile #! This will not appear in the manual. \end{Verbatim} } \subsection{\textcolor{Chapter }{\texttt{@BeginChunk \mbox{\texttt{\mdseries\slshape name}}}, \texttt{@EndChunk}, and \texttt{@InsertChunk \mbox{\texttt{\mdseries\slshape name}}}}}\label{@BeginChunk} \logpage{[ 2, 2, 14 ]} \hyperdef{L}{X83C01F9B7FA1C973}{} { \index{"@BeginChunk@\texttt{"@BeginChunk \mbox{\texttt{\mdseries\slshape name}}}} \index{"@EndChunk@\texttt{"@EndChunk}} \index{"@EndChunk@\texttt{"@InsertChunk \mbox{\texttt{\mdseries\slshape name}}}} Text inside a \texttt{@BeginChunk} / \texttt{@EndChunk} part will not be inserted into the final documentation directly. Instead, the text is stored in an internal buffer. That chunk of text can then later on be inserted in any other place by using the \texttt{@InsertChunk \mbox{\texttt{\mdseries\slshape name}}} command. If you do not provide an \texttt{@EndChunk}, the chunk ends at the end of the file. \begin{Verbatim}[commandchars=|AD,fontsize=\small,frame=single,label=] #! @BeginChunk MyChunk #! Hello, world. #! @EndChunk #! @InsertChunk MyChunk ## The text "Hello, world." is inserted right before this. \end{Verbatim} You can use this to define an example like this in one file: \begin{Verbatim}[commandchars=|AD,fontsize=\small,frame=single,label=] #! @BeginChunk Example_Symmetric_Group #! @BeginExample S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) Order(S5); #! 120 #! @EndExample #! @EndChunk \end{Verbatim} And then later, insert the example in a different file, like this: \begin{Verbatim}[commandchars=|AB,fontsize=\small,frame=single,label=] #! @InsertChunk Example_Symmetric_Group \end{Verbatim} } \subsection{\textcolor{Chapter }{\texttt{@BeginCode \mbox{\texttt{\mdseries\slshape name}}}, @EndCode, and \texttt{@InsertCode \mbox{\texttt{\mdseries\slshape name}}}}}\label{@BeginCode} \logpage{[ 2, 2, 15 ]} \hyperdef{L}{X7D3671AF86B995B9}{} { \index{"@BeginCode@\texttt{"@BeginCode \mbox{\texttt{\mdseries\slshape name}}}} \index{"@EndCode@\texttt{"@EndCode}} \index{"@InsertCode@\texttt{"@InsertCode \mbox{\texttt{\mdseries\slshape name}}}} Inserts the text between \texttt{@BeginCode} and \texttt{@EndCode} verbatim at the point where \texttt{@InsertCode} is called. This is useful to insert code excerpts directly into the manual. \begin{Verbatim}[commandchars=|AD,fontsize=\small,frame=single,label=] #! @BeginCode Increment i := i + 1; #! @EndCode #! @InsertCode Increment ## Code is inserted here. \end{Verbatim} } \subsection{\textcolor{Chapter }{\texttt{@LatexOnly \mbox{\texttt{\mdseries\slshape text}}}, \texttt{@BeginLatexOnly}, and \texttt{@EndLatexOnly}}}\label{@LatexOnly} \logpage{[ 2, 2, 16 ]} \hyperdef{L}{X8033B34F80A12A10}{} { \index{"@LatexOnly@\texttt{"@LatexOnly \mbox{\texttt{\mdseries\slshape text}}}} \index{"@BeginLatexOnly@\texttt{"@BeginLatexOnly}} \index{"@EndLatexOnly@\texttt{"@EndLatexOnly}} Code inserted between \texttt{@BeginLatexOnly} and \texttt{@EndLatexOnly} or after \texttt{@LatexOnly} is only inserted in the PDF version of the manual or worksheet. It can hold arbitrary {\LaTeX}\texttt{\symbol{45}}commands. \begin{Verbatim}[commandchars=|AC,fontsize=\small,frame=single,label=] #! @BeginLatexOnly #! \include{picture.tex} #! @EndLatexOnly #! @LatexOnly \include{picture.tex} \end{Verbatim} } \subsection{\textcolor{Chapter }{\texttt{@NotLatex \mbox{\texttt{\mdseries\slshape text}}}, \texttt{@BeginNotLatex}, and \texttt{@EndNotLatex}}}\label{@NotLatex} \logpage{[ 2, 2, 17 ]} \hyperdef{L}{X7EF303147F1BCC22}{} { \index{"@NotLatex@\texttt{"@NotLatex \mbox{\texttt{\mdseries\slshape text}}}} \index{"@BeginNotLatex@\texttt{"@BeginNotLatex}} \index{"@EndNotLatex@\texttt{"@EndNotLatex}} Code inserted between \texttt{@BeginNotLatex} and \texttt{@EndNotLatex} or after \texttt{@NotLatex} is inserted in the HTML and text versions of the manual or worksheet, but not in the PDF version. \begin{Verbatim}[commandchars=|AC,fontsize=\small,frame=single,label=] #! @BeginNotLatex #! For further information see the PDF version of this manual. #! @EndNotLatex #! @NotLatex For further information see the PDF version of this manual. \end{Verbatim} } } \section{\textcolor{Chapter }{Title page commands}}\label{TitlepageCommands} \logpage{[ 2, 3, 0 ]} \hyperdef{L}{X841E3AD584F5385C}{} { The following commands can be used to add the corresponding parts to the title page of the document which generated by \textsf{AutoDoc} if scaffolding is enabled. \begin{itemize} \item \texttt{@Title} \item \texttt{@Subtitle} \item \texttt{@Version} \item \texttt{@TitleComment} \item \texttt{@Author} \item \texttt{@Date} \item \texttt{@Address} \item \texttt{@Abstract} \item \texttt{@Copyright} \item \texttt{@Acknowledgements} \item \texttt{@Colophon} \end{itemize} Those add the following lines at the corresponding point of the title page. Please note that many of those things can be (better) extracted from the \texttt{PackageInfo.g}. In case you set some of those, the extracted or in scaffold defined items will be overwritten. While this is not very useful for documenting packages, they are necessary for worksheets created with \texttt{AutoDocWorksheet} (\ref{AutoDocWorksheet}), since worksheets do not have a \texttt{PackageInfo.g} file from which this information could be extracted. } \section{\textcolor{Chapter }{Plain text files}}\label{PlainText} \logpage{[ 2, 4, 0 ]} \hyperdef{L}{X828AE38F80CB02E7}{} { Files that have the suffix \texttt{.autodoc} and are listed in the \texttt{autodoc.files} option of \texttt{AutoDoc} (\ref{AutoDoc}), resp. are contained in one of the directories listed in \texttt{autodoc.scan{\textunderscore}dirs}, are treated as \textsf{AutoDoc} plain text files. These work exactly like \textsf{AutoDoc} comments, except that lines do not need to (and in fact, should not) start with \texttt{\#!}. } \section{\textcolor{Chapter }{Grouping}}\label{Groups} \logpage{[ 2, 5, 0 ]} \hyperdef{L}{X7D7A38F87BC40C48}{} { In \textsf{GAPDoc}, it is possible to make groups of manual items, i.e., when documenting a function, operation, etc., it is possible to group them into suitable chunks. This can be particularly useful if there are several definitions of an operation with several different argument types, all doing more or less the same to the arguments. Then their manual items can be grouped, sharing the same description and return type information. You can give a heading to the group in the manual with the \texttt{@GroupTitle} command; if that is not supplied, then the heading of the first manual item in the group will be used as the heading. Note that group names are globally unique throughout the whole manual. That is, groups with the same name are in fact merged into a single group, even if they were declared in different source files. Thus you can have multiple \texttt{@BeginGroup} / \texttt{@EndGroup} pairs using the same group name, in different places, and these all will refer to the same group. Moreover, this means that you can add items to a group via the \texttt{@Group} command in the \textsf{AutoDoc} comment of an arbitrary declaration, at any time. The following code \begin{Verbatim}[commandchars=|CH,fontsize=\small,frame=single,label=] #! @BeginGroup Group1 #! @GroupTitle A family of operations #! @Description #! First sentence. DeclareOperation( "FirstOperation", [ IsInt ] ); #! @Description #! Second sentence. DeclareOperation( "SecondOperation", [ IsInt, IsGroup ] ); #! @EndGroup ## .. Stuff .. #! @Description #! Third sentence. #! @Group Group1 KeyDependentOperation( "ThirdOperation", IsGroup, IsInt, "prime ); \end{Verbatim} produces the following: \subsection{\textcolor{Chapter }{A family of operations}}\label{Group1} \logpage{[ 2, 5, 1 ]} \hyperdef{L}{X79BF060F8436C586}{} { \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{FirstOperation({\mdseries\slshape arg})\index{FirstOperation@\texttt{FirstOperation}!for IsInt} \label{FirstOperation:for IsInt} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{SecondOperation({\mdseries\slshape arg1, arg2})\index{SecondOperation@\texttt{SecondOperation}!for IsInt, IsGroup} \label{SecondOperation:for IsInt, IsGroup} }\hfill{\scriptsize (operation)}}\\ \noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{ThirdOperation({\mdseries\slshape arg1, arg2})\index{ThirdOperation@\texttt{ThirdOperation}!for IsGroup, IsInt} \label{ThirdOperation:for IsGroup, IsInt} }\hfill{\scriptsize (operation)}}\\ First sentence. Second sentence. Third sentence. } } \section{\textcolor{Chapter }{Level}}\label{Level} \logpage{[ 2, 6, 0 ]} \hyperdef{L}{X8209AFDE8209AFDE}{} { Levels can be set to not write certain parts in the manual by default. Every entry has by default the level 0. The command \texttt{@Level} can be used to set the level of the following part to a higher level, for example 1, and prevent it from being printed to the manual by default. However, if one sets the level to a higher value in the autodoc option of \textsf{AutoDoc}, the parts will be included in the manual at the specific place. \begin{Verbatim}[commandchars=|AB,fontsize=\small,frame=single,label=] #! This text will be printed to the manual. #! @Level 1 #! This text will be printed to the manual if created with level 1 or higher. #! @Level 2 #! This text will be printed to the manual if created with level 2 or higher. #! @ResetLevel #! This text will be printed to the manual. \end{Verbatim} } \section{\textcolor{Chapter }{Markdown\texttt{\symbol{45}}like formatting of text in \textsf{AutoDoc}}}\label{MarkdownExtension} \logpage{[ 2, 7, 0 ]} \hyperdef{L}{X79558A2F7FE187B4}{} { \textsf{AutoDoc} has some convenient ways to insert special format into text, like math formulas and lists. The syntax for them are inspired by Markdown and {\LaTeX}, but do not follow them strictly. Neither are all features of the Markdown language supported. The following subsections describe what is possible. \subsection{\textcolor{Chapter }{Lists}}\label{MarkdownExtensionList} \logpage{[ 2, 7, 1 ]} \hyperdef{L}{X7B256AE5780F140A}{} { One can create lists of items by beginning a new line with *, +, \texttt{\symbol{45}}, followed by one space. The first item starts the list. When items are longer than one line, the following lines have to be indented by at least two spaces. The list ends when a line which does not start a new item is not indented by two spaces. Of course lists can be nested. Here is an example: \begin{Verbatim}[commandchars=@|A,fontsize=\small,frame=single,label=] #! The list starts in the next line #! * item 1 #! * item 2 #! which is a bit longer #! * and also contains a nested list #! * with two items #! * item 3 of the outer list #! This does not belong to the list anymore. \end{Verbatim} This is the output:\\ The list starts in the next line \begin{itemize} \item item 1 \item item 2 which is a bit longer \begin{itemize} \item and also contains a nested list \item with two items \end{itemize} \item item 3 of the outer list \end{itemize} This does not belong to the list anymore.\\ The *, \texttt{\symbol{45}}, and + are fully interchangeable and can even be used mixed, but this is not recommended. } \subsection{\textcolor{Chapter }{Math modes}}\label{MarkdownExtensionMath} \logpage{[ 2, 7, 2 ]} \hyperdef{L}{X871412737A0E12E2}{} { One can start an inline formula with a \$, and also end it with \$, just like in {\LaTeX}. This will translate into \textsf{GAPDoc}s inline math environment. For display mode one can use \$\$, also like {\LaTeX}. \begin{Verbatim}[commandchars=@|A,fontsize=\small,frame=single,label=] #! This is an inline formula: $1+1 = 2$. #! This is a display formula: #! $$ \sum_{i=1}^n i. $$ \end{Verbatim} produces the following output:\\ This is an inline formula: $1+1 = 2$. This is a display formula: \[ \sum_{i=1}^n i. \] } \subsection{\textcolor{Chapter }{Emphasize}}\label{MarkdownExtensionEmph} \logpage{[ 2, 7, 3 ]} \hyperdef{L}{X7ED0330479146EFC}{} { One can emphasize text by using two asterisks (**) or two underscores ({\textunderscore}{\textunderscore}) at the beginning and the end of the text which should be emphasized. Example: \begin{Verbatim}[commandchars=@|A,fontsize=\small,frame=single,label=] #! **This** is very important. #! This is __also important__. #! **Naturally, more than one line #! can be important.** \end{Verbatim} This produces the following output:\\ \emph{This} is very important. This is \emph{also important}. \emph{Naturally, more than one line can be important.} } \subsection{\textcolor{Chapter }{Inline code}}\label{MarkdownExtensionInlineCode} \logpage{[ 2, 7, 4 ]} \hyperdef{L}{X838CCDEB7E0ECEE2}{} { One can mark inline code snippets by using backticks (`) at the beginning and the end of the text which should be marked as code. Example: \begin{Verbatim}[commandchars=@|A,fontsize=\small,frame=single,label=] #! Call function `foobar()` at the start. \end{Verbatim} This produces the following output:\\ Call function \texttt{foobar()} at the start. } } \section{\textcolor{Chapter }{Deprecated commands}}\label{Deprecated} \logpage{[ 2, 8, 0 ]} \hyperdef{L}{X78CA9E5C7F494C19}{} { The following commands used to be supported, but are not anymore. \begin{description} \item[{\texttt{@EndSection}}] You can simply remove any use of this, \textsf{AutoDoc} ends sections automatically at the start of any new section or chapter. \item[{\texttt{@EndSubsection}}] You can simply remove any use of this, \textsf{AutoDoc} ends subsections automatically at the start of any new subsection, section or chapter. \item[{\texttt{@BeginAutoDoc} and \texttt{@EndAutoDoc}}] It suffices to prepend each declaration that is meant to be appear in the manual with a minimal \textsf{AutoDoc} comment \texttt{\#!}. \item[{\texttt{@BeginSystem \mbox{\texttt{\mdseries\slshape name}}}, \texttt{@EndSystem}, and \texttt{@InsertSystem \mbox{\texttt{\mdseries\slshape name}}}}] Please use the chunk commands from subsection \ref{@BeginChunk} instead. \item[{\texttt{@AutoDocPlainText} and \texttt{@EndAutoDocPlainText}}] Use \texttt{.autodoc} files or \textsf{AutoDoc} comments instead. \end{description} } } \chapter{\textcolor{Chapter }{AutoDoc worksheets}}\label{Chapter_AutoDoc_worksheets} \logpage{[ 3, 0, 0 ]} \hyperdef{L}{X80ED3C2A78146AD1}{} { \section{\textcolor{Chapter }{Worksheets}}\label{Chapter_AutoDoc_worksheets_Section_Worksheets} \logpage{[ 3, 1, 0 ]} \hyperdef{L}{X801D4A2F8292704C}{} { \subsection{\textcolor{Chapter }{AutoDocWorksheet}} \logpage{[ 3, 1, 1 ]}\nobreak \hyperdef{L}{X809FE4137C08B28D}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AutoDocWorksheet({\mdseries\slshape list{\textunderscore}of{\textunderscore}filenames: options})\index{AutoDocWorksheet@\texttt{AutoDocWorksheet}} \label{AutoDocWorksheet} }\hfill{\scriptsize (function)}}\\ The intention of these function is to create stand\texttt{\symbol{45}}alone pdf and html files using AutoDoc without having them associated to a package. It uses the same optional records as the \textsf{AutoDoc} command itself, but instead of a package name there should be a filename or a list of filenames containing AutoDoc text from which the documents are created. Please see the \textsf{AutoDoc} command for more information about this and have a look at \ref{Tut:AutoDocWorksheet} for a simple worksheet example. } } } \chapter{\textcolor{Chapter }{AutoDoc}}\label{Chapter_AutoDoc} \logpage{[ 4, 0, 0 ]} \hyperdef{L}{X7CBD8AAF7DCEF352}{} { \section{\textcolor{Chapter }{The AutoDoc() function}}\label{Chapter_AutoDoc_Section_The_AutoDoc_function} \logpage{[ 4, 1, 0 ]} \hyperdef{L}{X863584DB8497D8BA}{} { \subsection{\textcolor{Chapter }{AutoDoc}} \logpage{[ 4, 1, 1 ]}\nobreak \hyperdef{L}{X7CBD8AAF7DCEF352}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{AutoDoc({\mdseries\slshape [packageOrDirectory][,] [optrec]})\index{AutoDoc@\texttt{AutoDoc}} \label{AutoDoc} }\hfill{\scriptsize (function)}}\\ \textbf{\indent Returns:\ } nothing This is the main function of the \textsf{AutoDoc} package. It can perform any combination of the following tasks: \begin{enumerate} \item It can (re)generate a scaffold for your package manual. That is, it can produce two XML files in \textsf{GAPDoc} format to be used as part of your manual: First, a file named \texttt{doc/PACKAGENAME.xml} (with your package's name substituted) which is used as main XML file for the package manual, i.e. this file sets the XML doctype and defines various XML entities, includes other XML files (both those generated by \textsf{AutoDoc} as well as additional files created by other means), tells \textsf{GAPDoc} to generate a table of contents and an index, and more. Secondly, it creates a file \texttt{doc/title.xml} containing a title page for your documentation, with information about your package (name, description, version), its authors and more, based on the data in your \texttt{PackageInfo.g}. \item It can scan your package for \textsf{AutoDoc} based documentation (by using \textsf{AutoDoc} tags and the Autodoc command. This will produce further XML files to be used as part of the package manual. \item It can use \textsf{GAPDoc} to generate PDF, text and HTML (with MathJaX enabled) documentation from the \textsf{GAPDoc} XML files it generated as well as additional such files provided by you. For this, it invokes \texttt{MakeGAPDocDoc} (\textbf{GAPDoc: MakeGAPDocDoc}) to convert the XML sources, and it also instructs \textsf{GAPDoc} to copy supplementary files (such as CSS style files) into your doc directory (see \texttt{CopyHTMLStyleFiles} (\textbf{GAPDoc: CopyHTMLStyleFiles})). \end{enumerate} For more information and some examples, please refer to Chapter \ref{Tutorials}. The parameters have the following meanings: \begin{description} \item[{\mbox{\texttt{\mdseries\slshape packageOrDirectory}}}] The purpose of this parameter is twofold: to determine the package directory in which \textsf{AutoDoc} will operate, and to find the metadata concerning the package being documented. The parameter is either a string, an \texttt{IsDirectory} object, or omitted. If it is a string, \textsf{AutoDoc} interprets it as the name of a package, uses the metadata of the first package known to \textsf{GAP} with that name, and uses the \texttt{InstallationPath} specified in that metadata as the package directory. If \mbox{\texttt{\mdseries\slshape packageOrDirectory}} is an \texttt{IsDirectory} object, this is used as package directory; if the argument is omitted, then the current directory is used. In the last two cases, the specified directory must contain a \texttt{PackageInfo.g} file, and \textsf{AutoDoc} extracts all needed metadata from that. The \texttt{IsDirectory} form is for example useful if you have multiple versions of the package around and want to make sure the documentation of the correct version is built. Note that when using \texttt{AutoDocWorksheet} (see \ref{Chapter_AutoDoc_worksheets_Section_Worksheets}), there is no parameter corresponding to \mbox{\texttt{\mdseries\slshape packageOrDirectory}} and so the ``package directory'' is always the current directory, and there is no metadata. \item[{\mbox{\texttt{\mdseries\slshape optrec}}}] \mbox{\texttt{\mdseries\slshape optrec}} can be a record with some additional options. The following are currently supported: \begin{description} \item[{\mbox{\texttt{\mdseries\slshape dir}}}] This should either be a string, in which case it must be a path \emph{relative} to the specified package directory, or a \texttt{Directory()} object. (Thus, the only way to designate an absolute directory is with a \texttt{Directory()} object.) This option specifies where the package documentation (e.g. the \textsf{GAPDoc} XML or the manual PDF, etc.) files are stored and/or will be generated. \\ \emph{Default value: \texttt{"doc/"}.} \item[{\mbox{\texttt{\mdseries\slshape scaffold}}}] This controls whether and how to generate scaffold XML files for the package documentation. The value should be either \texttt{true}, \texttt{false} or a record. If it is a record or \texttt{true} (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if \mbox{\texttt{\mdseries\slshape opt.scaffold}} is missing but the package's info record in \texttt{PackageInfo.g} has an \texttt{AutoDoc} entry. In all other cases (in particular if \mbox{\texttt{\mdseries\slshape opt.scaffold}} is \texttt{false}), scaffolding is disabled. If scaffolding is enabled, and \mbox{\texttt{\mdseries\slshape PackageInfo.AutoDoc}} exists, then it is assumed to be a record, and its contents are used as default values for the scaffold settings. If \mbox{\texttt{\mdseries\slshape opt.scaffold}} is a record, it may contain the following entries. \begin{description} \item[{\mbox{\texttt{\mdseries\slshape includes}}}] A list of XML files to be included in the body of the main XML file. If you specify this list and also are using \textsf{AutoDoc} to document your operations with \textsf{AutoDoc} comments, you can add \texttt{{\textunderscore}AutoDocMainFile.xml} to this list to control at which point the documentation produced by \textsf{AutoDoc} is inserted. If you do not do this, it will be added after the last of your own XML files. \item[{\mbox{\texttt{\mdseries\slshape index}}}] By default, the scaffold creates an index. If you do not want an index, set this to \texttt{false}. \item[{\mbox{\texttt{\mdseries\slshape appendix}}}] This entry is similar to \mbox{\texttt{\mdseries\slshape opt.scaffold.includes}} but is used to specify files to include after the main body of the manual, i.e. typically appendices. \item[{\mbox{\texttt{\mdseries\slshape bib}}}] The name of a bibliography file, in BibTeX or XML format. If this key is not set, but there is a file \texttt{doc/PACKAGENAME.bib} then it is assumed that you want to use this as your bibliography. \item[{\mbox{\texttt{\mdseries\slshape entities}}}] A record whose keys are taken as entity names, set to the corresponding (string) values. For example, if you pass the record ``SomePackage'', \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] rec( SomePackage := "SomePackage", RELEASEYEAR := "2015" ) \end{Verbatim} then the following entity definitions are added to the XML preamble: \begin{Verbatim}[commandchars=@|B,fontsize=\small,frame=single,label=] SomePackage'> \end{Verbatim} This allows you to write ``\&SomePackage;'' and ``\&RELEASEYEAR;'' in your documentation, which will be replaced by respective values specified in the entities definition. \item[{\mbox{\texttt{\mdseries\slshape TitlePage}}}] A record whose entries are used to embellish the generated title page for the package manual with extra information, such as a copyright statement or acknowledgments. To this end, the names of the record components are used as XML element names, and the values of the components are outputted as content of these XML elements. For example, you could pass the following record to set a custom acknowledgements text: \begin{Verbatim}[commandchars=!@|,fontsize=\small,frame=single,label=] rec( Acknowledgements := "Many thanks to ..." ) \end{Verbatim} For a list of valid entries in the title page, please refer to the \textsf{GAPDoc} manual, specifically section (\textbf{GAPDoc: TitlePage}). \item[{\mbox{\texttt{\mdseries\slshape MainPage}}}] If scaffolding is enabled, by default a main XML file is generated (this is the file which contains the XML doctype and more). If you do not want this (e.g. because you have a handwritten main XML file), but still want \textsf{AutoDoc} to generate a title page for you, you can set this option to \texttt{false} \item[{\mbox{\texttt{\mdseries\slshape document{\textunderscore}class}}}] Sets the document class of the resulting PDF. The value can either be a string which has to be the name of the new document class, a list containing this string, or a list of two strings. Then the first one has to be the document class name, the second one the option string ( contained in [ ] ) in {\LaTeX}. \item[{\mbox{\texttt{\mdseries\slshape latex{\textunderscore}header{\textunderscore}file}}}] Replaces the standard header from \textsf{GAPDoc} completely with the header in this {\LaTeX} file. Please be careful here, and look at \textsf{GAPDoc}'s \texttt{latexheader.tex} file for an example. \end{description} \item[{\mbox{\texttt{\mdseries\slshape autodoc}}}] This controls whether and how to generate additional XML documentation files by scanning for \textsf{AutoDoc} documentation comments. The value should be either \texttt{true}, \texttt{false} or a record. If it is a record or \texttt{true} (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if \mbox{\texttt{\mdseries\slshape opt.autodoc}} is missing but the package depends (directly) on the \textsf{AutoDoc} package. In all other cases (in particular if \mbox{\texttt{\mdseries\slshape opt.autodoc}} is \texttt{false}), this feature is disabled. If \mbox{\texttt{\mdseries\slshape opt.autodoc}} is a record, it may contain the following entries. \begin{description} \item[{\mbox{\texttt{\mdseries\slshape files}}}] A list of files (given by paths relative to the package directory) to be scanned for \textsf{AutoDoc} documentation comments. Usually it is more convenient to use \mbox{\texttt{\mdseries\slshape autodoc.scan{\textunderscore}dirs}}, see below. \item[{\mbox{\texttt{\mdseries\slshape scan{\textunderscore}dirs}}}] A list of subdirectories of the package directory (given as relative paths) which \textsf{AutoDoc} then scans for .gi, .gd, .g, and .autodoc files; all of these files are then scanned for \textsf{AutoDoc} documentation comments. \\ \emph{Default value: \texttt{[ ".", "gap", "lib", "examples", "examples/doc" ]}.} \item[{\mbox{\texttt{\mdseries\slshape level}}}] This defines the level of the created documentation. The default value is 0. When parts of the manual are declared with a higher value they will not be printed into the manual. \end{description} \item[{\mbox{\texttt{\mdseries\slshape gapdoc}}}] This controls whether and how to invoke \textsf{GAPDoc} to create HTML, PDF and text files from your various XML files. The value should be either \texttt{true}, \texttt{false} or a record. If it is a record or \texttt{true} (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if \mbox{\texttt{\mdseries\slshape opt.gapdoc}} is missing. In all other cases (in particular if \mbox{\texttt{\mdseries\slshape opt.gapdoc}} is \texttt{false}), this feature is disabled. If \mbox{\texttt{\mdseries\slshape opt.gapdoc}} is a record, it may contain the following entries. \begin{description} \item[{\mbox{\texttt{\mdseries\slshape main}}}] The name of the main XML file of the package manual. This exists primarily to support packages with existing manual which use a filename here which differs from the default. In particular, specifying this is unnecessary when using scaffolding. \\ \emph{Default value: \texttt{PACKAGENAME.xml}}. \item[{\mbox{\texttt{\mdseries\slshape files}}}] A list of files (given by paths relative to the package directory) to be scanned for \textsf{GAPDoc} documentation comments. Usually it is more convenient to use \mbox{\texttt{\mdseries\slshape gapdoc.scan{\textunderscore}dirs}}, see below. \item[{\mbox{\texttt{\mdseries\slshape scan{\textunderscore}dirs}}}] A list of subdirectories of the package directory (given as relative paths) which \textsf{AutoDoc} then scans for .gi, .gd and .g files; all of these files are then scanned for \textsf{GAPDoc} documentation comments. \\ \emph{Default value: \texttt{[ ".", "gap", "lib", "examples", "examples/doc" ]}.} \item[{\mbox{\texttt{\mdseries\slshape LaTeXOptions}}}] Must be a record with entries which can be understood by \texttt{SetGapDocLaTeXOptions} (\textbf{GAPDoc: SetGapDocLaTeXOptions}). Each entry can be a string, which will be given to \textsf{GAPDoc} directly, or a list containing of two entries: The first one must be the string "file", the second one a filename. This file will be read and then its content is passed to \textsf{GAPDoc} as option with the name of the entry. \item[{\mbox{\texttt{\mdseries\slshape gap{\textunderscore}root{\textunderscore}relative{\textunderscore}path}}}] Either a boolean, or a string containing a relative path. By default (if this option is not set, or is set to \texttt{false}), references in the generated documentation referring to external documentation (such as the \textsf{GAP} manual) are encoded using absolute paths. This is fine as long as the documentation stays on only a single computer, but is problematic when preparing documentation that should be used on multiple computers, e.g., when creating a distribution archive of a \textsf{GAP} package.\\ Thus, if a relative path is provided via this option (or if it is set to \texttt{true}, in which case the relative path \texttt{../../..} is used), then \textsf{AutoDoc} and \textsf{GAPDoc} attempt to replace all absolute paths in references to \textsf{GAP} manuals by paths based on this relative path. On a technical level, \textsf{AutoDoc} passes the relative path to the \mbox{\texttt{\mdseries\slshape gaproot}} parameter of \texttt{MakeGAPDocDoc} (\textbf{GAPDoc: MakeGAPDocDoc}) \end{description} \item[{\mbox{\texttt{\mdseries\slshape extract{\textunderscore}examples}}}] Either \texttt{true} or a record. If set to \texttt{true}, then all manual examples are extracted and placed into files \texttt{tst/PACKAGENAME01.tst}, \texttt{tst/PACKAGENAME02.tst}, ... and so on, with one file for each chapter. For chapters with no examples, no file is created. As a record, the entry can have the following entries itself, to specify some options. \begin{description} \item[{units}] This controls how examples are grouped into files. Recognized values are "Chapter" (default), "Section", "Subsection" or "Single". Depending on the value, one file is created for each chapter, each section, each subsection or each example. For all other values only a single file is created. On a technical level, \textsf{AutoDoc} passes the value to the \mbox{\texttt{\mdseries\slshape units}} parameter of \texttt{ExtractExamples} (\textbf{GAPDoc: ExtractExamples}). \item[{skip{\textunderscore}empty{\textunderscore}in{\textunderscore}numbering}] If set to \texttt{true} (the default), the generated files use filenames with strictly sequential numbering; that means that if chapter 1 (or whatever units are being used) contains no examples but chapter 2 does, then the examples for chapter 2 are put into the file \texttt{tst/PACKAGENAME01.tst}. If this option is set to \texttt{false}, then the chapter numbers are used to generate the filenames; so the examples for chapter 2 would be put into the file \texttt{tst/PACKAGENAME02.tst}. \end{description} \end{description} \end{description} } \subsection{\textcolor{Chapter }{InfoAutoDoc}} \logpage{[ 4, 1, 2 ]}\nobreak \hyperdef{L}{X81F946A785BA3D6E}{} {\noindent\textcolor{FuncColor}{$\triangleright$\enspace\texttt{InfoAutoDoc\index{InfoAutoDoc@\texttt{InfoAutoDoc}} \label{InfoAutoDoc} }\hfill{\scriptsize (info class)}}\\ Info class for the \textsf{AutoDoc} package. Set this to 0 to suppress info messages, 1 to allow most messages, and 2 to allow all messages including those that contain file paths. This can be set by calling, for example, \texttt{SetInfoLevel(InfoPackageManager, 0)}. Default value 1. } } \section{\textcolor{Chapter }{Examples}}\label{Chapter_AutoDoc_Section_Examples} \logpage{[ 4, 2, 0 ]} \hyperdef{L}{X7A489A5D79DA9E5C}{} { Some basic examples for using \texttt{AutoDoc} were already shown in Chapter \ref{Tutorials}. } } \def\bibname{References\logpage{[ "Bib", 0, 0 ]} \hyperdef{L}{X7A6F98FD85F02BFE}{} } \bibliographystyle{alpha} \bibliography{bib.xml} \addcontentsline{toc}{chapter}{References} \def\indexname{Index\logpage{[ "Ind", 0, 0 ]} \hyperdef{L}{X83A0356F839C696F}{} } \cleardoublepage \phantomsection \addcontentsline{toc}{chapter}{Index} \printindex \immediate\write\pagenrlog{["Ind", 0, 0], \arabic{page},} \newpage \immediate\write\pagenrlog{["End"], \arabic{page}];} \immediate\closeout\pagenrlog \end{document} AutoDoc-2025.10.16/doc/times.css0000644000175100017510000000026115074117054015457 0ustar runnerrunner/* times.css Frank Lübeck */ /* Change default CSS to use Times font. */ body { font-family: Times,Times New Roman,serif; } AutoDoc-2025.10.16/doc/rainbow.js0000644000175100017510000000533615074117054015633 0ustar runnerrunner function randchar(str) { var i = Math.floor(Math.random() * str.length); while (i == str.length) i = Math.floor(Math.random() * str.length); return str[i]; } hexdigits = "0123456789abcdef"; function randlight() { return randchar("cdef")+randchar(hexdigits)+ randchar("cdef")+randchar(hexdigits)+ randchar("cdef")+randchar(hexdigits) } function randdark() { return randchar("012345789")+randchar(hexdigits)+ randchar("012345789")+randchar(hexdigits)+ randchar("102345789")+randchar(hexdigits) } document.write('\n'); AutoDoc-2025.10.16/doc/_Chunks.xml0000644000175100017510000000000015074117054015727 0ustar runnerrunnerAutoDoc-2025.10.16/doc/AutoDoc.xml0000644000175100017510000000064415074117054015711 0ustar runnerrunner ] > <#Include SYSTEM "title.xml"> <#Include SYSTEM "Tutorials.xml"> <#Include SYSTEM "Comments.xml"> <#Include SYSTEM "_AutoDocMainFile.xml"> AutoDoc-2025.10.16/doc/nocolorprompt.css0000644000175100017510000000031315074117054017251 0ustar runnerrunner /* colors for ColorPrompt like examples */ span.GAPprompt { color: #000000; font-weight: normal; } span.GAPbrkprompt { color: #000000; font-weight: normal; } span.GAPinput { color: #000000; } AutoDoc-2025.10.16/doc/chap1_mj.html0000644000175100017510000010326015074117054016177 0ustar runnerrunner GAP (AutoDoc) - Chapter 1: Getting started using AutoDoc
Goto Chapter: Top 1 2 3 4 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

1 Getting started using AutoDoc
 1.1 Creating a package manual from scratch
 1.2 Documenting code with AutoDoc
 1.3 Using AutoDoc in an existing GAPDoc manual
 1.4 Scaffolds
 1.5 AutoDoc worksheets

1 Getting started using AutoDoc

AutoDoc is a GAP package which is meant to aid GAP package authors in creating and maintaining the documentation of their packages. In this capacity it builds upon the GAPDoc package (see https://www.gap-system.org/Packages/gapdoc.html). As such, it is not a replacement for GAPDoc, but rather complements it.

In this chapter we describe how to get started using AutoDoc for your package. First, we explain in Section 1.1 how to write a new package manual from scratch.

Then we show in Section 1.3 how you might benefit from AutoDoc even if you already have a complete manual written using GAPDoc.

In Section 1.4, we explain how you may use AutoDoc to generate a title page and the main XML file for your manual.

Finally, Section 1.5, explains what AutoDoc worksheets are and how to use them.

1.1 Creating a package manual from scratch

Suppose your package is already up and running, but so far has no manual. Then you can rapidly generate a scaffold for a package manual using the AutoDoc (4.1-1) command like this, while running GAP from within your package's directory (the one containing the PackageInfo.g file):

LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := true ) );

This first reads the PackageInfo.g file from the current directory. It extracts information about the package from it (such as its name and version, see Section 1.4-1). It then creates two XML files doc/NAME_OF_YOUR_PACKAGE.xml and doc/title.xml inside the package directory. Finally, it runs GAPDoc on them to produce a nice initial PDF and HTML version of your fresh manual.

To ensure that the GAP help system picks up your package manual, you should also add something like the following to your PackageInfo.g:

PackageDoc := rec(
  BookName  := ~.PackageName,
  ArchiveURLSubset := ["doc"],
  HTMLStart := "doc/chap0.html",
  PDFFile   := "doc/manual.pdf",
  SixFile   := "doc/manual.six",
  LongTitle := ~.Subtitle,
),

Congratulations, your package now has a minimal working manual. Of course it will be mostly empty for now, but it already should contain some useful information, based on the data in your PackageInfo.g. This includes your package's name, version and description as well as information about its authors. And if you ever change the package data, (e.g. because your email address changed), just re-run the above command to regenerate the two main XML files with the latest information.

Next of course you need to provide actual content (unfortunately, we were not yet able to automate that for you, more research on artificial intelligence is required). To add more content, you have several options: You could add further GAPDoc XML files containing extra chapters, sections and so on. Or you could use classic GAPDoc source comments. For details on either, please refer to GAPDoc: Distributing a Document into Several Files, as well as Section 1.3 of this manual on how to teach the AutoDoc (4.1-1) command to include this extra documentation. Or you could use the special documentation facilities AutoDoc provides (see Section 1.2).

You will probably want to re-run the AutoDoc (4.1-1) command frequently, e.g. whenever you modified your documentation or your PackageInfo.g. To make this more convenient and reproducible, we recommend putting its invocation into a file makedoc.g in your package directory, with content based on the following example:

LoadPackage( "AutoDoc" );
AutoDoc( rec( autodoc := true ) );
QUIT;

Then you can regenerate the package manual from the command line with the following command, executed from within in the package directory:

gap makedoc.g

1.2 Documenting code with AutoDoc

To get one of your global functions, operations, attributes etc. to appear in the package manual, simply insert an AutoDoc comment of the form #! directly in front of it. For example:

#!
DeclareOperation( "ToricVariety", [ IsConvexObject ] );

This tiny change is already sufficient to ensure that the operation appears in the manual. In general, you will want to add further information about the operation, such as in the following example:

#! @Arguments conv
#! @Returns a toric variety
#! @Description
#!  Creates a toric variety out
#!  of the convex object <A>conv</A>.
DeclareOperation( "ToricVariety", [ IsConvexObject ] );

For a thorough description of what you can do with AutoDoc documentation comments, please refer to chapter 2.

Suppose you have not been using GAPDoc before but instead used the process described in section 1.1 to create your manual. Then the following GAP command will regenerate the manual and automatically include all newly documented functions, operations etc.:

LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := true,
              autodoc := true ) );

If you are not using the scaffolding feature, e.g. because you already have an existing GAPDoc based manual, then you can still use AutoDoc documentation comments. Just make sure to first edit the main XML file of your documentation, and insert the line

<#Include SYSTEM "_AutoDocMainFile.xml">

in a suitable place. This means that you can mix AutoDoc documentation comment freely with your existing documentation; you can even still make use of any existing GAPDoc documentation comments in your code. The following command should be useful for you in this case; it still scans the package code for AutoDoc documentation comments and the runs GAPDoc to produce HTML and PDF output, but does not touch your documentation XML files otherwise.

LoadPackage( "AutoDoc" );
AutoDoc( rec( autodoc := true ) );

1.3 Using AutoDoc in an existing GAPDoc manual

Even if you already have an existing GAPDoc manual, it might be interesting for you to use AutoDoc for two purposes:

First off, with AutoDoc it is very convenient to regenerate your documentation.

Secondly, the scaffolding feature which generates a title page with all the metadata of your package in a uniform way is very handy. The somewhat tedious process of keeping your title page in sync with your PackageInfo.g is fully automated this way (including the correct version, release data, author information and so on).

There are various examples of packages using AutoDoc for this purpose only, e.g. io and orb.

1.3-1 Using AutoDoc on a complete GAPDoc manual

Suppose you already have a complete XML manual, with some main and title XML files and some documentation for operations distributed over all your .g, .gd, and .gi files. Suppose the main XML file is named PACKAGENAME.xml and is in the /doc subdirectory of your package. Then you can rebuild your manual by executing the following two GAP commands from a GAP session started in the root directory of your package:

LoadPackage( "AutoDoc" );
AutoDoc( );

In contrast, the RingsForHomalg package currently uses essentially the following code in its makedoc.g file to achieve the same result:

LoadPackage( "GAPDoc" );
SetGapDocLaTeXOptions( "utf8" );
bib := ParseBibFiles( "doc/RingsForHomalg.bib" );
WriteBibXMLextFile( "doc/RingsForHomalgBib.xml", bib );
list := [
         "../gap/RingsForHomalg.gd",
         "../gap/RingsForHomalg.gi",
         "../gap/Singular.gi",
         "../gap/SingularBasic.gi",
         "../examples/RingConstructionsExternalGAP.g",
         "../examples/RingConstructionsSingular.g",
         "../examples/RingConstructionsMAGMA.g",
         "../examples/RingConstructionsMacaulay2.g",
         "../examples/RingConstructionsSage.g",
         "../examples/RingConstructionsMaple.g",
         ];
MakeGAPDocDoc( "doc", "RingsForHomalg", list, "RingsForHomalg" );
GAPDocManualLab( "RingsForHomalg" );

Note that in particular, you do not have to worry about keeping a list of your implementation files up-to-date.

But there is more. AutoDoc can create .tst files from the examples in your manual to test your package. This can be achieved via

LoadPackage( "AutoDoc" );
AutoDoc( rec( extract_examples := true ) );

Now files PACKAGENAME01.tst, PACKAGENAME02.tst and so appear in the tst/ subdirectory of your package, and can be tested as usual using Test (Reference: Test) respectively TestDirectory (Reference: TestDirectory).

1.3-2 Setting different GAPDoc options

Sometimes, the default values for the GAPDoc command used by AutoDoc may not be suitable for your manual.

Suppose your main XML file is not named PACKAGENAME.xml, but rather something else, e.g. main.xml. Then you can tell AutoDoc to use this file as the main XML file via

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( main := "main" ) ) );

As explained above, by default AutoDoc scans all .g, .gd and .gi files it can find inside of your package root directory, and in the subdirectories gap, lib, examples and examples/doc as well. If you keep source files with documentation in other directories, you can adjust the list of directories AutoDoc scans via the scan_dirs option. The following example illustrates this by instructing AutoDoc to only search in the subdirectory package_sources of the packages root directory.

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( scan_dirs := [ "package_sources" ] ) ) );

You can also specify an explicit list of files containing documentation, which will be searched in addition to any files located within the scan directories:

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( files := [ "path/to/some/hidden/file.gds" ] ) ) );

Giving such a file does not prevent the standard scan_dirs from being scanned for other files.

Next, GAPDoc supports the documentation to be built with relative paths. This means, links to manuals of other packages or the GAP library will not be absolute, but relative from your documentation. This can be particularly useful if you want to build a release tarball or move your GAP installation around later. Suppose you are starting GAP in the root path of your package as always, and the standard call of AutoDoc (4.1-1) will then build the documentation in the doc subdirectory of your package. From this directory, the gap root directory has the relative path ../../... Then you can enable the relative paths by

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( gap_root_relative_path := "../../.." ) ) );

or, since ../../.. is the standard option for gap_root_relative_path, by

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( gap_root_relative_path := true ) ) );

1.3-3 Checklist for converting an existing GAPDoc manual to use AutoDoc

Here is a checklist for authors of a package PackageName, which already has a GAPDoc based manual, who wish to use AutoDoc to build the manual from now on. We assume that the manual is currently built by reading a file makedoc.g and that the main .xml file is named manual.xml.

The files PackageInfo.g, makedoc.g, doc/title.xml and doc/PackageName.xml (if it exists) will be altered by this procedure, so it may be wise to keep backup copies.

You should have copies of the AutoDoc files PackageInfo.g and makedoc.g to hand when reading these instructions.

You should now be ready to run GAP and Read("makedoc.g"); in your package root directory.

1.4 Scaffolds

1.4-1 Generating a title page

For most (if not all) GAP packages, the title page of the package manual lists information such as the release date, version, names and contact details of the authors, and so on. All this data is also contained in your PackageInfo.g, and whenever you make a change to that file, there is a risk that you forget to update your manual to match. And even if you don't forget it, you of course have to spend some time to adjust the manual. GAPDoc can help to a degree with this via entities. Thus, you will sometimes see code like this in PackageInfo.g files:

Version        := "1.2.3",
Date           := "20/01/2015",
##  <#GAPDoc Label="PKGVERSIONDATA">
##  <!ENTITY VERSION "1.2.3">
##  <!ENTITY RELEASEDATE "20 January 2015">
##  <!ENTITY RELEASEYEAR "2015">
##  <#/GAPDoc>

However, it is still easy to forget both of these versions. And it doesn't solve the problem of updating package authors addresses. Neither of these is a big issue, of course, but there have been plenty examples in the past where people forget either of these two things, and it can be slightly embarrassing. It may even require you to make a new release just to fix the issue, which in our opinion is a sad waste of your valuable time.

So instead of worrying about manually synchronising these things, you can instruct AutoDoc to generate a title page for your manual based on the information in your PackageInfo.g. The following commands do just that (in addition to building your manual), by generating a file called doc/title.xml.

LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := rec( MainPage := false ) ) );

Note that this only outputs doc/title.xml but does not touch any other files of your documentation. In particular, you need to explicitly include doc/title.xml from your main XML file.

However, you can also tell AutoDoc to maintain the main XML file for you, in which case this is automatic. In fact, this is the default if you enable scaffolding; the above example command explicitly told AutoDoc not to generate a main page.

1.4-2 Generating the main XML file

The following generates a main XML file for your documentation in addition to the title page. The main XML file includes the title page by default, as well as any documentation generated from AutoDoc documentation comments.

LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := true ) );

You can instruct AutoDoc to include additional XML files by giving it a list of filenames, as in the following example:

LoadPackage( "AutoDoc" );
AutoDoc(rec(
    scaffold := rec(
        includes := [ "somefile.xml", "anotherfile.xml" ]
    )
));

For more information, please consult the documentation of the AutoDoc (4.1-1) function.

1.4-3 What data is used from PackageInfo.g?

AutoDoc can use data from PackageInfo.g in order to generate a title page. Specifically, the following components of the package info record are taken into account:

PackageName

This is used to set the <Title> element of the title page.

Subtitle

This is used to set the <Subtitle> element of the title page.

Version

This is used to set the <Version> element of the title page, with the string Version prepended.

Date

This is used to set the <Date> element of the title page.

Persons

This is used to generate <Author> elements in the generated title page.

PackageDoc

This is a record (or a list of records) which is used to tell the GAP help system about the package manual. Currently AutoDoc extracts the value of the PackageDoc.BookName component and then passes that on to GAPDoc when creating the HTML, PDF and text versions of the manual.

AutoDoc

This is a record which can be used to control the scaffolding performed by AutoDoc, specifically to provide extra information for the title page. For example, you can set AutoDoc.TitlePage.Copyright to a string which will then be inserted on the generated title page. Using this method you can customize the following title page elements: TitleComment, Abstract, Copyright, Acknowledgements and Colophon.

Note that AutoDoc.TitlePage behaves exactly the same as the scaffold.TitlePage parameter of the AutoDoc (4.1-1) function.

1.5 AutoDoc worksheets

AutoDoc worksheets can be used to create HTML and PDF documents using AutoDoc syntax and possibly including GAP examples and implementations without having them associated to a package. A file for a worksheet could look like this:

#! @Title My first worksheet
#! @Author Charlie Brown

#! @Chapter Some groups

#! @BeginExample
S3 := SymmetricGroup( 3 );;
S4 := SymmetricGroup( 4 );;
#! @EndExample

Now, one can create a PDF and HTML document, like a package documentation out of it. Suppose the document above is saved as worksheet.g. Then, when GAP is started in the directory of this file, the command

AutoDocWorksheet( "worksheet.g" );

will create a subdirectory called doc of the current directory in which it will create the documentation. There are several options to configure the output of the worksheet command, which are identical to the options of the AutoDoc (4.1-1) command. It is even possible to test the examples in the worksheet using the extract_examples option of the AutoDoc (4.1-1) command.

Since the worksheets do not have a PackageInfo.g to extract information, all possible tags that GAPDoc supports for the title page can be set into the document. A fully typed title page can look like this:

#! @Title My first worksheet
#! @Subtitle Some small examples
#! @Author Charlie Brown

#! @Version 0.1
#! @TitleComment Some worksheet
#! @Date 01/01/2016
#! @Address TU Kaiserslautern
#! @Abstract
#!  A worksheet showing some small examples about groups.
#! @Copyright 2016 Charlie Brown
#! @Acknowledgements Woodstock
#! @Colophon Some colophon

#! @Chapter Some groups

#! @BeginExample
S3 := SymmetricGroup( 3 );;
S4 := SymmetricGroup( 4 );;
#! @EndExample
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chap0.txt0000644000175100017510000001321515074117054015363 0ustar runnerrunner  AutoDoc   Generate documentation from GAP source code  2025.10.16 16 October 2025 Sebastian Gutsche Max Horn Sebastian Gutsche Email: mailto:gutsche@mathematik.uni-siegen.de Homepage: https://algebra.mathematik.uni-siegen.de/gutsche/ Address: Department Mathematik Universität Siegen Walter-Flex-Straße 3 57072 Siegen Germany Max Horn Email: mailto:mhorn@rptu.de Homepage: https://www.quendi.de/math Address: Fachbereich Mathematik RPTU Kaiserslautern-Landau Gottlieb-Daimler-Straße 48 67663 Kaiserslautern Germany ------------------------------------------------------- Abstract AutoDoc is a GAP package whose purpose is to aid GAP package authors in creating and maintaining the documentation of their packages. ------------------------------------------------------- Copyright © 2012-2022 by Sebastian Gutsche and Max Horn This package may be distributed under the terms and conditions of the GNU Public License Version 2 or (at your option) any later version. ------------------------------------------------------- Acknowledgements This documentation was prepared using the GAPDoc package [LN12]. ------------------------------------------------------- Contents (AutoDoc) 1 Getting started using AutoDoc 1.1 Creating a package manual from scratch 1.2 Documenting code with AutoDoc 1.3 Using AutoDoc in an existing GAPDoc manual 1.3-1 Using AutoDoc on a complete GAPDoc manual 1.3-2 Setting different GAPDoc options 1.3-3 Checklist for converting an existing GAPDoc manual to use AutoDoc 1.4 Scaffolds 1.4-1 Generating a title page 1.4-2 Generating the main XML file 1.4-3 What data is used from PackageInfo.g? 1.5 AutoDoc worksheets 2 AutoDoc documentation comments 2.1 Documenting declarations 2.1-1 @Description descr 2.1-2 @Returns ret_val 2.1-3 @Arguments args 2.1-4 @Group grpname 2.1-5 @Label label 2.1-6 AProperty 2.1-7 AProperty 2.1-8 @ChapterInfo chapter, section 2.2 Other documentation comments 2.2-1 @Chapter name 2.2-2 @Section name 2.2-3 @Subsection name 2.2-4 @BeginGroup [grpname] 2.2-5 @EndGroup 2.2-6 @GroupTitle title 2.2-7 @Level lvl 2.2-8 @ResetLevel 2.2-9 @BeginExample and @EndExample 2.2-10 @BeginExampleSession and @EndExampleSession 2.2-11 @BeginLog and @EndLog 2.2-12 @BeginLogSession and @EndLogSession 2.2-13 @DoNotReadRestOfFile 2.2-14 @BeginChunk name, @EndChunk, and @InsertChunk name 2.2-15 @BeginCode name, @EndCode, and @InsertCode name 2.2-16 @LatexOnly text, @BeginLatexOnly, and @EndLatexOnly 2.2-17 @NotLatex text, @BeginNotLatex, and @EndNotLatex 2.3 Title page commands 2.4 Plain text files 2.5 Grouping 2.5-1 A family of operations 2.6 Level 2.7 Markdown-like formatting of text in AutoDoc 2.7-1 Lists 2.7-2 Math modes 2.7-3 Emphasize 2.7-4 Inline code 2.8 Deprecated commands 3 AutoDoc worksheets 3.1 Worksheets 3.1-1 AutoDocWorksheet 4 AutoDoc 4.1 The AutoDoc() function 4.1-1 AutoDoc 4.1-2 InfoAutoDoc 4.2 Examples  AutoDoc-2025.10.16/doc/chap1.txt0000644000175100017510000006566515074117054015404 0ustar runnerrunner 1 Getting started using AutoDoc AutoDoc is a GAP package which is meant to aid GAP package authors in creating and maintaining the documentation of their packages. In this capacity it builds upon the GAPDoc package (see https://www.gap-system.org/Packages/gapdoc.html). As such, it is not a replacement for GAPDoc, but rather complements it. In this chapter we describe how to get started using AutoDoc for your package. First, we explain in Section 1.1 how to write a new package manual from scratch. Then we show in Section 1.3 how you might benefit from AutoDoc even if you already have a complete manual written using GAPDoc. In Section 1.4, we explain how you may use AutoDoc to generate a title page and the main XML file for your manual. Finally, Section 1.5, explains what AutoDoc worksheets are and how to use them. 1.1 Creating a package manual from scratch Suppose your package is already up and running, but so far has no manual. Then you can rapidly generate a scaffold for a package manual using the AutoDoc (4.1-1) command like this, while running GAP from within your package's directory (the one containing the PackageInfo.g file):  LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true ) );  This first reads the PackageInfo.g file from the current directory. It extracts information about the package from it (such as its name and version, see Section 1.4-1). It then creates two XML files doc/NAME_OF_YOUR_PACKAGE.xml and doc/title.xml inside the package directory. Finally, it runs GAPDoc on them to produce a nice initial PDF and HTML version of your fresh manual. To ensure that the GAP help system picks up your package manual, you should also add something like the following to your PackageInfo.g:  PackageDoc := rec(  BookName := ~.PackageName,  ArchiveURLSubset := ["doc"],  HTMLStart := "doc/chap0.html",  PDFFile := "doc/manual.pdf",  SixFile := "doc/manual.six",  LongTitle := ~.Subtitle, ),  Congratulations, your package now has a minimal working manual. Of course it will be mostly empty for now, but it already should contain some useful information, based on the data in your PackageInfo.g. This includes your package's name, version and description as well as information about its authors. And if you ever change the package data, (e.g. because your email address changed), just re-run the above command to regenerate the two main XML files with the latest information. Next of course you need to provide actual content (unfortunately, we were not yet able to automate that for you, more research on artificial intelligence is required). To add more content, you have several options: You could add further GAPDoc XML files containing extra chapters, sections and so on. Or you could use classic GAPDoc source comments. For details on either, please refer to 'GAPDoc: Distributing a Document into Several Files', as well as Section 1.3 of this manual on how to teach the AutoDoc (4.1-1) command to include this extra documentation. Or you could use the special documentation facilities AutoDoc provides (see Section 1.2). You will probably want to re-run the AutoDoc (4.1-1) command frequently, e.g. whenever you modified your documentation or your PackageInfo.g. To make this more convenient and reproducible, we recommend putting its invocation into a file makedoc.g in your package directory, with content based on the following example:  LoadPackage( "AutoDoc" ); AutoDoc( rec( autodoc := true ) ); QUIT;  Then you can regenerate the package manual from the command line with the following command, executed from within in the package directory:  gap makedoc.g  1.2 Documenting code with AutoDoc To get one of your global functions, operations, attributes etc. to appear in the package manual, simply insert an AutoDoc comment of the form #! directly in front of it. For example:  #! DeclareOperation( "ToricVariety", [ IsConvexObject ] );  This tiny change is already sufficient to ensure that the operation appears in the manual. In general, you will want to add further information about the operation, such as in the following example:  #! @Arguments conv #! @Returns a toric variety #! @Description #! Creates a toric variety out #! of the convex object conv. DeclareOperation( "ToricVariety", [ IsConvexObject ] );  For a thorough description of what you can do with AutoDoc documentation comments, please refer to chapter 2. Suppose you have not been using GAPDoc before but instead used the process described in section 1.1 to create your manual. Then the following GAP command will regenerate the manual and automatically include all newly documented functions, operations etc.:  LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true,  autodoc := true ) );  If you are not using the scaffolding feature, e.g. because you already have an existing GAPDoc based manual, then you can still use AutoDoc documentation comments. Just make sure to first edit the main XML file of your documentation, and insert the line  <#Include SYSTEM "_AutoDocMainFile.xml">  in a suitable place. This means that you can mix AutoDoc documentation comment freely with your existing documentation; you can even still make use of any existing GAPDoc documentation comments in your code. The following command should be useful for you in this case; it still scans the package code for AutoDoc documentation comments and the runs GAPDoc to produce HTML and PDF output, but does not touch your documentation XML files otherwise.  LoadPackage( "AutoDoc" ); AutoDoc( rec( autodoc := true ) );  1.3 Using AutoDoc in an existing GAPDoc manual Even if you already have an existing GAPDoc manual, it might be interesting for you to use AutoDoc for two purposes: First off, with AutoDoc it is very convenient to regenerate your documentation. Secondly, the scaffolding feature which generates a title page with all the metadata of your package in a uniform way is very handy. The somewhat tedious process of keeping your title page in sync with your PackageInfo.g is fully automated this way (including the correct version, release data, author information and so on). There are various examples of packages using AutoDoc for this purpose only, e.g. io and orb. 1.3-1 Using AutoDoc on a complete GAPDoc manual Suppose you already have a complete XML manual, with some main and title XML files and some documentation for operations distributed over all your .g, .gd, and .gi files. Suppose the main XML file is named PACKAGENAME.xml and is in the /doc subdirectory of your package. Then you can rebuild your manual by executing the following two GAP commands from a GAP session started in the root directory of your package:  LoadPackage( "AutoDoc" ); AutoDoc( );  In contrast, the RingsForHomalg package currently uses essentially the following code in its makedoc.g file to achieve the same result:  LoadPackage( "GAPDoc" ); SetGapDocLaTeXOptions( "utf8" ); bib := ParseBibFiles( "doc/RingsForHomalg.bib" ); WriteBibXMLextFile( "doc/RingsForHomalgBib.xml", bib ); list := [  "../gap/RingsForHomalg.gd",  "../gap/RingsForHomalg.gi",  "../gap/Singular.gi",  "../gap/SingularBasic.gi",  "../examples/RingConstructionsExternalGAP.g",  "../examples/RingConstructionsSingular.g",  "../examples/RingConstructionsMAGMA.g",  "../examples/RingConstructionsMacaulay2.g",  "../examples/RingConstructionsSage.g",  "../examples/RingConstructionsMaple.g",  ]; MakeGAPDocDoc( "doc", "RingsForHomalg", list, "RingsForHomalg" ); GAPDocManualLab( "RingsForHomalg" );  Note that in particular, you do not have to worry about keeping a list of your implementation files up-to-date. But there is more. AutoDoc can create .tst files from the examples in your manual to test your package. This can be achieved via  LoadPackage( "AutoDoc" ); AutoDoc( rec( extract_examples := true ) );  Now files PACKAGENAME01.tst, PACKAGENAME02.tst and so appear in the tst/ subdirectory of your package, and can be tested as usual using Test (Reference: Test) respectively TestDirectory (Reference: TestDirectory). 1.3-2 Setting different GAPDoc options Sometimes, the default values for the GAPDoc command used by AutoDoc may not be suitable for your manual. Suppose your main XML file is not named PACKAGENAME.xml, but rather something else, e.g. main.xml. Then you can tell AutoDoc to use this file as the main XML file via  LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( main := "main" ) ) );  As explained above, by default AutoDoc scans all .g, .gd and .gi files it can find inside of your package root directory, and in the subdirectories gap, lib, examples and examples/doc as well. If you keep source files with documentation in other directories, you can adjust the list of directories AutoDoc scans via the scan_dirs option. The following example illustrates this by instructing AutoDoc to only search in the subdirectory package_sources of the packages root directory.  LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( scan_dirs := [ "package_sources" ] ) ) );  You can also specify an explicit list of files containing documentation, which will be searched in addition to any files located within the scan directories:  LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( files := [ "path/to/some/hidden/file.gds" ] ) ) );  Giving such a file does not prevent the standard scan_dirs from being scanned for other files. Next, GAPDoc supports the documentation to be built with relative paths. This means, links to manuals of other packages or the GAP library will not be absolute, but relative from your documentation. This can be particularly useful if you want to build a release tarball or move your GAP installation around later. Suppose you are starting GAP in the root path of your package as always, and the standard call of AutoDoc (4.1-1) will then build the documentation in the doc subdirectory of your package. From this directory, the gap root directory has the relative path ../../... Then you can enable the relative paths by  LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( gap_root_relative_path := "../../.." ) ) );  or, since ../../.. is the standard option for gap_root_relative_path, by  LoadPackage( "AutoDoc" ); AutoDoc( rec( gapdoc := rec( gap_root_relative_path := true ) ) );  1.3-3 Checklist for converting an existing GAPDoc manual to use AutoDoc Here is a checklist for authors of a package PackageName, which already has a GAPDoc based manual, who wish to use AutoDoc to build the manual from now on. We assume that the manual is currently built by reading a file makedoc.g and that the main .xml file is named manual.xml. The files PackageInfo.g, makedoc.g, doc/title.xml and doc/PackageName.xml (if it exists) will be altered by this procedure, so it may be wise to keep backup copies. You should have copies of the AutoDoc files PackageInfo.g and makedoc.g to hand when reading these instructions.  Copy AutoDoc/makedoc.g to PackageName/makedoc.g.  Edit PackageName/makedoc.g as follows.  Change the header comment to match other files in your package.  After LoadPackage("AutoDoc"); add LoadPackage("PackageName");.  In the AutoDoc record delete autodoc := true;.  In the scaffold record change the includes list to be the list of your .xml files that are contained in manual.xml.  If you do not have a bibliography you may delete the bib := "bib.xml", field in the scaffold. Otherwise, edit the file name if you have a different file. If you only have a .bib file (manual.bib or bib.xml.bib say) you should rename this file PackageName.bib.  In the LaTeXOptions record, which is in the gapdoc record, enter any LaTeX newcommands previously in manual.xml. (If there are none you may safely delete this record.) To illustrate this option, the AutoDoc file makedoc.g defines the command \bbZ by \newcommand{\bbZ}{\mathbb{Z}}, which may be used to produce the LaTeX formula f : bbZ^2 -> bbZ. However, note that this only works in the PDF version of the file.  Now edit PackageName/PackageInfo.g as follows.  Delete any PKGVERSIONDATA chunk that may be there. One reason for converting your manual to use AutoDoc is to stop using entities such as PACKAGENAMEVERSION.  Copy the AutoDoc record from AutoDoc/PackageInfo.g to the end of your file (just before the final "));".  Replace the Copyright, Abstract and Acknowledgements fields of the TitlePage record with the corresponding material from your manual.xml. (If you do not have an abstract, then delete the Abstract field, etc.)  In the entities record enter any entities previously stored in your manual.xml. (Again, if you have none, you may safely delete this record.) To illustrate this option the AutoDoc file PackageInfo.g defines entities for the names of packages io and PackageName.  If you are using a GitHub repository, as well as running "git add" on files makedoc.g, PackageInfo.g and doc/PackageName.bib, you should run "git rm -f" on files doc/manual.xml, and doc/title.xml. You should now be ready to run GAP and Read("makedoc.g"); in your package root directory. 1.4 Scaffolds 1.4-1 Generating a title page For most (if not all) GAP packages, the title page of the package manual lists information such as the release date, version, names and contact details of the authors, and so on. All this data is also contained in your PackageInfo.g, and whenever you make a change to that file, there is a risk that you forget to update your manual to match. And even if you don't forget it, you of course have to spend some time to adjust the manual. GAPDoc can help to a degree with this via entities. Thus, you will sometimes see code like this in PackageInfo.g files:  Version := "1.2.3", Date := "20/01/2015", ## <#GAPDoc Label="PKGVERSIONDATA"> ##  ##  ##  ## <#/GAPDoc>  However, it is still easy to forget both of these versions. And it doesn't solve the problem of updating package authors addresses. Neither of these is a big issue, of course, but there have been plenty examples in the past where people forget either of these two things, and it can be slightly embarrassing. It may even require you to make a new release just to fix the issue, which in our opinion is a sad waste of your valuable time. So instead of worrying about manually synchronising these things, you can instruct AutoDoc to generate a title page for your manual based on the information in your PackageInfo.g. The following commands do just that (in addition to building your manual), by generating a file called doc/title.xml.  LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := rec( MainPage := false ) ) );  Note that this only outputs doc/title.xml but does not touch any other files of your documentation. In particular, you need to explicitly include doc/title.xml from your main XML file. However, you can also tell AutoDoc to maintain the main XML file for you, in which case this is automatic. In fact, this is the default if you enable scaffolding; the above example command explicitly told AutoDoc not to generate a main page. 1.4-2 Generating the main XML file The following generates a main XML file for your documentation in addition to the title page. The main XML file includes the title page by default, as well as any documentation generated from AutoDoc documentation comments.  LoadPackage( "AutoDoc" ); AutoDoc( rec( scaffold := true ) );  You can instruct AutoDoc to include additional XML files by giving it a list of filenames, as in the following example:  LoadPackage( "AutoDoc" ); AutoDoc(rec(  scaffold := rec(  includes := [ "somefile.xml", "anotherfile.xml" ]  ) ));  For more information, please consult the documentation of the AutoDoc (4.1-1) function. 1.4-3 What data is used from PackageInfo.g? AutoDoc can use data from PackageInfo.g in order to generate a title page. Specifically, the following components of the package info record are taken into account: PackageName This is used to set the  element of the title page. Subtitle This is used to set the <Subtitle> element of the title page. Version This is used to set the <Version> element of the title page, with the string Version  prepended. Date This is used to set the <Date> element of the title page. Persons This is used to generate <Author> elements in the generated title page. PackageDoc This is a record (or a list of records) which is used to tell the GAP help system about the package manual. Currently AutoDoc extracts the value of the PackageDoc.BookName component and then passes that on to GAPDoc when creating the HTML, PDF and text versions of the manual. AutoDoc This is a record which can be used to control the scaffolding performed by AutoDoc, specifically to provide extra information for the title page. For example, you can set AutoDoc.TitlePage.Copyright to a string which will then be inserted on the generated title page. Using this method you can customize the following title page elements: TitleComment, Abstract, Copyright, Acknowledgements and Colophon. Note that AutoDoc.TitlePage behaves exactly the same as the scaffold.TitlePage parameter of the AutoDoc (4.1-1) function. 1.5 AutoDoc worksheets AutoDoc worksheets can be used to create HTML and PDF documents using AutoDoc syntax and possibly including GAP examples and implementations without having them associated to a package. A file for a worksheet could look like this:  #! @Title My first worksheet #! @Author Charlie Brown  #! @Chapter Some groups  #! @BeginExample S3 := SymmetricGroup( 3 );; S4 := SymmetricGroup( 4 );; #! @EndExample  Now, one can create a PDF and HTML document, like a package documentation out of it. Suppose the document above is saved as worksheet.g. Then, when GAP is started in the directory of this file, the command  AutoDocWorksheet( "worksheet.g" );  will create a subdirectory called doc of the current directory in which it will create the documentation. There are several options to configure the output of the worksheet command, which are identical to the options of the AutoDoc (4.1-1) command. It is even possible to test the examples in the worksheet using the extract_examples option of the AutoDoc (4.1-1) command. Since the worksheets do not have a PackageInfo.g to extract information, all possible tags that GAPDoc supports for the title page can be set into the document. A fully typed title page can look like this:  #! @Title My first worksheet #! @Subtitle Some small examples #! @Author Charlie Brown  #! @Version 0.1 #! @TitleComment Some worksheet #! @Date 01/01/2016 #! @Address TU Kaiserslautern #! @Abstract #! A worksheet showing some small examples about groups. #! @Copyright 2016 Charlie Brown #! @Acknowledgements Woodstock #! @Colophon Some colophon  #! @Chapter Some groups  #! @BeginExample S3 := SymmetricGroup( 3 );; S4 := SymmetricGroup( 4 );; #! @EndExample  ���������������������������������������������������������������������������AutoDoc-2025.10.16/doc/Comments.xml�����������������������������������������������������������������0000644�0001751�0001751�00000063424�15074117054�016145� 0����������������������������������������������������������������������������������������������������ustar �runner��������������������������runner�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<Chapter Label="Comments"> <Heading>&AutoDoc; documentation comments</Heading> You can document declarations of global functions and variables, operations, attributes etc. by inserting <E>&AutoDoc;</E> comments into your sources before these declaration. An &AutoDoc; comment always starts with <C>#!</C>. This is also the smallest possible &AutoDoc; command. If you want your declaration documented, just write <C>#!</C> at the line before the documentation. For example: <Listing><![CDATA[ #! DeclareOperation( "AnOperation", [ IsList ] ); ]]></Listing> This will produce a manual entry for the operation <C>AnOperation</C>. <P/> Inside of &AutoDoc; comments, <E>&AutoDoc; commands</E> starting with <C>@</C> can be used to control the output &AutoDoc; produces. <Section> <Heading>Documenting declarations</Heading> In the bare form above, the manual entry for <C>AnOperation</C> will not contain much more than the name of the operation. In order to change this, there are several commands you can put into the &AutoDoc; comment before the declaration. Currently, the following commands are provided: <Subsection Label="@Description"> <Index Key="@Description"><C>@Description <A>descr</A></C></Index> <Heading><C>@Description <A>descr</A></C></Heading> Adds the text in the following lines of the &AutoDoc; to the description of the declaration in the manual. Lines are until the next &AutoDoc; command or until the declaration is reached. </Subsection> <Subsection Label="@Returns"> <Index Key="@Returns"><C>@Returns <A>ret_val</A></C></Index> <Heading><C>@Returns <A>ret_val</A></C></Heading> The string <A>ret_val</A> is added to the documentation, with the text <Q>Returns: </Q> put in front of it. This should usually give a brief hint about the type or meaning of the value returned by the documented function. </Subsection> <Subsection Label="@Arguments"> <Index Key="@Arguments"><C>@Arguments <A>args</A></C></Index> <Heading><C>@Arguments <A>args</A></C></Heading> The string <A>args</A> contains a description of the arguments the function expects, including optional parts, which are denoted by square brackets. The argument names can be separated by whitespace, commas or square brackets for the optional arguments, like <Q>grp[, elm]</Q> or <Q>xx[y[z] ]</Q>. If &GAP; options are used, this can be followed by a colon : and one or more assignments, like <Q>n[, r]: tries := 100</Q>. </Subsection> <Subsection Label="@Group"> <Index Key="@Group"><C>@Group <A>grpname</A></C></Index> <Heading><C>@Group <A>grpname</A></C></Heading> Adds the following method to a group with the given name. See section <Ref Sect="Groups"/> for more information about groups. </Subsection> <Subsection Label="@Label"> <Index Key="@Label"><C>@Label <A>label</A></C></Index> <Heading><C>@Label <A>label</A></C></Heading> Adds label to the function as label. If this is not specified, then for declarations that involve a list of input filters (as is the case for <C>DeclareOperation</C>, <C>DeclareAttribute</C>, etc.), a default label is generated from this filter list. </Subsection> <Listing><![CDATA[ #! @Label testlabel DeclareProperty( "AProperty", IsObject ); ]]></Listing> leads to this: <ManSection> <Prop Arg="arg" Name="AProperty" Label="testlabel"/> <Returns> <K>true</K> or <K>false</K> </Returns> <Description> </Description> </ManSection> while <Listing><![CDATA[ #! DeclareProperty( "AProperty", IsObject ); ]]></Listing> leads to this: <ManSection> <Prop Arg="arg" Name="AProperty" Label="for IsObject"/> <Returns> <K>true</K> or <K>false</K> </Returns> <Description> </Description> </ManSection> <Subsection Label="@ChapterInfo"> <Index Key="@ChapterInfo"><C>@ChapterInfo</C></Index> <Heading><C>@ChapterInfo <A>chapter</A>, <A>section</A></C></Heading> Adds the entry to the given chapter and section. Here, <A>chapter</A> and <A>section</A> are the respective titles. </Subsection> As an example, a full &AutoDoc; comment with all options could look like this: <Listing><![CDATA[ #! @Description #! Computes the list of lists of degrees of ordinary characters #! associated to the $p$-blocks of the group $G$ #! with $p$-modular character table <A>modtbl</A> #! and underlying ordinary character table `ordtbl`. #! @Returns a list #! @Arguments modtbl #! @Group CharacterDegreesOfBlocks #! @Label chardegblocks #! @ChapterInfo Blocks, Attributes DeclareAttribute( "CharacterDegreesOfBlocks", IsBrauerTable ); ]]></Listing> </Section> <Section> <Heading>Other documentation comments</Heading> There are also some commands which can be used in &AutoDoc; comments that are not associated to any declaration. This is useful for additional text in your documentation, examples, mathematical chapters, etc.. <Subsection Label="@Chapter"> <Index Key="@Chapter"><C>@Chapter</C></Index> <Index Key="@ChapterLabel"><C>@ChapterLabel</C></Index> <Index Key="@ChapterTitle"><C>@ChapterTitle</C></Index> <Heading><C>@Chapter <A>name</A></C></Heading> Sets the active chapter, all subsequent functions which do not have an explicit chapter declared in their &AutoDoc; comment via <C>@ChapterInfo</C> will be added to this chapter. Also all text comments, i.e. lines that begin with #! without a command, and which do not follow after <C>@Description</C>, will be added to the chapter as regular text. Additionally, the chapters label will be set to <C>Chapter_</C><A>name</A>. Example: <Listing><![CDATA[ #! @Chapter My chapter #! This is my chapter. #! I document my stuff in it. ]]></Listing> The <C>@ChapterLabel</C> <A>label</A> command can be used to set the label of the chapter to <C>Chapter_</C><A>label</A> instead of <C>Chapter_</C><A>name</A>. Additionally, the chapter will be stored as <C>_Chapter_</C><A>label</A><C>.xml</C>. The <C>@ChapterTitle</C> <A>title</A> command can be used to set a heading for the chapter that is different from <A>name</A>. Note that the title does not affect the label. If you use all three commands, i.e., <Listing><![CDATA[ #! @Chapter name #! @ChapterLabel label #! @ChapterTitle title ]]></Listing> <C>title</C> is used for the headline, <C>label</C> for cross-referencing, and <C>name</C> for setting the same chapter as active chapter again. </Subsection> <Subsection Label="@Section"> <Index Key="@Section"><C>@Section</C></Index> <Index Key="@SectionLabel"><C>@SectionLabel</C></Index> <Index Key="@SectionTitle"><C>@SectionTitle</C></Index> <Heading><C>@Section <A>name</A></C></Heading> Sets an active section like <C>@Chapter</C> sets an active chapter. The section automatically ends with the next <C>@Section</C> or <C>@Chapter</C> command. <Listing><![CDATA[ #! @Section My first manual section #! In this section I am going to document my first method. ]]></Listing> The <C>@SectionLabel</C> <A>label</A> command can be used to set the label of the section to <C>Section_</C><A>label</A> instead of <C>Chapter_chaptername_Section_</C><A>name</A>. The <C>@SectionTitle</C> <A>title</A> command can be used to set a heading for the section that is different from <A>name</A>. </Subsection> <Subsection Label="@Subsection"> <Index Key="@Subsection"><C>@Subsection</C></Index> <Index Key="@SubsectionLabel"><C>@SubsectionLabel</C></Index> <Index Key="@SubsectionTitle"><C>@SubsectionTitle</C></Index> <Heading><C>@Subsection <A>name</A></C></Heading> Sets an active subsection like <C>@Section</C> sets an active section. The subsection automatically ends with the next <C>@Subsection</C>, <C>@Section</C> or <C>@Chapter</C> command. It also ends with the next documented function. Indeed, internally each function <Q>manpage</Q> is treated like a subsection. <Listing><![CDATA[ #! @Subsection My first manual subsection #! In this subsection I am going to document my first example. ]]></Listing> The <C>@SubsectionLabel</C> <A>label</A> command can be used to set the label of the subsection to <C>Subsection_</C><A>label</A> instead of <C>Chapter_chaptername_Section_sectionname_Subsection_</C><A>name</A>. The <C>@SubsectionTitle</C> <A>title</A> command can be used to set a heading for the subsection that is different from <A>name</A>. </Subsection> <Subsection Label="@BeginGroup"> <Index Key="@BeginGroup"><C>@BeginGroup</C></Index> <Heading><C>@BeginGroup <A>[grpname]</A></C></Heading> Starts a group. All following documented declarations without an explicit <C>@Group</C> command are grouped together in the same group with the given name. If no name is given, then a new nameless group is generated. The effect of this command is ended when an <C>@EndGroup</C> command is reached. <P/> See section <Ref Sect="Groups"/> for more information about groups. </Subsection> <Subsection Label="@EndGroup"> <Index Key="@EndGroup"><C>@EndGroup</C></Index> <Heading><C>@EndGroup</C></Heading> Ends the current group. <Listing><![CDATA[ #! @BeginGroup MyGroup #! DeclareAttribute( "GroupedAttribute", IsList ); DeclareOperation( "NonGroupedOperation", [ IsObject ] ); #! DeclareOperation( "GroupedOperation", [ IsList, IsRubbish ] ); #! @EndGroup ]]></Listing> </Subsection> <Subsection Label="@GroupTitle"> <Index Key="@GroupTitle"><C>@GroupTitle</C></Index> <Heading>@GroupTitle <A>title</A></Heading> Sets the subsection heading for the current group to <A>title</A>. In the absence of any <C>@GroupTitle</C> command, the heading will be the name of the first entry in the group. See <Ref Sect="Groups" /> for more information. </Subsection> <Subsection Label="@Level"> <Index Key="@Level"><C>@Level</C></Index> <Heading><C>@Level <A>lvl</A></C></Heading> Sets the current level of the documentation. All items created after this, chapters, sections, and items, are given the level <A>lvl</A>, until the <C>@ResetLevel</C> command resets the level to 0 or another level is set. <P/> See section <Ref Sect="Level"/> for more information about levels. </Subsection> <Subsection Label="@ResetLevel"> <Index Key="@ResetLevel"><C>@ResetLevel</C></Index> <Heading><C>@ResetLevel</C></Heading> Resets the current level to 0. <P/> </Subsection> <Subsection Label="@BeginExample"> <Index Key="@BeginExample"><C>@BeginExample</C></Index> <Index Key="@EndExample"><C>@EndExample</C></Index> <Heading><C>@BeginExample</C> and <C>@EndExample</C></Heading> <C>@BeginExample</C> marks the start of an example to be put into the manual. It differs from &GAPDoc;'s <C><Example></C> (see <Ref Subsect="Log" BookName="gapdoc"/>), in that it expects actual code (not in a comment) interspersed with comments, to allow for examples files that can be both executed by &GAP;, and parsed by &AutoDoc;. To achieve this, &GAP; commands are not preceded by a comment, while output has to be preceded by an &AutoDoc; comment. The <C>gap></C> prompt for the display in the manual is added by &AutoDoc;. <C>@EndExample</C> ends the example block. <P/> To illustrate this command, consider this input: <Listing><![CDATA[ #! @BeginExample S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) Order(S5); #! 120 #! @EndExample ]]></Listing> This results in the following output: <Example> gap> S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Order(S5); 120 </Example> The &AutoDoc; command <C>@Example</C> is an alias of <C>@BeginExample</C>. </Subsection> <Subsection Label="@BeginExampleSession"> <Index Key="@BeginExampleSession"><C>@BeginExampleSession</C></Index> <Index Key="@EndExampleSession"><C>@EndExampleSession</C></Index> <Heading><C>@BeginExampleSession</C> and <C>@EndExampleSession</C></Heading> <C>@BeginExampleSession</C> marks the start of an example to be put into the manual, while <C>@EndExampleSession</C> ends the example block. It is the direct analog of &GAPDoc;'s <C><Example></C> (see <Ref Subsect="Log" BookName="gapdoc"/>). <P/> To illustrate this command, consider this input: <Listing><![CDATA[ #! @BeginExampleSession #! gap> S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) #! gap> Order(S5); #! 120 #! @EndExampleSession ]]></Listing> This results in the following output: <Example> gap> S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Order(S5); 120 </Example> It inserts an example into the manual just as <C>@Example</C> would do, but all lines are commented and therefore not executed when the file is read. All lines that should be part of the example displayed in the manual have to start with an &AutoDoc; comment (<C>#!</C>). The comment will be removed, and, if the following character is a space, this space will also be removed. There is never more than one space removed. To ensure examples are correctly colored in the manual, there should be exactly one space between <C>#!</C> and the <C>gap></C> prompt. The &AutoDoc; command <C>@ExampleSession</C> is an alias of <C>@BeginExampleSession</C>. </Subsection> <Subsection Label="@BeginLog"> <Index Key="@BeginLog"><C>@BeginLog</C></Index> <Index Key="@EndLog"><C>@EndLog</C></Index> <Heading><C>@BeginLog</C> and <C>@EndLog</C></Heading> Works just like the <C>@BeginExample</C> command, but the example will not be tested. See the &GAPDoc; manual for more information. The &AutoDoc; command <C>@Log</C> is an alias of <C>@BeginLog</C>. </Subsection> <Subsection Label="@BeginLogSession"> <Index Key="@BeginLogSession"><C>@BeginLogSession</C></Index> <Index Key="@EndLogSession"><C>@EndLogSession</C></Index> <Heading><C>@BeginLogSession</C> and <C>@EndLogSession</C></Heading> Works just like the <C>@BeginExampleSession</C> command, but the example will not be tested if manual examples are run. It is the direct analog of &GAPDoc;'s <C><Log></C> (see <Ref Subsect="Log" BookName="gapdoc"/>). The &AutoDoc; command <C>@LogSession</C> is an alias of <C>@BeginLogSession</C>. </Subsection> <Subsection Label="@DoNotReadRestOfFile"> <Index Key="@DoNotReadRestOfFile"><C>@DoNotReadRestOfFile</C></Index> <Heading><C>@DoNotReadRestOfFile</C></Heading> Prevents the rest of the file from being read by the parser. Useful for unfinished or temporary files. <Listing><![CDATA[ #! This will appear in the manual #! @DoNotReadRestOfFile #! This will not appear in the manual. ]]></Listing> </Subsection> <Subsection Label="@BeginChunk"> <Index Key="@BeginChunk"><C>@BeginChunk <A>name</A></C></Index> <Index Key="@EndChunk"><C>@EndChunk</C></Index> <Index Key="@EndChunk"><C>@InsertChunk <A>name</A></C></Index> <Heading><C>@BeginChunk <A>name</A></C>, <C>@EndChunk</C>, and <C>@InsertChunk <A>name</A></C></Heading> Text inside a <C>@BeginChunk</C> / <C>@EndChunk</C> part will not be inserted into the final documentation directly. Instead, the text is stored in an internal buffer. That chunk of text can then later on be inserted in any other place by using the <C>@InsertChunk <A>name</A></C> command. If you do not provide an <C>@EndChunk</C>, the chunk ends at the end of the file. <Listing><![CDATA[ #! @BeginChunk MyChunk #! Hello, world. #! @EndChunk #! @InsertChunk MyChunk ## The text "Hello, world." is inserted right before this. ]]></Listing> You can use this to define an example like this in one file: <Listing><![CDATA[ #! @BeginChunk Example_Symmetric_Group #! @BeginExample S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) Order(S5); #! 120 #! @EndExample #! @EndChunk ]]></Listing> And then later, insert the example in a different file, like this: <Listing><![CDATA[ #! @InsertChunk Example_Symmetric_Group ]]></Listing> </Subsection> <Subsection Label="@BeginCode"> <Index Key="@BeginCode"><C>@BeginCode <A>name</A></C></Index> <Index Key="@EndCode"><C>@EndCode</C></Index> <Index Key="@InsertCode"><C>@InsertCode <A>name</A></C></Index> <Heading><C>@BeginCode <A>name</A></C>, @EndCode, and <C>@InsertCode <A>name</A></C></Heading> Inserts the text between <C>@BeginCode</C> and <C>@EndCode</C> verbatim at the point where <C>@InsertCode</C> is called. This is useful to insert code excerpts directly into the manual. <Listing><![CDATA[ #! @BeginCode Increment i := i + 1; #! @EndCode #! @InsertCode Increment ## Code is inserted here. ]]></Listing> </Subsection> <Subsection Label="@LatexOnly"> <Index Key="@LatexOnly"><C>@LatexOnly <A>text</A></C></Index> <Index Key="@BeginLatexOnly"><C>@BeginLatexOnly</C></Index> <Index Key="@EndLatexOnly"><C>@EndLatexOnly</C></Index> <Heading><C>@LatexOnly <A>text</A></C>, <C>@BeginLatexOnly</C>, and <C>@EndLatexOnly</C></Heading> Code inserted between <C>@BeginLatexOnly</C> and <C>@EndLatexOnly</C> or after <C>@LatexOnly</C> is only inserted in the PDF version of the manual or worksheet. It can hold arbitrary &LaTeX;-commands. <Listing><![CDATA[ #! @BeginLatexOnly #! \include{picture.tex} #! @EndLatexOnly #! @LatexOnly \include{picture.tex} ]]></Listing> </Subsection> <Subsection Label="@NotLatex"> <Index Key="@NotLatex"><C>@NotLatex <A>text</A></C></Index> <Index Key="@BeginNotLatex"><C>@BeginNotLatex</C></Index> <Index Key="@EndNotLatex"><C>@EndNotLatex</C></Index> <Heading><C>@NotLatex <A>text</A></C>, <C>@BeginNotLatex</C>, and <C>@EndNotLatex</C></Heading> Code inserted between <C>@BeginNotLatex</C> and <C>@EndNotLatex</C> or after <C>@NotLatex</C> is inserted in the HTML and text versions of the manual or worksheet, but not in the PDF version. <Listing><![CDATA[ #! @BeginNotLatex #! For further information see the PDF version of this manual. #! @EndNotLatex #! @NotLatex For further information see the PDF version of this manual. ]]></Listing> </Subsection> </Section> <Section Label="TitlepageCommands"> <Heading>Title page commands</Heading> The following commands can be used to add the corresponding parts to the title page of the document which generated by &AutoDoc; if scaffolding is enabled. <List> <Item> <C>@Title</C> </Item> <Item> <C>@Subtitle</C> </Item> <Item> <C>@Version</C> </Item> <Item> <C>@TitleComment</C> </Item> <Item> <C>@Author</C> </Item> <Item> <C>@Date</C> </Item> <Item> <C>@Address</C> </Item> <Item> <C>@Abstract</C> </Item> <Item> <C>@Copyright</C> </Item> <Item> <C>@Acknowledgements</C> </Item> <Item> <C>@Colophon</C> </Item> </List> Those add the following lines at the corresponding point of the title page. Please note that many of those things can be (better) extracted from the <F>PackageInfo.g</F>. In case you set some of those, the extracted or in scaffold defined items will be overwritten. While this is not very useful for documenting packages, they are necessary for worksheets created with <Ref Func="AutoDocWorksheet"/>, since worksheets do not have a <F>PackageInfo.g</F> file from which this information could be extracted. </Section> <Section Label="PlainText"> <Heading>Plain text files</Heading> Files that have the suffix <C>.autodoc</C> and are listed in the <C>autodoc.files</C> option of <Ref Func="AutoDoc"/>, resp. are contained in one of the directories listed in <C>autodoc.scan_dirs</C>, are treated as &AutoDoc; plain text files. These work exactly like &AutoDoc; comments, except that lines do not need to (and in fact, should not) start with <C>#!</C>. </Section> <Section Label="Groups"> <Heading>Grouping</Heading> In &GAPDoc;, it is possible to make groups of manual items, i.e., when documenting a function, operation, etc., it is possible to group them into suitable chunks. This can be particularly useful if there are several definitions of an operation with several different argument types, all doing more or less the same to the arguments. Then their manual items can be grouped, sharing the same description and return type information. You can give a heading to the group in the manual with the <C>@GroupTitle</C> command; if that is not supplied, then the heading of the first manual item in the group will be used as the heading. <P/> Note that group names are globally unique throughout the whole manual. That is, groups with the same name are in fact merged into a single group, even if they were declared in different source files. Thus you can have multiple <C>@BeginGroup</C> / <C>@EndGroup</C> pairs using the same group name, in different places, and these all will refer to the same group. <P/> Moreover, this means that you can add items to a group via the <C>@Group</C> command in the &AutoDoc; comment of an arbitrary declaration, at any time. <P/> The following code <Listing><![CDATA[ #! @BeginGroup Group1 #! @GroupTitle A family of operations #! @Description #! First sentence. DeclareOperation( "FirstOperation", [ IsInt ] ); #! @Description #! Second sentence. DeclareOperation( "SecondOperation", [ IsInt, IsGroup ] ); #! @EndGroup ## .. Stuff .. #! @Description #! Third sentence. #! @Group Group1 KeyDependentOperation( "ThirdOperation", IsGroup, IsInt, "prime ); ]]></Listing> produces the following: <ManSection Label="Group1"> <Heading>A family of operations</Heading> <Oper Arg="arg" Name="FirstOperation" Label="for IsInt"/> <Oper Arg="arg1,arg2" Name="SecondOperation" Label="for IsInt, IsGroup"/> <Oper Arg="arg1,arg2" Name="ThirdOperation" Label="for IsGroup, IsInt"/> <Description> First sentence. Second sentence. Third sentence. </Description> </ManSection> </Section> <Section Label="Level"> <Heading>Level</Heading> Levels can be set to not write certain parts in the manual by default. Every entry has by default the level 0. The command <C>@Level</C> can be used to set the level of the following part to a higher level, for example 1, and prevent it from being printed to the manual by default. However, if one sets the level to a higher value in the autodoc option of &AutoDoc;, the parts will be included in the manual at the specific place. <Listing><![CDATA[ #! This text will be printed to the manual. #! @Level 1 #! This text will be printed to the manual if created with level 1 or higher. #! @Level 2 #! This text will be printed to the manual if created with level 2 or higher. #! @ResetLevel #! This text will be printed to the manual. ]]></Listing> </Section> <Section Label="MarkdownExtension"> <Heading>Markdown-like formatting of text in &AutoDoc;</Heading> &AutoDoc; has some convenient ways to insert special format into text, like math formulas and lists. The syntax for them are inspired by Markdown and &LaTeX;, but do not follow them strictly. Neither are all features of the Markdown language supported. The following subsections describe what is possible. <Subsection Label="MarkdownExtensionList"> <Heading>Lists</Heading> One can create lists of items by beginning a new line with *, +, -, followed by one space. The first item starts the list. When items are longer than one line, the following lines have to be indented by at least two spaces. The list ends when a line which does not start a new item is not indented by two spaces. Of course lists can be nested. Here is an example: <Listing><![CDATA[ #! The list starts in the next line #! * item 1 #! * item 2 #! which is a bit longer #! * and also contains a nested list #! * with two items #! * item 3 of the outer list #! This does not belong to the list anymore. ]]></Listing> This is the output:<Br/> The list starts in the next line <List> <Item> item 1 </Item> <Item> item 2 which is a bit longer <List> <Item> and also contains a nested list </Item> <Item> with two items </Item> </List> </Item> <Item> item 3 of the outer list </Item> </List> This does not belong to the list anymore.<Br/> The *, -, and + are fully interchangeable and can even be used mixed, but this is not recommended. </Subsection> <Subsection Label="MarkdownExtensionMath"> <Heading>Math modes</Heading> One can start an inline formula with a $, and also end it with $, just like in &LaTeX;. This will translate into &GAPDoc;s inline math environment. For display mode one can use $$, also like &LaTeX;. <Listing><![CDATA[ #! This is an inline formula: $1+1 = 2$. #! This is a display formula: #! $$ \sum_{i=1}^n i. $$ ]]></Listing> produces the following output:<Br/> This is an inline formula: <Math>1+1 = 2</Math>. This is a display formula: <Display> \sum_{i=1}^n i. </Display> </Subsection> <Subsection Label="MarkdownExtensionEmph"> <Heading>Emphasize</Heading> One can emphasize text by using two asterisks (**) or two underscores (__) at the beginning and the end of the text which should be emphasized. Example: <Listing><![CDATA[ #! **This** is very important. #! This is __also important__. #! **Naturally, more than one line #! can be important.** ]]></Listing> This produces the following output:<Br/> <E>This</E> is very important. This is <E>also important</E>. <E>Naturally, more than one line can be important.</E> </Subsection> <Subsection Label="MarkdownExtensionInlineCode"> <Heading>Inline code</Heading> One can mark inline code snippets by using backticks (`) at the beginning and the end of the text which should be marked as code. Example: <Listing><![CDATA[ #! Call function `foobar()` at the start. ]]></Listing> This produces the following output:<Br/> Call function <C>foobar()</C> at the start. </Subsection> </Section> <Section Label="Deprecated"> <Heading>Deprecated commands</Heading> The following commands used to be supported, but are not anymore. <List> <Mark><C>@EndSection</C></Mark> <Item>You can simply remove any use of this, &AutoDoc; ends sections automatically at the start of any new section or chapter.</Item> <Mark><C>@EndSubsection</C></Mark> <Item>You can simply remove any use of this, &AutoDoc; ends subsections automatically at the start of any new subsection, section or chapter.</Item> <Mark><C>@BeginAutoDoc</C> and <C>@EndAutoDoc</C></Mark> <Item>It suffices to prepend each declaration that is meant to be appear in the manual with a minimal &AutoDoc; comment <C>#!</C>.</Item> <Mark><C>@BeginSystem <A>name</A></C>, <C>@EndSystem</C>, and <C>@InsertSystem <A>name</A></C></Mark> <Item>Please use the chunk commands from subsection <Ref Subsect="@BeginChunk"/> instead.</Item> <Mark><C>@AutoDocPlainText</C> and <C>@EndAutoDocPlainText</C></Mark> <Item>Use <C>.autodoc</C> files or &AutoDoc; comments instead.</Item> </List> </Section> </Chapter> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������AutoDoc-2025.10.16/doc/lefttoc.css������������������������������������������������������������������0000644�0001751�0001751�00000000474�15074117054�016004� 0����������������������������������������������������������������������������������������������������ustar �runner��������������������������runner�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* leftmenu.css Frank Lübeck */ /* Change default CSS to show section menu on left side */ body { padding-left: 28%; } body.chap0 { padding-left: 2%; } div.ChapSects div.ContSect:hover div.ContSSBlock { left: 15%; } div.ChapSects { left: 1%; width: 25%; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������AutoDoc-2025.10.16/doc/manual.pdf�������������������������������������������������������������������0000644�0001751�0001751�00001006644�15074117054�015610� 0����������������������������������������������������������������������������������������������������ustar �runner��������������������������runner�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%PDF-1.5 % 97 0 obj << /Length 738 /Filter /FlateDecode >> stream xڵVMS0+|tV-t0m2҃bئ\ߕ !ô)<|7=_4)҄hQDR*їt$pܹF_ʑҊ$b%lc%:J[9㊺ G͈.C5A61*Z;1)f(Me!r6@gun -$jSRFD[SƂ4Q ҩك|\=Mˬ\])OBڙi]aL:fg)3E\WgMWk�mxOlP׀Nc(`i;/M<qG(|Q3n&^KzLWty<)%$^Xx)*s[ܟۀ5d(E.7c"W,=Yz2s;k lm0hycx85f/�Aw\x!ئ-=|H-?}:21|ilmM"쐈@z~D\515Xbls{{)AkS^WET'ͣ됗Y~7xn' }l^+^Sps"[,{ӛ]`4(!@-OhtAvp*vnY$Fa`3S˝zg@ ~vL/b8O~p+ endstream endobj 108 0 obj << /Length 612 /Filter /FlateDecode >> stream xڝTMs Wp&GtLU{IrBP]N=>} f79CTπ03D+08U`;]OǛ%%�#,ĎmDH99x< (²}[#jC^/@`N$4Cɫfvte"&hq :#W 6C ӉEld<lun0]sIciLDwu1ح6jCHaU ^ֺ<cWs94:zK* E~P0bsA"[l_H($r,O')$,A1ȵhcڴA+.Vڎf#t1hmN[ل6~9+>2\PQފ8E!;UVղ#[1NGC}D.V@=" *mםߊ'RL(NXq}:TY/N1J;lo&zD섑ݡB.ow~!Q׉ϫ[w{_L{W}5 dr endstream endobj 140 0 obj << /Length 991 /Filter /FlateDecode >> stream xYMs0Wh,@a8�4&vqh>r,qiBs(Ȼ5. N_O^3�CRI ǁS&e*<+MV.'q΂2<M4+8C0Fpe"q80e9.8eRfT_,}k9'$X+oml.ԍanpX73*Ą"ΚMA{o]$wu^%'2E>w;IN<7zB(yLk;uրlpjUWt"X-Ar3-'5aE#4ngF>"侐Djdy,�])Rjx0f4s׍&"<.}c./Ay.xy9s@xs�0C<H%MpF -L/ëSwd8bbLeŎp!m*X)lq'B`mgWpze)ˑKVgYsNiRu^.td3:oβ;(ATBxaDy8-g)z&/"]<�>B w1K]֊~` 3A(vEvoG~Ug(dG({L>Iq5+oZk.%jym}ΘMBq^̓^r>ޖH<A ͟Yn+B5Zl{S¤I/a/T[}Rz|9x{Z4 f=뼤^H�1Qyۗ3Jwۇ0)tʼ:Z?M#.+.t\UqVj&^`T?E~lƦ M6�Ɏw>졫 4TńDZNw O~L endstream endobj 153 0 obj << /Length 2330 /Filter /FlateDecode >> stream xڭYKsWt Xeé8**)@P@ �.� 1J~~= \ql~əI=]N|i'Lpr|qޥѺILjq'??_Y._ S>! "~WId=񫛨j}ljK- d8\LLneLX旞BevL+掮K\n7L ߉hꐻWzuq=Oz ;~(~bM8WsVIT4DjJu\,_{iҲeWID1Sh7=Z'3vmUi҄-xJ`aK9YE$+Tͦ3=cȦ±f#5"kz7,_D߬mP)2x==?b6|IZ<@ɄR.muv>n>ZPǺIV@sY|/ad`^_*zo3WJ2'2;TѣJy'I$βƬ;T;bc\ �*?Z؉:72D#EM01jzw:ۄ~TjgkWOzT؇ RO(9 j?f\\fUݠ<٩L!$ A<d$6Н|!gbiܳζʚ^#zIoZGM*W4qJ ?6M0!JJBt �POÙ+{ӆhwI|\64bC}nthy7v(DM#$Z`)@Rʮf5&)gړ�A b|?h)՟ ZtI�Q1^@dSGzx Y(^v %)z+WD&krKY۔q86iҊ׊?p3!�16s\ 3OeVDy8t ISxݷiԌ[c'{m۩NY=iHTxUtDHP:R'p3L[kvy\ι󮚊i N\G (�+f.nJ~@6G(;xAfml@6EbCU;aN]Ҕ%?[QMԢ$B3ŵEy+ǑT:[VHI ۄ)UJU,|4B SW;cʢyau'#/D&`ثsqlJ< |En<{@'YC=rK{LJqPӍ^o3}>X3ecqU+eHhtER)WxeDŽ s&1۳ph[d& 7>Y!Sa0ٚ+#瓛x(.Y�z7p1|"aUBЎBD ڲˇ`B-=A+m&*u2e9OaH2롿Z%OPcA྆?�V9a` E"ۿѳ6Nd FX�} ,l!/qpd%]Wda |b;  �\!<, �L ttxSUpr*J(ʰcCsj(nQkݕ-e{au @+|ː ^b9CPD+ˇma/w )fu%,b<2v**`J ՅeL<,5e<_xϋ*pk6#ۘ)>^t.n+.{-E*W ¥P#ZxϾxWŮ\l⽻%dm |rhkwa:=f2gaP@=SGZͤ&I&tH;&*fpVFnh䕖<EpzVh*bb vh^Ii/W9NҬ{,m#iy2`_V=)_pRE+V5jp]胢],ANP'+E:AmAS Oe9_Fb#,ۡzPPzDŽo}vQiGOIs~' wS>Po~ o�4<YC %Ա^`܅ ۻ byT;TSz `j~<C:qT%w.. hzdS endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 825 /Length 2350 /Filter /FlateDecode >> stream xZs6~_$3,~x:uK.3'vKȌ-$Naђ(br . P R H˜ ֒$lpB[:Q$"Y#RCRТ Z&2X,(}8IQhuX=G dS( sМq-ߏPL5z �A}"@_p�/�} xPH "p14-F`"aHJ70 \"A. X „d`l8q;AAA:8Ili C9 t*Iw?G$<{а!a: #C³_ʹfyRWO/DD xǚ?x 5T`,߁8`~ C2LX\Ywb0;ԆVDk- 10 bd8)z\$FvBh ' X;{v ~pp cQLEF] or&K㏃g';>|ȧ IY< 0˗gˢ,Aa5L&^ a^t"Ax k$勛|gć|yދ^&}y,%Z6eqq/Y,Ψ'0ʏ 6?Wky:ʲ胆[wa~mVz1u]氫8ΪL_rW[.nUxorD3 vX>ݘPHG>]qttӬK8{CSk£u\c÷=ߙxMZ8i' uӑyγxQSj'jeJ mEɺTUd0泫.aUǯm^yuY>lq.W z늩i~|ٓqC(fv,GKoZ3Ӭb<@:'mPOZ8մzՋѺtrMn{0fkilj]~Ҟ-6-պDM໠\QDv\AqM)y9(^O'U9Ňr>]F圫ίxx 9ij-eLAQ{'~8L#W5ằwA K̠y:;+gu7Gx ԣkT(TRVrylZ@x8<8{(kCop|UMVj>(V%Kr"ʗ�L(Q*ݱ^TPWPnz?b̍}uLqMp0JI&?nE/d@ \23:(cZVgQNl96 xdALWW$$TlE ϷTTQ 8Qwl::.a 8)VQPk`xռkWXn j7lvʎ%ҒaZ7yI Ih!w(Vr*ã7Q|;i;-͒L$ɈvYloiL#9Z!=ɡkvwmltմiMRڦuM3>3>jQ}F5Ga?5Ӓp!hxS:Ʉ9dz6{ALٰI1(i"!UG\�.AoaAt R[XJZ xa?O^r[pqh$հoQ$:1JMg`X4"T9dIF~-;aAXX+5%_6 "MbRCn5˫\@ oXj"FdX+gCjP߇y%#h)F X19Df ; JQ2E*8=fY z&*F|]+!̻6u'C,$v@5Ng2֯zP#~!X?b:8$isaͫQ*͟(0;x1R^pL)Tont0H 3j/(\ڵD,[%X+`NY٦Mc6%mJ(۔PN%w_ |dQB;rۘ90k^r:;XG0ܼH^TW/(JP7 @D(W6XeN9 KQN߯\A eKLimW4PZL8 +dQ@:g^0^o�4rȡxE̛bvxdy%ڑW7:]daq$ OtJK {m&@ endstream endobj 167 0 obj << /Length 2889 /Filter /FlateDecode >> stream xZ[۸~_E%.& mL<hdz,yud^{)[00ER~#5|r;7Wz:1D)S\OHTcWu>tZNg)OiR,Mfgjs?\_~c|{D,V,$_]}'sq™Jɝٰ֓rg2L&)K#ᦂs֊S.LgZ_C?ñV\Z$L y|n){"d<ukqLݗ ;O{+ R| vB([! %|~tEI" bɺ̺ڧYhqsvkAU=eR#UQA|.[XeUl:0xiE,JƍYmWޣAP`Sf3`Q7PhL%gec=u˺/4U=Д5ޢV`v(Zޯݫҽ9Ϻ̿G=ֺ1RޓnĊ$�UQ\/ VQe?7sRw.T V ��ae*t`@EpzVi,7źی lgBo3'HFHWEY-]d/8_PteVa⨵=vыTRDܰ[͍ɳ5c%ufycZ'#4go-yИCnhNػmvȳEj-GjA,ԕ׫y '0TR,Qʆ<+粴wEyxET�%a4+W|~z 6t–U~ \,zDt'欩 D (RBҜ;ӸVUkd7 AYЀtS3T8erHZBQ>P.p3Y/ 3+/ycOe>ݛ}P@4Khe ؽ@}4 ˦"(I-j s@'!LY[/Դ`c7bXzyj&]Dmg /u0[[5>ښ:0A?k% a46Rشcʬmi<Bm|Bb~q@,*xڂ csv@l !< \&6fa%yGR ZHL*^c3*ڮ)\&Ėeۯ(m9 CD!YR}0S&IJ*5 7v5�xiNɸ7WeԈn ~Qja{mߥg\vӵ3�8Rdg0#G.z(ls2Ďּ#VRqJpS\vo%$̝]Eif(XGx"=XܴC8F[P/0(J@cv* m2*j/U#^L/J3PVp@5wy8f'GȄ%Ir"^dÙ/trb+xAW^(RJDc kQqS)R&;rUmq'(tLT;z,!bt!N?KDP'<_Vg KS샊Ղ4 O69 @Nv¼ϋ) Y"CkNsUɎ=8XD{k'0Z 85!v@a?l. p 9<a4,fT 5@|g!A`Q%Uc<lf+/F@}_p6k(.m2] ȁ8v%:dQ]r* 8S{l#Ha=8??|uZ4ơ4G`4zj 4}lTN`8&ع>&K.gYKx܀%"^C#wdAk $VbQhX4jgCoYT.7E3apX^]8&̵u/;$=+.oJ< a*g-"RotKx!"�H]"Um&Lр} ,ólKȂXx,ODV2b"dP2n>&ܝ`|8&fT$ 8 |~f=,qD<"QW5)TR{W1k3~۰>xtK܍#Pdny "t `!ۭ-RRTi̪CX9/<;X.9N5j`{H,= < �{#.͌%0<]Z!9p^@/%dl{0aDxr$ˬ1x\P'uSʚtORGy۾woQt}XEX'v"QJI6G{ si Ќx;~1*baھqۏ: tw [vrН P%R[H_lѳw?o'|vMnjw;<h}s/kz A|K,sR% `o X-Esk9TKy]}y_Nf_X0%'Bo*Npa?BeAi?KuDW%/2YnL@U ^Z{e;'KPW.78IwEi\MʙN݋m6{{vDeWt Lt}3σo_CX.GX?u endstream endobj 174 0 obj << /Length 2882 /Filter /FlateDecode >> stream xڭZms۸_I31/3n/N^nƝi'wӡ)Dv�)J#E`�bB<xon",nSHT<<*-YSK\pG> Ub-+Yits)/d2|Yꪻ_4y]lڢ*iZдecQ#ܜyXƬʄiYT|vxcaB*֦lZHl2YcUmF\WB1DEN5l x@ZA} l?c1X:ͦL ,gR<ZjSRk~J"LY!j^wfQn;\klZƵڥ4 M& lc+'nj%$nȎr&2 {l:M֚K;Rit]bWZ% FpZK9-Y"%I|{fVx(V+Z$ {oJS:F<4ߒtz'XjH*[d6Jc7'ykEWx V_m/isJ(W*DgJ __|sxLI`g) ګſh(.FbdDL=AaGA*!�|Z?N>L,CFC)XYTeY[v+fpI_`! R^&Ofq�+}]%BNlu<[nT4/lμ|b'c)Y;o�%: r?Yw'3G %0' PzBJpVc7T3M)*tH,# XMB8eZ׿]�tAa�,Y׸/B!8b#uv(EE@ K0#=3Dm"� =F؉,"0W!�G/ `0[ >h8:L y }]ҋuۥ(>dqF�0 ͼhiA$2ٕW�'j S“"m;`O@ܘ64VEi`:G"܀s$<`:MaŻNzC$t!͇-47ʰk^a{:[뉄8KOk!PpUҘ$O�eV[ٝ.mVYnЇѵJl)Ocӊ;>#J%y#,jcl8 mz|^ ,dayȻ_)}Tܮpy zJpQ+ahB"@g@?zB".0pP\Χ4Xw-uLR5hu!fE06N4\AYVʵ7 E2u[n %艅 $DmP6>2vv Y`fCi[;BKnQw`NJQryC` n }֪Sx]ZC"q'EfU/DIvd*DP40y{a$< Pg"Ji,R±RF`I43>sd}`_"eIrVw o}@!Jp*"d*6*!B{", ?C]Ui<|DWOiEf⍗)oC_8k`]uW2 x ArV`~CSj I+IZmi|+i:e"MZ-ǛBpEc\k]/[Z8URnoDZ5X&^GcLE0s~ MaT_bKЬXLJ R1F*&a֮&~,(еKݒ@\aNᓁ9Gz[)pj_h�lzNh[+C#vrvZ6gfhG['l[I+ P5u*dԱR A3+xʹ ̦ZSٞ2iͼ:Ghx-Nqu*?&O)HEc;^vc[ڼIVq+wbS* Z "DL%Nck&tLعlW5 nK+$2^qX{Y.M(oQn}qVRׇopk9_ڝ,z3эP|<; E^9T¸׋Z5QO<nfq$6@ |$m@>Wb7>.{ƒ|Ekdx0L֒+wxZ}-|2VBVXqX`_ӣ߅٤ CYzչ 6-.Uع^O ;6/|Glƒ&Xŷʮ^! Z_pΛ^1Sb!{9EG$p7C5^L$M9-s/&饐lr ?\.J/��R5:l%4?[IN#4Տ7?_xþWSl' )vWpfׯ~TiFjypS!#q[}@;7/A2p\PّֆT LzXOTk{'UԼsqAlpԇ?}LD 5ʦH$Q{!CMd jH"0 Hǿw1uKK[7}NO D0Վ"ryWYWgL( ~Pdj];:]JϳIL"(}k'p?Sg S?>?�E_ endstream endobj 181 0 obj << /Length 2711 /Filter /FlateDecode >> stream xڭZo8_a{tv5n^Q6*[^I6͐,[~BSp~3aDGgo.k6(ݏxdjiF j]oo1J 5~ 9B M"FBX+BQ:˪Hb\=Z! S|(O?E=qkbt*}Kls]vYeOץ-[0&D;n}ewػ|K(JψmF.E{Qx7;gw%Ԣf 8dZd Sc" [Sɻ?PT 1]g6Dxݭ\8EM6=w4Gu hC4舃b+;DDHR`p* $Ȁq3px>cm ( sy}N9(|UWq0] 1'E^[[]'+@!ATw4_5\5>_W  WNMAt!1)J&O3Dnۈ_z8+XB 0DW(=S{9H+G ?+s+AN $) -Î )2DEA\>$+Tea j0G]PL*i@h.5.(4>"Zh6ZgIt(~O#e +bb?7IΞ4.(&,:T Ս6d\/+aUg.0-II�y8u0]ZN>mH x�TPnӃ83ũ$9rFoo8.D]vrs3H7,U>gp T:U -d@_!PD9?q0]T2)@8xHHw)FibB};oU[϶:5>B#}ʗus9bM j¹IkWKfiKD?v0]qhQA"4l8LAui[j) yr !zL*1™URT D1ryW-c2[SrlL|0lO~:?O]{}q}]V 3w\'$zn^]qP$EiV̓"2 |BĎ^a0-/¿$a&Gl$^:K~Ya>x2"L7/ TV�akYzEhy>:Ei`G t�Yx1UZ 9{<B =_fuh _ik*)xNŏEvIA")rI?O"0!ISa@6Fk.$^EN%N23}nm?&mK݈eG"J' B18u$tW=8xj<ǫ_yuwprQK8ӢyGCs4Q,Y=e'M0h!|s׶AWP.{]=k|}S0*wCvu$Y홃WѯWUp0)ucbtO o}g.!&rs*!b]k� -"H?Uڂy [@p&dO}H4g@6\:2A{'{eOI6;:($|}[-gD W<??]>_0J)^9U._Ā=Ok с1CWY[[편Y$hWy/l.lmY8s{n0hԟdk =Lk N)2 .mMZ'7 "y]EධhN Y@SH { RA338[+o׫U^b FĹ;[*u:N_: ;">S/&, aϙ%X Je6|h4bAJ%H.mMf X@zG,4h]16DMs|چ4ڕ[ueע$crB.Gz]6:|GN%܅G&G g?*:DŶI:=pILOg|12 X$HVslr2BoIl8Ac"#+!>IЩrEn*q7y4I v䗷|_`р^ 7Ml-%MŒy*B s"^*D횣uI´*{ZW Lco6=!@uNWԱNW 1Wxy׆Aɛg8d2T_,LJ賶ݧUCŚ߀#,7Rzy~,!@%HdVF6]f4$OяVsX]q(\t4]h:$}Z3ɺ1-Cc!u=זR/|I~ԧœqN(~+X]@&oM+Nz~"2�f|H`\. \VFP˝r|=[mR6}r _+ Ӵ B u*d|CP?Ԣa endstream endobj 189 0 obj << /Length 2872 /Filter /FlateDecode >> stream xZ[~_!ٹ"n m( '0"wE"U̅wW p8<3,]<._nnlaHb([=,Ija4# l)zw?Qĭ$1jvekn'o](&\Ƌt$^|+ q#rks8s$ob$B8cR5RU0Ds H`=0ItQt%}̗+F]||S _XM#q0 7BO20&=< shpr]h:}r?ovNz߬ odb̈T~{^@{N*)9`=t)bFG,Q_@( ҲݨO]Y͔EGR^->h]W]dQQգ~tWz\I&bqeFyڬ7y& uL�Y'4ˊ\Ѩ/NCYIעM ~uW7E޾; bf.Khە_d'ars PB"G<3B J 5y6]}vSd`^'1`zX4R4Ifı+@t?K--fP`;75%z]]Zei2&l|N9DS "Kz*�CݸA Gi&K,j >1_\p޺3i p?ȕ-Xd0l0VwF܋&/1pRwKJm 6O'/>aDfʼݟhV{FTurġϕ?ik-GR-/PdhI'GbYÁm]Bzy532Yg88zDύP+''`f|*^K [EY->cHdX˴)ܛ}?KxpsO6tc03k'~٫=sө~tis:H�mkdtV:gt"$Z}C'JCE]jҦWxV*"#Q*QIm_c~g w )cm7B$aQQ9`&Cs֠a�Z7 [3}Usd�=1^[MAF%1Nj3E8<X[�Rr<.p%oR;y'@+a gql=07m7C4` RC-8uDu JBEgC@WRE΍L?Gm6; ݌@4`=JW蹺sJJ8$w�}W}}p93t#>>2d\Xf\Dħg2VDPj%KcBfW3^~c.5#:I¥Vm豟]Mp7.+^.ca*Z;|(ƮSTHF!'&E "!\g`LdE{pnh`0rA51ՁpSCAĄ~)N/EKZ]'�AJO](_|#&EbJJi(fgQ\3.)x 9LBx#Z@3F9<f+F)/m SXKʪyv]_l!z1eB1"5 n(xv0�KzsRPPya%m)Bp[#z>}BoB7׺H@*?GoƢ%sPo$A0Z,s{U6Ka<͞ymlI?hmYMЗign  iiv=X5hca=LoS(%}$Zqyl 6Uơ߃嫛 {-Xڹ i͵oK3D^i6:j}ɡ&n ,mꮰw3xS ng-CoЍ!AEf; 91S(M0Ck ES^>cze<t)/)ڈlb@+2?%lr9ci_vfu5n6aŋ׮"ඵW LI0Z{/;l?cu<>]ۧ)=|0:`y qrWK�DLF l M7X@ˍsr깈Ԡ39Cl 1߰t(Λ*/اr/=v E275qNSCӒa2;pښ+RCx^m`bq+ whH| $"XZqusyQئ 1wz:853l uYz%68c4ϯ]z<lan>n:`E3_B-PB>ϔ;ފٿxa2��Qu@LlKھ=251Į46,z+9 όM@ 6\xWIN3nTXtHY^,q{7ڢlLb<+,Y)+>⓲ UKplVXIaPxLNm.u6f vn=:A?` ƙ=dB'obY9|/HOćop endstream endobj 196 0 obj << /Length 3222 /Filter /FlateDecode >> stream xڭr6_KX0@�۝6N6zOMJ$nhR+Rz:= u;ŀ^e$1Kc.ALr=#Rx//_p 8KyJdi"�93nKn4idB$oa|8a<Zj|FAŬ! 䴓cRLʢ^rzs=Xyv)a_~hÑq7sa+/|KSؽa^_QU/H 0$di^i|`^3/(XM~1uA>+@L (@D]Wٝ]sz9bW|cV|W[q Ғpʇ0=bQ!d#;#=ti+vU<Ek<!X"ҏe&{�*K"E7h 1`.ƱfQsM?d 8FQl W2pUz̴D:V2bQwuv-8{\z=㏵tIPly%V3SE"_BS/;8}EYJ� &6z1!xքa4dJX}e1}̎wѮTyi,u4 ؃ {N8q؛H+e\b~[ܢ+<u<玺>'M& ; 2rOȊ 5.eiuzzE�z^eXt/PxUXm#1͓^r0`Xvg91cÔ*oBK>d7? _f}C+"T uDubs3Z5=Wz0>?Bpdb30w%Ͻ� ᮸ɸ\+:C.U00i9!!{/|b)!aw5{ EX*L a=v?VC�U?0SQ͋(pq cwCq0JBBXPʁx\Ի~i΃73E[txKf ȯy$z,PLH% bPHzJ%…cvǩ.n~xw?y1Z-.7A&+ f eteiZYj58-:;hjAy6@_GYϚJMO:� ڀ;3lie(5UE[hGeRn0~uf+PXjka~غRЖ꓌[|c%}=!V* vJ<<_w^+0Һ5+IѽsB,f44fVcX#0u/`Ź'\UY-w<R?_{ IHu s6_g%1uUal-a], Иb@Y,^H : WG (hBøl<Pe>[wW[~CtofА88h${h _AEَ�FE&mYC:C4^c]<H]} m3dHr;ddD_js]/:p>h!Ӫ)!}*RLE|xA.F艐mjvIAg{^-,GmIǟqJ mi + ;:$Ñ&gͻ:?pS<Y,(~#Q׈nV" ۄqߌF %£Y0גT,a8#kv!l7μxxQ{Ӳ`a?>6lwSΒcr�1\0.5 픲kb-pÖ́n paUR6=�Ҿ㛪pd} 3³' p"x2(o%q㍏gs4dzמ?j#czݴp4 _3LE7A#6ȔBwt71\j @Xӑ7NX) v!Eӆ[,b,LԎKq)/Cg^m n.xf(#f;8G|)\lP)-/um$2  cɡT(=L2^ wa]*^ 5Lp`(% R 6nʴCʫdgVhDNTd(x9*S_JS9sڵE tܾ9ꘕ@2m1RkWK "4̘eշێ%DY4mCECƌJܠ)jd$ 2e Q.u4Uu2uYQS%z\٦]4X+a{`i,Vn'+S 93$)@(I [<ىVӔ8 [n7jZ@GN2zLY[&N&�bc/T [$X͇WIZHeK3^Ûa<7Y"Lz: F7]k+{#}eP Qz8k a 4_6c eBQYX4 vЯK{̦DoƈR* M vͬ"˼\Y\5ёW ,ֹw"hVJmsMsA( ͸;Ms^̮ʢ3؝iP2FV-~g sxBc1ޝ;7P71ɻn; C@, @V]!OE |8I hp ,"KNClAAqIhp>AbqEOD 82b G"`# i:d+L9IʸzacK..{}'Std 韅/@K cI^~s~ ۹9 6L!2'⦋=_\ش)&L!Lj,(I&^zo:˥7_!bɔ2/c0\L/mG|2|Bϣ0Q8%y)>L<L lF (ErY endstream endobj 205 0 obj << /Length 2550 /Filter /FlateDecode >> stream xڭZY~_K* J(edk,.a�ëcːZ {=}M7 7y>^Sqqő Riۅ7ߚ|oއʓ"HEJ T]).ߛO#o BZfBdl/{|~]_V{Qig2 ~W4j_]A$ޫ+ fs^n=-_4EWy2Ǯ=xUMUzYE֗=Z,0:MJZo։_5m?E,JئIdOX_WqW;z7`H##~Sy3#͔~2UNS˳(jmToVMDz,h"8g 4Dd00`h%YM;~U_=F뻬mT;F=`X~[6~lZjӾ+[Яe@?ڢ~Pߘb6J`2_0 !K;2tق޲Kq-PFY5dw@uAQxc=Lre>⑱3]C)tU,=mrPАHCN!)E; <ew3|77B&, h ڳ}z47|SDK;DY6+fRҌe=aeeNŎrp9 ?Q�lc::Pq1'Կ]QpOeSU9&Y.:",zd_evA*Tȇ%3=HGlsd;!!t 'GF2P)()vX_K솕7HckH$W͗[@`W=%\XV+OZ((eL@ ZS<4I82KXam$H4RZ> bbwdOJ_y%dH I!N<_C- UL s9 M~tyDex.OG'keVu<FLv&!…$:/`g9(`Kq{#uN2-Jo;0tG$ %I}3XdaY!q1<3ӨyIO i>:ZEa.,%Q[?>%6YۗPe`L( 9zTe^ <հ( NPD/W)e۬:+Y &2x|wȩO┍uaCcFbHر[3o,֠K*NmD2HɭG⠩զ ǚvbR 8 }WaNW5)H@y+s d WڡyŒ !jƱ0_c!wGfL[]P�zt r?81A,tz'Gd IWHb RQBVFj)S(�6~�ɏp2[OЗjU<snv,ͭERN =Q?U3HˁRe1t,&@Jԑ_:;MF$ $Q fl%iy ~9Ep%hS}Q=qYsA?m2<{J{bPJ46peX V!%`N&WxN M5ԩ΋tř|Xbw >|:cqrt⤜83(R#Gn�t 3EAĞᒻojzj XmJ =H˅ީʎ 5V:[طҘ;Z[zZ.^hɞ[<Ʉ5b-}YƼ` /B JKTblΘgKx#X( R+y0!Uz>r#/I bJaޟn<$2H IVOA=3ݳESU׬eN<,-.@WLV%"0!V%?{C#c^|ڊLj8#ô( _KrUt4.ENJظfMG4~B&}zv⾎qo7)@$a4N|Edcު^`/ھ d ws[ٖCKqnj{gEKQs:<:׳[گ(e2DI _vxo^`Εp<nWz6D`h{u~ ȗs c_.lU`xN9>$upȍ-yS%~FBdd(!; g`in㛦as7!;d42 pʝnXey uvϫ D' Q"pޮ\ƭ+=m?ޢGY/t~64\FQ`!gqyIׯo'Qi fqOX endstream endobj 217 0 obj << /Length 2561 /Filter /FlateDecode >> stream xZY۸~_l^* c7Iwu9dJq(2E*$eק RDkf n9<X<xwH1Kc.@3qđ`"%|u>o g)OiLJ!p[jgi̕aId?mڢFlN6U0`~|*\r㶵 v~beIMKu$ʟ6J[ڵ<vEWzr-3 wE:ZvMQ-${ۣ՞Sc7Z;ԑEq0>|dZ~ʙF2-N|Ŵ`Y`Ҭ Ϝ:zDxfgq}Iou>mm!aE Vu3iD߼:J⛌pHY~s7ť 1yDOpx>\QmGŔ͢'t[j̾{F[3mp^|Lub~e 1mή7#|X03&`Ԍ|iU۬dQj4pݔfjL}53k") 5Y\'1^$ $^n-;['k,x>I~<@G�-F(aZI,R1ֶDw#o'jNK_uݮ\gD~xTVy|DewV>;=Y,bbf((1"|tUDXzGц3mnI]uM]kζyv~v[ gJ|mݬ{7>b" z A$ؼĹ̳mn|@q K/EbO[\'^3$޹< "#x7%H+Q]?dKB^՛Xh4q1D#e^$b!p(@X; $#bTbow8$# lI%Hk rAh8錆3u_K$|e^۳2"pF}~ ҄1�zʄE:91DZgzӺt=`490GRg]�2R^fC}]iKD&x�� }r?)%PIeY?.4RLjg JѻuiBabS k(px-'W�aƮ2[GsKDI+)`04L̗J'b ɚl=WسlgSP=e+�Fj$p@1Пix`foBh*Dh_,�4WEĴP)*xsN[GC[7ە`\ K� a 8t\ɘTq&h㰈�(;p@Eo=d=*$am[8V�ܺ2>Q%Er?SW[ځpnm΄aEֵgҶu^}�~ѣ> ` 5ʕz$ oޖU&TWWd\#�/U I*|}˯<Xm[0,qW2xKeL@ *J9<T' e XBi-sR,\[ JK Y2oX0q`EwO$wp=-婢x:DQB #E@VYS^ W3=ZS6 b\CB̐D ݸO7A*M{ʏT=EVC�|I̩<K,7X5Шt6E9&1PSh#�y;GE|G-wpWv{jDg4~NJIO1 6~5֏j !OsƑ197 3z<ZS=L!/)9D�pjnКc3ïD}ȼ,2pW+úB@̅H(B2>Ճeϯ,գ5S=; ʨ*' ?n7�OHx솺PISc{p\..l9٫g:^ ۜJSKt'a͠HjWѸGؼ;ztU9g}kʄm(_ gs4eaiĔs_4$OET2! 3}?)gPUzuE}Aiҥܫc�g eO;MۛoYYn,RCvXL795ʡ_9rEG[oz@b":Wepm0 Ș=YYyJ+7p-v婃G}:Š#^T)rGO[ӥC˽ƯTz ՘8+P@* (hb-8%+KA"AvG=/3;L|ϫԊŐN;Կ@z n endstream endobj 222 0 obj << /Length 1178 /Filter /FlateDecode >> stream xڭ]6+\Hƻ[UjbL$(S ο1TH9jvQQф=bZaCņ ڠ/Xv=tQ2D 6b&9XGRHc-K\PI?6| ]8) l/wq\kf+EsFT"/ʐ碨XKڊ69x0sëfM*u3{CT%6*w,eU~FbЂr,3,?f!^.yn %NH�\z_'URM3p߻2*$CZg/?C3!7liڽ#^M]Wg.W%RJ+>̾|%h}܄T< Fai~{fOgZ" lİ Mς!sL"�a 6zlSnUbJ||! ~Zze囧z4#h}Pi P0Uz{Xoi-.pkߢC�h}`Ibl`)0#qsgEE4ėclo>L<8F+NfN03]7% G0ph)}ȳZIh@>*)nSPG죺L8ᗨ"~PFKQII(wl,w%Jʸe!!ӄPL2,t7t˻loSЧ4bB,ٳPQuв|>Smm;{l-1/gFc=ƄW*Սdk`g69'eyl>iPXA,>4l:MXvSVv�vDOM.c6E>U^ky{p>!5PJsl2tZ*.nv's>PώփFB *96Z!LNcn!2&ٵ;|8~ۥY4zsxA pf<@Wq_�ƒ8z~�x>4PN /h=#Ǫ j0M;:\Ja�cW8W|*9DYfpLͧ^r# endstream endobj 226 0 obj << /Length 1900 /Filter /FlateDecode >> stream xڭXI4ϯ0pqWM .T((`.Tܶ{/$o=Nfަ| tC&DW># "ň&˂Wf 7`k\X2Vpo ~QSafTE :y%]QWN>ڙ֩C |Jxauo0ME,OˤAq{_ֻt{}H*s¤)]~)DuMpsȻlpf͛nk.d(鏤5sYLd=qCRN .A@Wc7v$Fi vnr7y35JydG \A@DzMg:pp_lEcem4hCCr jT/taH&»C"cRBPtnTmA44;xq^{'=p`vpΉ<DSt)yvR)|ͩr"*IF]geQwE,HW/9Vna T4ɂx 2X#)ghuqی�+uP$FE8ămpPLiOa1()"Hgډ 1נU_|v⳨CMG6BbBAyP俼`k@?\Yo)/_ v}N>XI,Rr(jL\t첎 L Ȣ,Y>P̚G7El,w#X+s LVw#N(1Ԏj6(xhiIꎮ;65\f Ͱ]SAY;": |>ta\{]jȄj`Z~;︾37BtE t]C a a'ࣨS߭9b-L~?Xb4ۇaKF XHot,XŠ"* Mi7f,v9r+~>.O3A�SG7j'"6[i\kŀ̵9t.>ALUwN=&UCrn`}0p�FFt+ް&�B9Adxu#MA}>/Ћexfι m}09&"ċaK1V2(nyZwŕB=&R.Z0`[ <oPgSaC Cӥ|L s>z*U߾۴)NS82lRl)g-L ̻.ѝ=_>Y޺UXOvpWulI6bJ)=chܖxx1C+"ܶf6)QۇͻX i$=Y -1@4gov5~›-l@+;^h\—}x,kBAJjkKYJל gP܌WU؂ }SW~]l瑃=}i�I ʡSwˉ[5Ew3=`;78d=κqcTXr?wee75h<$+zz~X{ȕX|8~[H Mɝ4}s d/2\;"s.?z*JZ<qed>W,b`5=B{bZ7AXaܭؾ^Eá@$c_n}9?Hkwxʥ%v&BպEf5?z. 8vUyy 4\(&Dp endstream endobj 242 0 obj << /Length 1999 /Filter /FlateDecode >> stream xYYF~_M@v_<9N&^,`Ǚ�kTH*ߪ>$(H}lV뫛%,\x{ Q e"IL$ dp;ɦT?_Q f(D+cUED8TU= MVkӈP pGSۼ*ere\Þa[GŲ^߹XÖtw$?vА8QvaA"IRf~P5X/%i0fDRYM 1( e]L.F g=wO5s'rg^kA+Y(1AuUn'k|YzNx*ܣqn\;A_}gRG"hcH9w7W/7ઌ|O^?fmXRsRp2[鎧7NR.s. riV}掮^FB=^9bQKr+qvd/E2�w'Q72x�6Wk;ii 樅㝅 X_Tϰpi_޵p ҚPz3p)]M(f {Ԅ/UeڍfgGJuH(ȿD("YՙcRڟ#Q\XqY&E޴Ex|f4 (Z]7G%m3,kB!!+@[kcr(U*Jb)E3ݴ9<A+ ˌ�@*BfS\)JM"&,a`X U?q{dڴ&`~㊁x2+ b(i0g`?"|63Q]CPI $49ƃTpX aBH`Sca( D Yi1 ClA,!*̋**!*;!B#Fq#NKH*ϳK6āP, o�9Y PPΉC?AJN8lML(Bgsꙵ<~F-z@anĈ+ЖR-Bp2Xׂm0�C ɶdri oe0}O A{Tt{;(E(p(XKoT2!Ln?Mz3XA*$ۏRH _f q* )B?Y$E<:w(?B)"A( Sr[̐Pl˔gBp|BvhbIe2:}R!;] Es\ .|BױCr~[7x^@Q ^|25|-0ڍgSvK"}81igzp%jSee[?7gH tSqs܉dP-]qD!~nR`gFHkӜv#B=hW/j](w)9H HI6m wVpkYy!Nڎ7qUih.ͺ &3g1qՐ)Hp,1]sbEqlͬтAOKr&�.X>x0z fN1 34+hvXh(v{nf:Z{AU2wMlfOkdڂF&1}Á鳦fH}U=XBE5ȖMao^Qh"a2qhKzcSG"Ci{8No_N#8ǡ*t9e|CRȤsM9uhr膢@%1(w<@d,v^3xJ{Y4l/<dQAp=I6܏:UCP **IMuKHk ~MbѦ1,] ס{ endstream endobj 257 0 obj << /Length 2411 /Filter /FlateDecode >> stream xڵZM6ϯf/T7Kur*]͛rq(jtD*4�)R2)@hv7OCBoݼ~YQܭi2ddrL>ov])? R#\ g2& _oti$*8'R|&KxCB&y37n6|]d|/j)Mb\Zo@"ׄJr1.ˇ-KMKi!JuhE*1Iz jܨL߮ muS֞ꁵڂ(u}0]YmpyKOEl|ؖzwW->_C {2 stf}w.H-VEg3c "8HxjSQ}NpIG_a#b¿CoOR=r\tMYwyW55ƍ6͆4咘pn@l%:κm60DuOYX-d.|*'݇ɻ\b1!IB Bxɽ^|w&mSTyU'7Mn,`*K_VK^Z|[0q[cl/[4J'.,BfƦ$|Ym*@/0. ʮ =.wN9}{1/G(b;3>~'"B8!N歅JAMb},nsrkU/܅_u]]8>;S8A:>}YWEՍ5@IX!{ ܉;w"|z"x[ KW(CLNw jt3'?YT9oh!0U0jq$zA,}-;2 $io&HWt];qNff m`u8㬐W DKķ1`h1jE>>Ԓa}WŶ3uFr*CGT+.q  t.%bEw B݀]o<k$́ mXuCP m.h+"y!0?\GsiX RwPqTBIVD} ^&>� # dh]v.W+fi(e/ EvhWNbLfd▜lSp/S=I}И^&n סN|33(X3r1( I@}C >:%tgh>/ycDTX0_�Cϗx <98f5y7&ŏwSV>V2jR8,s"2W*\B3ӜXo}#mxy;7}>i;a>l%Rp<c{D7Ov)]խca.Up7;sܲx ˲20 F9 <B8V?೿>a~4=fj@ ux6Y![B35vh?MWU1{qȻ,0 e=Ƀt ࢋpaX_yHZ8f!^uLpEBB>b%5Q 5G\ -x2~*H.WWF!O>k͏H`".SLǼvĶ5;4Nlvۤcmw, ONxĶs1M=]t^." ~6t} 0p@vʥzXd(ݮj2SMF_Slv⋌d�DEU?,'GfgH#(فPDW}'>8<@P]<.sS6P\Wu`BU$E@+b`{H)j9򑮝z:8^a]`<fyJwB>M|,=ƜڣC]*o<z2BhEd&P(rs81 &M̈=l^p崑xQAOe("!!sH.#]/pi1 ;[5ebبUm#;/6E|fTG)8ޮ'}7'`\4pCP{l'(mq#_D^ "[4q LI1@f4܍ukю: 5 zhݐQHy'X2@8d*Xݘ/OjTg9}' L$F׹eXhcwFr07h<m < .gU$q3 *5ez}o?�l endstream endobj 269 0 obj << /Length 2201 /Filter /FlateDecode >> stream xڵrF]_M^*i<f0/vۥwSkMv@rH!-�Zoυ #{&ǫWo>I$&|Q)P,H |=ryu1F +1lt=7`@rDtb"!j 6B>:D^6YY8J \.JptG9%X!!ItKa0w^7-%x~i<vM♆=fuGɳ?aЎ.*QI}!I\"�YOrMfCj`ۓ`lD)hy62D+K<@,2FP ڵ4'lVhsL!*(7SJj J e5Osƶ,۴XhD'4K7s43+@;¢\həo$dbTYg+:]>Y8V_(e@s0pƦҩ!.Z ?W2F&zDWӯL%ыFJcyt ABȐ 8H%jC ҏ99E "&?G10Qب̓H!%0F�>bb`>(0:#ٍ}w:oɬn̒϶f4w r2'"sR?͓gv}tMt=#?X-g}5:"y@L  2AԾ= #e@fZ3D_V҅cNp$EpHx &(\C 1-if 'Zچ݃w6DdO 4y๥ 7L d8);yL ,nuUGLBŐY.>.Xnl|=&ztôD"8#O1QBZ#񃖄PLi5$rQ"XPFbߢ 9?ޜ̻Z>"l84$'I!m*[|o+,Nr iۂx!α.HқXWp\zjʤ s-�.jl5<R({ 79ϖt bˑ{Ra$c#wUڅ+x2QLYRg&m4XZVYwmz Sn>ܦWpXH 6[;cXrܓc*Ñ뺶|zZ.хLVy.]gFme&$_,֟h!.IVA &K29)rH7F½u \lSFEveC۴ MšaD B]/9= AYлU]HqPÉB8<g!#7�B>"R~%GN}GLOi-l1Uc>}|m3Ok[ef]@=tGИ擭~9T3*y! bpI]) E Hyig#'3p28G]ڹDg7. o:"5 L>&OeL)<Dwfי4O<S:G 'ʋ%zE<=4I}ON>`L\MƫM� ϻddZsөgTB/R#(7d\L>´s3P`D#S ՀxE5� PlB|MH}n^g8 K2XmXz_äV1 [> Nڷ:Tn}7Xe.~a^&lj5&h5Q桯hoFu֠K¹L_0Mj`h.)d_yvˇTv/0w5w̃4~g8m, ?aRl:k߰~tm~ /svhƉGz3'JF r4G .5&˻zQusoUa=jݬ u  )76S]FxK endstream endobj 171 0 obj << /Type /ObjStm /N 100 /First 881 /Length 1761 /Filter /FlateDecode >> stream xڽZnG+\z^�( �CA[&#hhϫ!pDj 3󦺺MS!HsWG4%PI4c U�+Ze|x,RWe<-g@dܘ9'JЦ& YO0\ +hܠ<\ŃY=!>Td%2yfn82'%;+NnW ].X1` !DrpQAsL bʮ%e Y[1&#A :.jPa)4ch {2T9fxˊɰ6s Z`n?)Al:^Kᥥ % #c Xݬ|-*sL XIO p¬B{ 3@ì9UwX @NM&Xi!vaY 9 Kg0H D0XZa W72 O,#B1wCv #0H);"'Htvr2eφ˛5_ofÛb~=O_,\gCU "#ƸƓ1WZ]yϞ=[hn6p3bqq~5Μ·_g4޸7 ֈ;>z kQ0 Ow0 ?\OHQ~ (8L-pJdXl"tQhCFXGjGGT$UN5fBy&)j*O6+Xzo" F <B1!vab)f&Z{8EīdB] Ios[x}o&K贌L;Z\ÞWax7z0uэ.|`PgY3)zuB(ը`+_nWj1!"VvE.֨LItt]OGA`E/]X䟲z=vQ|#&ۓ^5o,5u{q]y&c $ۆkkcf^2&MXChǻQm%wb Zs;f*=%߬-oPQڬq%ZĂF${:xs<qq[)nmeO{.t= oGC2SFlIz8}ԉs.,vT&t;"?9I6~*qVm..ƣ@Q *|-">~H='8*"{JЌݶVUDшԽOBWnևe뒿Y>BZfN]?1p!ڟsԍwS0E ]).JMm7nrѨom0`l}X`:mX@.'^ⴻ^+~`ȏ�)R_3+ . @s+hHD]P-a->sd.,{C"N,s]P4ÚXN&g?}X$,܅5U, օY SLv!ʄGu'nˁ|u˟Q"Q(;i2'܊9A!E M#.wGNt۰yև  endstream endobj 284 0 obj << /Length 2061 /Filter /FlateDecode >> stream xZ[o6~а@~b+ lkADcyܬ~ٺىb5 u !G7G^^$R(LEDDBHI <ol݋F#47(;ioH̞r;hR(H_~U4BtU"˵l}%Y6@!OgS cݷɔ <.n0y*|gL1̷yԕŰAf�-Mn՛5 XV2Oj�_ }WDVLgpt !-1N8l-IM~(^~b-d2?:+j'ZmD)d{Xa.+I`,5܌HD*.qS㍟װgj ?˽,Xtƌ% /'S}vӵE2UmkwE\zϬ80%`mr+8WYm`e dgާŭm!n7*H�ZF F8^.3{ۥEJ4m!AI;<glف pTdD0{30`V,nΙgw[n{c^D' glr2�̆i/'=ަ!CJK$.Y?ʛ\pcy2K;y A0!xoem !mA!`PU[RH:42@ fDUs�IJR3M2x!7r.<hBhGfNvW6U!oܛÐ<9;eGX6U+q.%.jU^P`z>A!]&r)HJi6<ɛDKWa\xm}7g.y4]}޽SwfEa@2U0:M�QH) 1CA4x"IG%MN\GI-Uޡ7 HdSdJSNP@WZ ӈp^?+$"OgyfڮmxD ‰RAi4z\!K|;RV/ڶrơ#.C!qXU/tZo-%4At#pi{F%Z!H#C4nEjѡIX Jc8\s(ٺ9aPf,vŰQYyfOW7~ȟWLhbAB*87.~g "Sn;1'JL  _؁GvT.II;�| 8Xl˳V{jItto޶i ^ Uje[OxMsKEF kcgpm1. /Pr_749% "R; )j]VK \q})p_r~{fMUNdYdPWelѵtWMNj޸7}jao' ~ *Y'‹dIU ؃P"`RB w$;J%.9!(qh)qəs Qw}xE. dy.DxzqfYt`ࡦ,Tz;6y2 /Uns BQ9lY;JO!aS m#=ǬIB -3ݼ3PZTS) EB4J%(՝ V5uހ*q0zK^8VqLWmpߘꍶ/T3 E! IWLmFx4e-x_`w=IP n`'9C` `#B`OXxs t %:ۦm^8Ah0�גoCFg #>= fHLӏ/ځ[ OJdOP`7_m4 endstream endobj 294 0 obj << /Length 2609 /Filter /FlateDecode >> stream xڭZYs~ׯ`vBVY8ݵR* r$a  �FֿO 䃍`z 6/^ , LDax<H]foMC\|wZ8 z%P+y.?T> gRqiՇfq)%gEmiAOz5]or V5%j iMs&㐁$I9|ўFA"aټ+*_@B֟;6051Ve^1+/ O] P V U涴{% g[MAI)03c &*ťjr <O)foMZ54S &VYGChb`|>gtJz 1C$\سwU{h}Nt Ani6ELnrp(qP};!˝ AʬK)c to0,!X4,tm]$+hjyV1ϔ&]<K`vQܑ%nܻ b2 <2ǺEX4/ 3A'Dϯ1+0E5M+GhYVY6?+چV8 -]9Ik}'O%Hb(IU_ +EHn]d~U:6U4h$^=! ύDU&FK %0_br 5-lsBPu3IgiMCm][w.+:gϹ"&�!Hx_t) !-82Wͺ??AuzNʻuVx w:/VZ[߇R_rآT6\ج`�+"}kh~@%ys( [HmY&z PWԍg Pί̐p�@ɲuo~aw6_#,@Nh@)GYC~@{kt)dಭ_~6J(Qc'E!PG'!Oě�j)t'㭗p4~LuP J~Q/C  ޛuSȻk,7}HᜋJ11;0y0R�ְ9W[BUp+Ў.Aѯ c" } j\b`~ BYm0ö蕝 Y8}SG]ЮrhwB!R@aSHvh*HgOJt  |I@U0'yCGoeT@'K~:0h(D`P[HuW; `$nmRhorЈ4@dRnq[EVGȿizSVieFx{} �#zPD.Aŧlw!sdzr=(?;4$A q`?@DɈ1=~ςڃ {#�e_ uR+]ێS~=Ƥf%cRXnY'D 4< :xP0ۣ9 %#vnOو�zk[ ,Gsydz?hrC}J9˶H8@AHLЫB;S -x?[>HfUJ"DQwt0̞܁<z$~ a/׃z1q:+ګ֗QyMx{eK׀0߀0׀སաEV4X0rś_ۯ)j'=.BM.^�+@͓Ei7V|֍ĹVZlk7"uanwJ^.":xvO'8S{lk).Dh_E`U79]$okBڇzdq$n5um v?Z?CAkdIcz?{/$;�pנa6 ߏfuq>p"&) ؼ~!Ba )Ge?X0,&Y<Y/&Pey#À籓LPˁ1GYK!T8 ]Bó!,ʄ(P\n=_㏧|4kcD"A{hW1|355) ɶ*w$nPՇhG:IX{ W;|2]>+YbPd,K/jbCxؿν|L6E[9bdVO"=!IIx&T9, ~Sc*Br^ʖJo񜎅4gO\TєC;pat<+ci;";Wy'zV#X ~3q<�Y.YoXrُ?'zpz=&>%> ܎eg AVBQ4? p endstream endobj 306 0 obj << /Length 2041 /Filter /FlateDecode >> stream xڭZێD}0%黻AH,0,Zy@Eȓ83&8"ĿS}cǗ]~|Itm>7=$1 ֻP$HųS}m칠Hc3`f[m`)B&R% 6` }`Ĵ l˃i n~qVrh%W  R0׮?Z Bѷ Nm?8~ּiW]tx<F!5@ySDnᔾg1ބ Ɇ!(JV\ a&7I>9E 89J"Yt\QC}Tŧ:Iq^TI$bȷrn c8ϾcO.0C tp)Hb`:J@X CFpT1 0Ŵzi̬,ޚ|q\ȓ͟/>=Lv0I^ A�a07Z&BD�~ �#D8AW$&ƮZH Q6No4X6 ch9> ReOU/SLc.xp0\1)\jbR. w..bHmĜ>6 0xUWxm]h0{.*3:*<I,$ vvORL!ji8HSCtAא}1ޝ>g횱1Ԋ&cY&xS)*!JO!!GL  |S2A@"pvQ^L7IT?ެ63dfR>ϿtGW_ pmP, q~IĐ:?TfL( JTD7/Gբ5A%]Cǎəh[wej g8޼6C@YMʝ |1By qSd+y'gw`UJ,>Du8US]tP اAКBT j?ZB"|إf*DS~ Z`YHD;@MFB Mh=MIMY, |Sy=f,ؐ{J`?ܝxzL2$u5gOfoq\xԆGz~#""r _U,{v1�HrZSf#Zafio}HA]b9H&;W~ a=ȱb'kD)F0"*gcұv"^7ޘ6aEf) ʔ >oIٟ񿏉)NPF[&kxA 5m sa58LMi ')JFPf=WzXmeQ 9VN3 |5txaᚏs| ǬpySI)=7!P+:(}N*\ >]=#-wyUKDFW P^9FΙhNbAj?:u>;^+|-)^<nH_D"&$rK jRBDiG9; x[t8!fC(_M6M)˝]k®xcKlred.pʍޝOIĠy ĕhK2_}%m2e5g4 RSh&1ߎEx-m`hHO{u; y1-Y WU2} ^x^Hs>._A="mw1ldz|gV+p?q:]2^1n]ۢDdyt[>F=k\yYf̊mͷTn:ul74#gM3r26帉*޳ьξ l@W"A|T\ ]S΁T [kzڧl< endstream endobj 320 0 obj << /Length 2175 /Filter /FlateDecode >> stream xڵYY~P X}B^<] A![RTuUSp ya:j~ܾz.,.2!WJeid*Ke\H֫ߣi~.Q+)B^X%JWjcU6:4՟Jֿ~WKE_эr-Іl~9~p]|:[mw<v|ii~*w]]v^Za;=nx>Cc'ۮNJ'UTzEuDuMӭU=vOskGz4Ե5/ϢSڑfr <Szcr}ll$jiDz]$z7` �JI$2]VO'{;JҘE_| ښv}w ,YJ1`9;cY}}>./9"\MXz'BE dDw9oL/hZ76+"P;6W pǁf\Р7&rXҤ~;;ŌDGA뮚6K1�|FeohmV<@a-Xpvhmn[`R=+KAq=Bb!YǃM\{f".AP`H()d˅B5̞2 DR e,G@MH38xPZXTyy'* @bsc|qmzAH!J2 4:C*s1!uc!a }Ys5#K 1X/7&}P5@D!ph^ĩIfVtfslk݉0eo4DKzV* ϰ<M> o!V,!i@D#GLx ϮyIITVc;*f<o_B 8wA/k[,8 >×W wk-罱1B)^?.Mv0o(S U9wb;XZhvøݸϸ.+boؘ$sFTtI"=![EhR ]P3lb8ڡV-t?1=sI 4˂f˒R^TyA"47?̣n:av. <>~tz24w 4t^~t߃ЏNeü? c3p--W1POc7Ո۵~d{,lN0rALcvb&o%5X Y1|CUᡃ=6LySuϘY~Zp? GA,jjG6hmp^o/8y=],rz hȻ@Z6 | CG.W*}thd|<Q#lΎ B ޔXU7*%_P `|4w3–<Bpkˁ$�}̽ma˙ <XsC;^$�%z;N6Eo5"Z"|OFG{wvm-i`K<JñYNPa y0�:,fxoÇ',,2Vمnu( F�1LS+*wB{|辘f6Î&ءQwˑ-$p'!9ka=5Jq+3o'Bx1馻zufsn <p&Y{gh&!I±gjIH`|uf$#0D~1f=ZJYoH%řo㻌.v gIj[AgqnQ n+4U &R*@njFwjI*ӿ]sj)Rsٕ^b@;7,o~ng%-enOYiAks }ڨԣzI7[Qyq[*58Sf-ݼ9;.O-(;[FFᶬHزKR\W "HzpJ?\KAvKn.ḟb7\7}4KHrړ=zwcOOi!d)x|O/].Z endstream endobj 327 0 obj << /Length 1784 /Filter /FlateDecode >> stream xZKs6WEA$Gf&7ZlPJQqxDY6Cv >.qt{I"$XFTI$T)I&<XD۪x[Ϯ.>|/hD0X *Hs#)&8w1gB#X$3)*q4_M.pFLѝ((VVh}ݒ0ETÄ")D"�Ab$8 VD8-h!c�\#-;a|  GRS ; *ޘ4P۵oٌLkO{ӠTq`+&`9DidZxٽSu٪MTioF[.X!ND�JR({le:- F*҅"8X@vX}Zn*kcsN�N Q= "!RykYR`vW3s=.͹@ƕ |i3djP8g[`Eizk x Ѩ9W3/ӽ:]D!QaOq; w|cEF39Qolz&H]l Q4z]1C$>tw U袐 I>2j5@2LUJ'!_~e0" ʁQY)5 L &φt@|) 4XqO"l10.IN&DuZ%m ␠k&_w,vpCojvسu̓ЎY2eCR"»N)SD{R Snae (Ruk|eYdYqߥq@p48d W(ʛ$fnȊmFl2p^sZ쁵a^?1h~!toRLJʛ0Zi@zѼ5 3~5fn\? 4-[4D9FȔ[IHHeCDԯ.NHxp a 2wqcs.y:&:pĸtafp S-EGdΈ~?UMvuu ̣nyyۊ^߰1TȋpWU47eX'ec&-me$ +YZՓmVw\;S�}*IR@j-7dY*"Sl7Jq( [7qbMjz|LiDVuXb1&ulGTGTu~7:ϲFщ/nӛ[wdm d0+FR}w#Y4 gv%44,o6AU 3RpE[[_tM)1o-]q< ʥK?MCfozsdj7lxd`jmrf̡!VŢb\}FY cuټ>cx5r]Čzixhqfoi>϶ KQﴨ+Vӌ2FIfm7܇u)…ǽaj4HHRpTȐ� 畒o&l:$7E(oC*q) ʼnL?..dVn:H}v9bo-80FTATOh^uVs!afCy$aàELbDA'aОџ..z_y!>/n Mq><2$t 2Z.7�b%$;Y endstream endobj 334 0 obj << /Length 2238 /Filter /FlateDecode >> stream xڽ]۸}ČH@RCqcHlkɒ+,pHYN\}X"x17yAD<L$0*u߼D#F)K΄B @7C<f21:K!f<?~ >yEoU=QTE\%�t"<IsbH(]> 3ºd]WTV?_:n5Z zg2 ED8:aH,=V,iQ֛g<\,θ ȫ %բjA|Yd%<XAx c9ҽO `�ޕ+V\m2 shrsv˾hҭ Ͳ&M/itv;SC/ҁKtx<<`TX9ή+&_3&VNUy~˒vMV!,./`! X$+ B+Q* 5yKh8vV=lY~nW@Snݢ͗]QW-^)Zֲ̊N^ۺmEChR:ŞM$K~@S8Xx|qAX!ёY& .JlZ[ǢHBp0@4ez*G+8 #F8,R$QLK!ʬ=ړn%h`kT H4m.EP#!jhDcEڊ q&<:hqFu7t qJꍋLk65C{]; C[ӸpEI0(aNoQagv6Ih2Q$5\E 8V-͞,8<Pb  ~T `#݃wMNgvuS[.w%lκw7 =D@s)E,77~LB<~@pH/ f%e? p[k.C$DA"O@xB92'1Pt(l'AR-4f{~ |[gޙqy;V-(lY :>{_9ጟ`lZh3IeŽ8ٴ ^vGF˓ƌEM<60y%̈́K5I4ˊj:ځǾل(GWp$,Mq)Qq{);dHٯ›1,_sFI捣xZ:L}A|2qz5v0N倫X{.rtV|=*Tx*^ٜ C.A ǂ d{dҰbYafǮ#z'2T>?_kXHCu%&PcOs>|g*Uz^a S:ݬA% Ǝ= dAIS_ٰnaRjd ]swǜk}L(Zm%q3#MIgm`}#C[kPAĢ' 5sINo쯎2bJt:|}!+gE %Ty(Th{ZkzK_,]߷H$Kɗf)lG.sȖ4qV[ئ^օ. ؜L:X~|-}'>i[Iqf_*a ~5% rh6QKnz `g]Um+c?{l5nY󔙨|@ݤ&bo[{~uX^Z~kVE-Ѹ-7:nU0ݼփe-,H@K'"\%+(ͼUd{d8#p%o9~-.L@ j%-!zB.iw =Cfa& dz[?sU7�Q2\Tj\…WEѶM-i1пPy쳱i9qVyG DBz},G@%e\1v#=;Ƒgt8i'=N@"|Hmt[!ec*;OrBѳ<}F1'8#A_f|#с? F}6s endstream endobj 347 0 obj << /Length 1785 /Filter /FlateDecode >> stream xڵXKs6W �)IdC6d-ER#xQ$E+Ql `/|AػvbMH%&ŵG(0b}_ML/~}S`<�mz& ԤaG@U0{$Gq"!aU7^Ϸ3`|u5 {K _$0^FB0_vjs ^=i[gō5wsE*ok3 sXb*ݭa~[dUe%k3V]^U] mMV ظXYs' @k?yee |ݭtm^un+; ͗p~/F>1?3#5xb1)|3V0 ;=1(GV6އ=PI:H8t`$N4pC)*! k0ª'^~1!m|)uV/+$ߪ $~#h;] pC%UK˞P!WsUFOUOhJl6ʡ3%e~^J9Zz+ +d<FM$~A4;u.]AVt6m»04q<! QD1Ox2 Α9? ҷUjSYuٔs1uͶm~$6Z- jױgWՀ4H]MYt&jtTÀ@є%a]GP٩!Mr� ]/PǪ"} [\3y"" 8/H;+zFX sQQTҺȶ[K%wdIDzdG0Kt`Tx"1Qs41;Xj/GzĆLp)=V.] p$i$%8䘓,;A5%)dO.8Ć�/p2u[MVԭJTT}1#L nDuD8\)8A-L!§i+, ɓ49\N PPcҐ^pE(kȼ]8f(`cRuG%Gk2sP\fNۦ)V[|96I $Y:̅R8/VdG[0ω$`A~ mS1a%$`00#Y{(3p`*<846 P wkg5LW9@@GLhlTLT2Xm#+ETk">=q<r8%dd8+Cp9"qlunm N8Sm.w\חMWtãu|%@ ~c1$Xn*Gc{ؠ<音(8B cj4Ls[ɭu!I V2݈JE) -r@<x ঢ ;gm5[1wYc7v0+F'RAW} �:x3 xxa¦*C@`@"Z!r9U?4@4Φq/Cm<jftQre'F %c^!@붸jU:pр<(j2,#Y.1ژS~#BHMeE_jؠ9pj9lt!֫G܀)8V �;qcvWL=] endstream endobj 357 0 obj << /Length 796 /Filter /FlateDecode >> stream xڕUKo0Wp4Rpo#Q{zHaM@ަ?6c6Kj=o<=d$ i}*cٶK.BR̙ʶoޛ)0IϿo?_Lכ*pY4l#(<`k|)Avzt1At E,p} %oy)b%I̸:yUWAW1E",+C"X׊6K;" xQrSW/n}hތz0.mٽƖ 3R,(!hUIUJX0u8)\1c@D�bۚF%FoGĵB5.Y,[0'}y=%=[R<b{;w l"C;BXoҥ`{<+z|ks#8Ǣ |PHsviliovIcFV} =xvdj;,EFQKUq*g "#C*Ol jfA͛|#ÇK7:2PsDcb�#d!) ] Of {ȓ:NUR4/j;zݍr1/ țJkGd?]&(@;[0s]KoKg3ƹʅUTnof¥;TL~As`9evCw!A&Le"E&`}L9R_('=S,WoS pݰ͙j:5`7 endstream endobj 364 0 obj << /Length 2201 /Filter /FlateDecode >> stream xڕ˒6-TAou9j$afHӍ(8 @~?�_<?߼xu+YI[iWLbu_&osz#5Oכ_^pWkWá)3x(_m҂ByWk8 m"e*dئ L<v#8̓#G']_x: 5xW\<%?O Q zu]1Mt|`"ط'fevZ$uszzInStsT!Q^ hXa8a x1F HdPLoB'Uz 80VuPVH&<-E&4-+ .& U0"k5v2~=zx|'͑�-J}ܖ39>ㆴ!9HOԁQ)xH2e`'$ i`Sۍ+8Wqh{Wv, !o6\ r|Uo^Q)e'YRv)p SS]=OjB7<6T-T0W6nq64 fi:y-AN ޔ0FM k^&ev^ԩ 4^`IK׻Wz>T:ve�T`5:i ,ѬmWv}!A܅cʰ#f6@BpŒ'Ej.TP 'QK  6#*/q޺Cs:A)@mʅDWMYᜰH\(:q*6HeX#V9h\uuh#pOys&s,Y,fpYeûM 4OV- m#r-`f$$-Ed11·qI.Y Wn1cvuՁۀOh,ìڝ ±nt*L' bᤅ Z%.bՆȅ:yp{*ԍhH`(*[e*'# >�D�A@?r|B p1(? v[Xh&Lpnn. z/>$D^kSJwM:WRHV{&.(<sk[SC0vfeE\,p?@~ qYNl#%ؾ"|.+V gJCIB =jԠQiL6nߓL_2Yg[:j3 ΃ [jP jB5+xhXTP@؄(�g�n*ul2& g.P b4ؿxWn,4P0ƖL gU ֌*:aKZu*Z8ύ/y6n9`v/pT�`iU]Sc{S} w5=K\A=ZR ҆T>ǐquFi~. jrĀ[f%׈A RL l}EJl !߰vRj$7GZzBQ&;_ kzDUSc $y!lvWPH6_ӷ0.PdB.C=uTmn=)6WE:kOUP g"yoo΄pI9Ll�mwMvH N@XP `y7&^'}nδ%,7CxS'w]zE sH_Z?#攞 !ih5$X/ 9F MPI[%@{k`Lm~7.>yG1M4Դs 7Yb%Pf\hCQ. H~(K0.`+wUȂg:y#oVYgL&*FM̞oFRG�ӻI 'X<)gDz v 4l AAWgv<>15)>>%y"x�#fW1w [bv<D\i 8z`B R>)2ɡsо P5^HeA}Rٍρť.6(˞6bkNj2cY6'Xn^ z%` endstream endobj 375 0 obj << /Length 2828 /Filter /FlateDecode >> stream xڕYݏKe`'$O\/"I ֖ɒ+Q3>rv8|ao~|ݻRɄb;lT ,ds}\m}Xz-2v+Uż6+F䩡U$2rǒMq*x =kP(З_JW q7MU&zlhZeNrY"Pxc厼pZB4^̪hx$ ,ϲH(M.\6_0? SU,Ta X 3$K쫮ܹ{ڦ&te'ޠW| Z\ ^3=JGN`k8*U!2a N;r<sqyeԕm KQUڀ9=3p`0 06:Dgon\&$ŞRt[X0UK:-?UΕ{&^ I3p7tդ6eb&D$>VmOYsS»KuNW);+c]۸Śd<u$9aMc�_Ra9Tskͷs"|a:%IX[nعoPt,h #2̡kO4,KIBtuOMZcv'BY|_rKq:%̀eWhS;XlUPjfШOx` [b8&F/v]$<G5CI`v"xo>T"֚xu%:z$aj֍<i>!k,Kw Mܗ%^ogN͒Oʿyv`>y.-ٴ<,Wv4mU|vPpވ8/MF׷$UJ{�@0Px5Sш8XD7%Ll.. &˨ *x.1 A'K݅u3uԙȧaW߳+.8f{lС]ꌣ y5X>CYSp }X$3F.ҳ5(v4Pc6*( u;zF(Mc;<E"(B[kwY.7"F΢3?U "G@ 3( )V2H.&Qs*]odxCE#WQe>Ývwz>E7!DЏl}W{K}փ  yQzRb)Rv4t:u6Bwko("GC\LGce9CE! $9_dkE25=5vV\Oqן3|BO[2ohT١s xA>>!xj>[YaY l e/"cX Hi8(>D|Tv&%nm{E>K/Vaj []q�(ݿq{ueO(ˑ`< An4B.pSH2i Yf!fJݮU dS~p> x@0ay !xI;/]7,f2:N݇ZB1ډ XgKc?'Z;djׯH1/_ Kyl!܎OUԙKE*+%OPzcԥ넴3\`<b^n9 zhV+J#b�byM-T,Z6NUS2ls.Pvl1Z Z Zj!}C]tBǂ]!J<OT`BhNo-(ryM2hʜzVJ W톺eyH2;SZcMI?b>oH/\2CzC4HOv6ǥ i,ðE\)sl{ToB{Ȑ[2V=>Gχq �Q|\C80'Ծ<q !n6.�)s քm fNSEM@hx<M+dU/e9ojphbx":|4+ u\B L SO>uO98~YZn;NH 0uq Q"PPh _E۔p$-Ҭ˳̦%\em5C#΄tDoϘQ g|ƃ ԯҿ7s+5(+(M~`Lx3SCvJ(ͅp�oldJs2C<;۪?e䂩Zِ|:LV@u<i_W6,w|883,pӴnN 4R" ER{@u#(  '0o zJ y&>bcU/r~7þٌ{Hu㢡'2C?H&F?L}'4;v_E敩KN�E�_e*mAG %ԉթ= Lä�q"@e6S=r`q؄zcaʊ+R6H|<1slZ: !{\ =X!7 +ͼ6|WF1ےR[UDO47f%mƯ+p�_(K&iF(O(LHAju[ endstream endobj 380 0 obj << /Length 2880 /Filter /FlateDecode >> stream xڵZYs8~aCUYqfʻ2Ly=TJ$Bvi;Oq4>n2'ٿg^F|4d8b:N&qYd|.ms~4LiLh L㤳џ̤NY$$6XinLm3A3GP6JFHGu,ųo/ٔڡ~!l]u4YRgM)6KV7( 1XN4$*\ tyfi6޳\ D0!CrbLmnuGWDzL\ QPEU/uSI L90POV6q lksDcZrύ#צU2/1a-N}Nbf!Mæ3 ܼDV+'U_vWsWnZ4:I@}5WH)[|Թ3T& W a2I>Yl>| 'KfLW;s; (]LޟGCʄš<hHƅH8,M[$4O@=)$:.4g<'M T2IY U�-b.PG3 Jaoog:PSO]O5v;SHBLp~$t8H B+wo./_~yp<!'n-3>3FLsO@ BCA¾B3N `Ū* =Wr^v`+1Ws4@\gOjm #Kq9H�6It\i?x$�)("uz{렅ΧǞ'<+|4뷏Y$:`cnw=OE}{<oc�S萄R2: gzL$[p+1zC#+0-yyIS4Qȵ7[ Acظf^gmvE o7ٙED wHPY9QOr O.t\{KzX|֢)EDkǴaA`RT^ț޸kS:k$5w!akE`jՈtY�>v-`t[g4@s^*4ņ0 %napSMK# (Aݡȝ]Rfq8&aPeY2Y1lAj1^T[<p?z׀ lL F<81kqxL=hAow{4/r:vd`cq2'q+sGnb鵬i%n!>P~є ;k í{R: D-=N Z'踀HC)cxxySYyCv_0j>cߔ<8#"1KI9 $:EX1hBqgv- qKI8L}m@#(РI�"k\wmVmiMvն$ cNX _{uquGqQ)ϣHv`E~&C}E�(R!G8v7-RL#Si>I`-`p~=C 0xwbˋl >*kU8qДd6UZDK-udj`8YID> n ҽ)a_=vKJN 6ǵܯ>Ai{soa޶ }҈$6*zUKCA00lH]Eu M6`$F;P.XF~'WrE@FbFbk\۱<fU*fRw{1H⮺=8λr:,n/sp2}kht\Ez(<C<mJo/|<R Ty wUUV4!<s>.|^c{oZ[w%ѴgBE^A-!Ez%tv=bNЄPu5J]+?!jXl[CiZF]. 21ލNG֌F@{Tw^@ q Kε,cݢ0@NG@|l}#wR_lP·o:;?|ZP*g/_0 Dis;`3k&a^oƺ>�9j1ԟWya |ʀw ,̦ M;Ȫc}rPJ:lj[aZcDxgK{ribpi>EE:x; I`VPyҕwV� 1L( f'%_<,p=buh4Fp_=[${1 �́)![?ҽ^★ 6/wцJH. `c\HB_8Py8^sK['3XYQt~ e9r2f:ߊVGA9o>ld4z\Rȸ:}lh6 u>K9&$Ay6VF+{*`?qܟ h kd:̌c*.(J�<)!w d~eL:Bfڽ-‹ti -Qj0vW$#þYϰE]!,m4Zfڗٙr9-n<$P3b|u8aTf|ݣL=adE�sN6 hLs;첺"6Ƥͥd"C,MӞ4>daA0D89v!Vk}7., endstream endobj 281 0 obj << /Type /ObjStm /N 100 /First 869 /Length 1558 /Filter /FlateDecode >> stream xYKo7W^$`n @qh ~�7Jkt( ypC \,QBx@x@ c%3LO 9,ada>E0Q(͕CeB[Br!Y J>Eu Ԡ C)A7ȵLxa@/IHfCwA`!%$!U ^ BG! o V8c3H cgLXHtV087M-LB+v#SU|j6_jKuͰ:v* @70@frU%I[5Iq rE`X`8QPrb9Ԇ5dG][Z0LU4i2l`njxf.GCpsd(�4<0_|"֐B`Ż?w bٗ. (n X%]T#/7"ȅ mln#LbIxq ɻdǔe5f1T2.ëp@& g(9$&ųgb"D{``L0B[T-:uV"zup _!oG38m[Nylз fm! 4Bd |%yla:0[~wJg-K(\]_ydfy<_^k凋k v.!g*̔G3Xh2Xj]X-"aۧ"XÊ"%˄a"ʮhhxd&`q )8U}X.>;`ˈֆ2Rn=Li$,IIIS@IAI{'%o4&f :#tbFKz({ l6iaQEP}XOuLx]+ 9m.$VkH<kkWKknh0ۛc׋?r)? /OhlnXJшTg j=M6 ?߭+ XD0`^W^XgkoDnj삣{w8jQ6!p>!'6Df<CPlQyUg֤Ճ->q7mgA|*[tsS,Zlk,fJ9,B[gtj¾0(\E1ѯEd{0qWvмƨz #ԣ*Q#܃?,rfg]f 6+ԇM-~10Pql9͌E#ql3 +eV<Pbqq~g(edVuPJˮ6 cmO۱ m2P@W{Nw/im}^^n_Kj ~\'kD}:tOwE ‡-*Z$mv=Ap>e;vA>p8F]?VHJi~ endstream endobj 385 0 obj << /Length 2309 /Filter /FlateDecode >> stream x]۸='>5M/itp=Mɒ+w3%GNvyh!9f8ߣp~{M,gȒP63$,d4[~ n]^7Fd(0#|-2ns*Eg!?[4�Ɔm*]ȲЉnl�9E;_(9 ]9M}~"`UW]^T4vM]\ྨd)l+F,}E"ARl!MQÅ"3Z(W/4 ʢAxbm~K4D!v2tiWӮcN~Ϸ<Yv]ݜ3QU^Uvc#6uCGTDQeu;ap]D(kH9�#5pjUBJoyYhmTX5Bh@[; д8Iƌb |OfsSd3al-Ҳc|OˤS/2F^LD+qUp7#1C^choJ=+&tvҲXt)ddD �9: ݻ:@l Pȫ5cyfl�OY2AЪ!&M3S:b[I2Zhj[V|Ŷ5zrUD)Ȟǒ=<ڗފґR_d܈6? e|w7y 0pC˿MыL^30+(-h\|nG8X[z央 4Uce.J  cf.A3ގ}OMu”yaM)8+p;E`mW%L4/#а+;< ̟ɒꎀ%#�'8 *'g0hA8˸. d!+&ęuq[4�رw(.�G 7{LaWo"QN _:Zy&P_Dޓџc_>'!鱊ic%X,{l$X)3>vN&qч䉛7yN^1OW"1')qs(llfK[4k:|5#n ĝ[E֐ :rtvpYʤS(ۃ]0+Н$v0îY Bˣs$0ʗWu]C=›rŵ˜Qeq6 PFdgmi($(85=-m\]&ͯ f!2=) <g@WYB@wPx-Nd/b_- rZ}m_rMǥ˓,=C.![Z9�+}N)2., Cs{pXL)kCݸW �E`?GoAYL1g\=aph ئ&<ȓЌ|NJ0MȾJz:-^x|e6oXV۟$(˵ ɏJ?߾}ŗ}9e9i~0{hB,)Bjކgӫm R 2wM5`ݵ5�z[#.qŨUCC©54HM:0# ЪՏgsH �)g`)kڣt�ܿiG߿ /a@Ux&x]0#YX?[g t+iW+;/==I8(ڂ1/O��Ox2+W n9Vk]]'Te=�j,]r#fj 9Ll4Fg/QKMtlH!4D{eqVa:o.I$pK*ۥAg]oI{N"rtYFEnJ+ %550ԚRG=f]5MXk^IO)mEuū_�Lszc|C0}A*ׄC u '|<ѸYВW󕹿+^<U> m["Tk g3Anj_HQ.8OM]w(XGzWيJ˺vBQkIY)YAUQช*DK>+.~Cqu�++j}ͩJvH6rFAco ?'[4P7/5孭lC-h\ !Ke$ڦǝs?{omͶ endstream endobj 390 0 obj << /Length 2399 /Filter /FlateDecode >> stream xڝYs8޿“OLݧnvͷݛ,ӱ#_� e9Io(@aWXE,XW2 Yū(,zu[*?r%8Kx+d])\Ս J[h6m8Xt >u{0Nh8*bJ^/L/:e Fڸ)jgvN`l:/[mki)m h9O:a:aX'Oe Eeُ(K;Jiڴ3, U(]o4__#)Xo7TWɂ&? JМYEӓu͡ꊝnu![ǮhUX 7Lֆ=0Z%FʑeΎـwy9muv72X?n܌#V{wq]/:0(b1?tv*X(^ 8<jSn&:*i'?]#|Vh@ŠjbB2֭ƴĥr;Mdb죭;hiJNICn1LLFzj& adZ,()&Ig')BҚ "8ޑB-%�Tv.aL(EoY%#g,` O,v*Ҍ+�HN9lf s M h]cbb}>`:0%eȻZgNA_3 K heCgi�C=zi 㷟z(� Mcmk B VVgJHn2T22ӣ` .Dҍ=�qyaP6p'[ `JPm9 e!Bi.7"&ƙ;b&Ab?3u_rP3c1<p("L& WQ2��ccj (bc(n4 :N? uIU�nڠ{z3els}fahGLY@u$|[Z@8}~3 E?V5^`.X +C`g *iSn;A:3`0Ԍ: Lj'Cz_H$FeEF'z= xk -c} ! fR~Y]{&FP'քYJp~HFx|_EWw!i(oSdd4yj,{�] ^֊@תۈ{EP\$E|PWP$|dDG2$u~#NnM~rpT#.6 dh+6D 5zj{+P,gs2ΞbVXW n8&j-9bPЁ P>g2G[z8r\G'\ӄ@`hlS<O"eht8`%r)Hq%+!Fodbƃy!r~DHKu{>U8YZPŪJd]~%8buDXq2&{q5n[o+[Q$1UI|P$^eƵw(L FxS"^} `_SK8y6VA!lN r{;⍠ ThҲᘈ2R<|O'br[.q 4iHi^.M̱ 9ʥD/CqСk̔gFWez}r"Rcd 4մֺPmR]/XNo q/=w%H.8/xCK�@XW+7tku3xBc8BӇQ4zm9Y2=WsHO_Ş2)砾X|؟ k{4, `Ge"X JZC&2jw?nT1tM0N=r3/M(>9f}WIa'B( /S[( C@F' 77t~ 77 t|( \Qi$%uN8uk �?7#_ŕs3WL+[t$ň'ߜeEۖP5}wcoڟ~j*BhPa(h )[³_Q;p 'pN(G?O%sZ5ij`N"wbWtr9Qe# LPRA(T-?՚$k[n&;Y5T[״ޓwBhvVR'8IUb-=l@Ezݿ$&3 endstream endobj 399 0 obj << /Length 375 /Filter /FlateDecode >> stream xڍMO0 9u$N[nCPMJhP('~;2>zAX #<'()L.4KI+Z` d\FI5Z߄`%!|_"f &&פ|1QQr-'s{Wo_#vWmUXJ}&EnN)y=ڟoN�#mDDs )2h_DHTN{wE�q푿B I|7#�Eخ00-*3"& 췵tqv;x"]^ ,]Qlv7כ`H.;4㟫1gS&h AY9va endstream endobj 461 0 obj << /Length 1177 /Filter /FlateDecode >> stream x͚[o8+r ֵ8R1B˨EڑfV@L@c߯s�f._;Aӛh�m!m,hB6oQѷ?tvK@04Q|j=Z*l_Gx�CVӍCz-Mvt@OmRS[4Pzl)6)P3~n~|s_7k%lMzx5 ,T!evtOm7*B1yR +$\lC>*RU0f @`餣̌|HUY]Ը/&)-3^DzXA �:vSRWŒSY d|PeBJg<cwFHҠGfD@tѵ}ќ/+yj�ta8i eG29L]Fbfzἱ̛ _NGaDVf(תUǵdG1;qnN&ajE :_Ah)BkAxVjRg]f̗4:벎qs9]tCͮ6>cjDst?BSXit riMU4dbb#cKz4Jq) NO>e>B.t P'cS?]`<͌Q>b'-`w%/>,ybCeqs*zZsQ1`~mkFtmkZ&D[:mgQu�4N xJinlp~u#)h\ 6EsOn!k/%>"=wr}'Lb#߮=1BǤߚz>M߳\ F'_8Hܬ G*gxJ9&2 DpZ/2 +F sFJ_EKhTqBu|n}{IWwGG=6oZ l[~灿n)Cfu<(<0*uf: ϭRN+<fh.R00v}K$9_C)|POH!ӨC^"; a2jv)e 89\!ˀ{_V)"C'Gl)C/~C endstream endobj 465 0 obj << /Length 165 /Filter /FlateDecode >> stream x31ӳP0P04WеP05U03VH1*26(Bs<͹=\ %E\N @BA,C @"F`F`;x�#! `=`pN`#1przrr�c endstream endobj 466 0 obj << /Length 163 /Filter /FlateDecode >> stream x31ӳP0P0UеP01V03VH1*26 (Bds<͹=\ %E\N @BA,C AL<@!BL4`u?`?PAhrzrr�{` endstream endobj 467 0 obj << /Length 147 /Filter /FlateDecode >> stream x51 @ )i»n^d1[ZYZZ(ډ<GA? VLaY*S;4큥YZY4n.eOS.&4U ]%G웠A�5"jx~7:.M . endstream endobj 468 0 obj << /Length 98 /Filter /FlateDecode >> stream x31ӳP0P0@P!Ő H(`\.'O.p�U()*Mw pV�]zb<]?`XAՓ+ �& endstream endobj 469 0 obj << /Length 185 /Filter /FlateDecode >> stream x31ӳP0P0SеP05Q03VH1*21 (Bds<L̹=\ %E\N @BA,ȀI;0Y&!H? d�" H`Dڃzd acP ;00"Ď$>&<&{1 c�P�&\=�!M endstream endobj 470 0 obj << /Length 150 /Filter /FlateDecode >> stream x31ӳP0P0T06P0"sCB. ̡Rɹ\N\@6PKW4K)YKE!P E�??0`v!�?cA@=717C`?`\v  6 \\\�!:? endstream endobj 471 0 obj << /Length 207 /Filter /FlateDecode >> stream xU= @iVbYorR;-Y1#^+w;bBj`u;hƴnuj 11]Ae<P�#PC\D.!B RF3 jweng"Ӏ9r0Ox)uȢ"Kh&bvY}W%o k-aI26p endstream endobj 472 0 obj << /Length 245 /Filter /FlateDecode >> stream xڍпJAY8far+RZZ(&&J+®Li쿏O/2x&'QZ yuDu&wW+#Ws+WkAu)RQH'9 62yH8U7SIMv:Qm9;D#'^:1G&s?ɴlq�7àZmtj 26曎l endstream endobj 473 0 obj << /Length 211 /Filter /FlateDecode >> stream xm @\|'h$A:uNձCQ!GQ|mg+f?߅a?K!=<?T#Nk(jEz@1YNC#wIL`J)+M-�(9B]ͷd-Xz+JhKyF'5z,?1>޴wҖ8Kp/^ endstream endobj 474 0 obj << /Length 243 /Filter /FlateDecode >> stream xUпJ@/Xfa4Y  +P$Vƾ)S,Y'?pcOl-X^ʻKﴨdZrh]SSQ++TlrD_&~nlFd)Ej4zWLnB>c'ŒD[ Ƚ�LwD #TR ;你^ ]`~E>_''J4Gx endstream endobj 475 0 obj << /Length 257 /Filter /FlateDecode >> stream xUϱN02D%?NDBR$2 Ā['xx f UsPYwtgOz'S}]W398"qu͹flMsoOuf/J]\rД>[G8Y򔯈 іH !dSK-D(Jm {.E}X _! g4S?n%FhP-/6Cу_)St\+ioBO|�k, endstream endobj 476 0 obj << /Length 262 /Filter /FlateDecode >> stream x]ϱJ@=R,L<}@r'BBBQ.{OWYނER3{+D_>fg?*VLe3 91xxE ѭJs.J?A>W DKuʥҊL`@(#@zjg{N+fW{OOn&QZ3 xŜ)S`U8><kb}` M<;b 3)b½<3"^3Br/Oħ;pc8'pQ �Ďg endstream endobj 477 0 obj << /Length 244 /Filter /FlateDecode >> stream xMбj@ `Zlpv!M !dj;fHiț42d+dbG9@5Tp ske 3#<EY=-e(4(c5%* bk�5U0Q0%@k�=UO>{tܱW=[v< Yو n8,6rXI|ljF=M1Ɖw>.x` endstream endobj 478 0 obj << /Length 216 /Filter /FlateDecode >> stream xeαn@ �P#$/|Hר):T+i| چJwOl)ݲt- R-bՠ{!=)L߷tH^ ߰ b a^LaS<tP-dw55qXC)4 5XMW*TT΢)J̆tXT)sB;bΡZ}]7OYO >/t{ endstream endobj 479 0 obj << /Length 233 /Filter /FlateDecode >> stream xM1JP?"0;B<6nXW0ZZ(nH<L |exu;G?:zRӊkzxuK /T^hNe{oOTX :000X @':K#"yLD>3L"F4 $̈&`<@&/iJL}gjhGB _i:o~oo& endstream endobj 480 0 obj << /Length 237 /Filter /FlateDecode >> stream xUбN0<B," & X<Z&<B6Yϋ٩jY]Z/ʋT'GϲjjUd]LsoObVjŬjy/ZO$'Րw ;! =ȈDl>P{>Zסh]O61&&KLksMد%6`mC āseR0gx~\4r#ߒo endstream endobj 481 0 obj << /Length 211 /Filter /FlateDecode >> stream xu1N@E?raiG\ WqHV A $RDT@IDZGۣ.SD*)??ݭVtYjS뛓Tkmu!VRmK>]ӽri"F`' (%xnxc1; ]Ṃ1aO XbL8qhGr,2HAGFN"BZyVSQ endstream endobj 482 0 obj << /Length 256 /Filter /FlateDecode >> stream xUοJ@ [#d^@īL!he!>{{ 2E8_ 3͗ǫ*Ik:4_bIqVIZҢ?fcQ_#SXlFSy�v3H#n";M, (6234|0$c:iBA y &=faL]K0 Qܺ&3Ҫ3]{ (�xV endstream endobj 483 0 obj << /Length 217 /Filter /FlateDecode >> stream x]=N0risHSYZHPQ-|!e(Ì$?kpq~}=gKz~ A۝=N'Ӝ>ߨ?ܰ| ?x`W�2NVH$#i}Ii rQmtEY٨ Xt?~NČ I$덂v8Dۑzf endstream endobj 484 0 obj << /Length 260 /Filter /FlateDecode >> stream xMбN@!$2//gEr&ZY+h{RZFN! l#j#U!%ph!rۆ[V_bJ^ߟ8^ ܕRsh$<~Vv&0c :Űݻ'񯃕0^Oz%m #[yL?;;bAnm,qpypmCN_ >9 endstream endobj 485 0 obj << /Length 214 /Filter /FlateDecode >> stream xڍ=n@F?˅i|`wc~+KHT)"*�%>Gpb#23z͌}3 l^xdxt{C'5=]<V#JR_kR*{ xeCj߆5q$H'@\?BXHCzdVh(jp|ݹĝHdo$YݣEp<I;g!4B-�[ww[It_Vp endstream endobj 486 0 obj << /Length 187 /Filter /FlateDecode >> stream xE1 0!y4%mu vtr'utPtm^G:v(I#?xH%F3s1&)^9< 0~clk{`_ X_#Vct@i2eƴ#=Q5Fx3Zg5NIM8(E UO'MGMKMzb]M vQ endstream endobj 487 0 obj << /Length 231 /Filter /FlateDecode >> stream xMαJ@ )#d^@5܁pp` A+ J--N,emea.g'874cZ2tBiYM':_^qc@Fjl[zxf{wEwc#*m<|�#$pز Cab9I[P2dˠt^9It.UYu2}XA.)-0*D8|p �x=& endstream endobj 488 0 obj << /Length 216 /Filter /FlateDecode >> stream xMn0e@ J@tTjJeb@ #]- !{NﮚO_ZbiUIʒj}%jYJN]Cοɗ+{;ŗk�xL�{ 8D@1078oZo<>BB3 ) ̍;%=ԑ>Ttye#nU4 endstream endobj 489 0 obj << /Length 256 /Filter /FlateDecode >> stream xeϱN0 `W*y#/�mp)qHt@ XIߌ<Jc(iZlmPK'g s2 =f#ՆWuX?`}#u[x|zwwE-{:<b'rAE�mpѱ=dr"}D7(_界>8FL9vlAz(b@ w*ݤܦ~$PAJQ/O+`SVl)ZVbmX,'Hñk endstream endobj 490 0 obj << /Length 217 /Filter /FlateDecode >> stream x-1N1E?Ji_�s]eYj$@")@=#l"''{ʹRk]M흶~6%amsjMTOw+A^]� 0317f{DG? i ?GAx<30I' T\N!q:"kw bfe̵mH9$7;z/}\yU\* endstream endobj 491 0 obj << /Length 234 /Filter /FlateDecode >> stream x]1N@ fnDVP,)XQ%:N%GH"q \mkWӚ+n*~鍚 +Z*Pycc*[x|rwwPsH|P LӘU,f{?d]oqH\ (}uZ oxcn tiN]V'V3Df%,C tiqDk @-/"o endstream endobj 497 0 obj << /Length 100 /Filter /FlateDecode >> stream x3337T0P04P02R05T0TH1*21P�AsLr.'~9BIQi*S!B4РX.O e\=�3 endstream endobj 502 0 obj << /Length 171 /Filter /FlateDecode >> stream x31ӳP0P0PеP05Q03VH1*26(Bs<M=\ %E\N @BA,N؃$0z8Q'`& >`& `G${ ?Qr �`E endstream endobj 503 0 obj << /Length 171 /Filter /FlateDecode >> stream x}1 @ a!s51VBVbnY-DM(HgjxD1alT+ Q9O=|1!w)ڠ) B T{@6\% .:Z@ Z|ae_U/b endstream endobj 504 0 obj << /Length 109 /Filter /FlateDecode >> stream x31ӳP0P0QеT01T5RH1*26 (C$s<͸=̹=}JJS ]  b<]D�,r �H1n endstream endobj 505 0 obj << /Length 143 /Filter /FlateDecode >> stream x=1 @wn^Xbhi(m,-q#(|cYj9֌YJUT΢yךTN̖Y ƭx܎b*N7qDoR�p, endstream endobj 506 0 obj << /Length 99 /Filter /FlateDecode >> stream x31ӳP0P0Ɔ )\\@�$lIr p{IO_T.}�g E!'E@!ncr �h endstream endobj 507 0 obj << /Length 127 /Filter /FlateDecode >> stream x31ӳP0P0f Ɩ )\\f@ IrW04� s{*r;8+r(D*ry(0` 0~` A9.WO@.�{a* endstream endobj 508 0 obj << /Length 193 /Filter /FlateDecode >> stream xe̽0[x "~- &2`A+Zl+ z1xK7}`|8CQ'p7.h nv7Z͐1nc!孅+ ݗД>!uBG3%9mM5F4V.կf֚RFiHk7e0)#W^a> endstream endobj 509 0 obj << /Length 219 /Filter /FlateDecode >> stream x}н @ �H!KyZt;:9::(ZpCLrE>%ɋhH)#tyT?D@(rIfRfFی3'zj[Cp\; f[ k} H{wZI Nd;j<WJX2.&,iT !q^P endstream endobj 510 0 obj << /Length 155 /Filter /FlateDecode >> stream x31ӳP0P�aKS3CB.rAɹ\N\ &\@Q.}O_T.}�gC.}hCX.O1TD�vBL4 D"?8F0 &> (O'W �1` endstream endobj 511 0 obj << /Length 168 /Filter /FlateDecode >> stream x31ӳP0P0a3S3CB.C �I$r9yr+r{�E=}JJS. @-\. ?000+ e8Iv�!#!d>B2#dn?`c XYc%e0pzrr�eT endstream endobj 512 0 obj << /Length 262 /Filter /FlateDecode >> stream xuAJ@xAN`bP+.U҅"8EBxxq7@|/Ģ.oa7Jh+(*[$'eY1Ƨ|qqFwΏ)xN)%WX 0 A@'X!TW@ F-@\GaL@+?QowI Sji*ՕTj`t ^3@ #=ңuf'^^ endstream endobj 513 0 obj << /Length 217 /Filter /FlateDecode >> stream xu1N@P#. l5ɺ&RheaB8 G bc WySWk{][!R:]޼~ȡe.{ywxBQ _>*@H9“2؜!b( b<f<M<B3igә69ѸI�aG!]lhZZK~-6嶖GB2 endstream endobj 514 0 obj << /Length 215 /Filter /FlateDecode >> stream x}бn0n|OPBP:!T*CfeJ;fhծGQx (JXbٟtg4{y]SLK^+}&iƵq`Q=P}.rG?_h %htL(>a%Ƚw�Gk]BrQN &Cv&̍A FȗF7"'1u&<کZ܆dT?s1ݭC&Vo} endstream endobj 515 0 obj << /Length 183 /Filter /FlateDecode >> stream x31ӳP0PbSS3CB. �I$r9yr+p{�E=}JJS ]  b<]{u 1{ H�2Y&|$#d>B&v�Fāj\=� m endstream endobj 516 0 obj << /Length 243 /Filter /FlateDecode >> stream xmбN0�г2T%R$2 ĀCQYK)S =D6w6 O:}sX]QE5Z%ǕxEH-ihf}M5 =T=c!.bǜU,k��/튑u$=?AbΔ20g-h.풓&|cIJӷ܏5k{Z;h<K #Yi�z endstream endobj 517 0 obj << /Length 219 /Filter /FlateDecode >> stream xMϱJ1"0>Bt7BBGˣ#\yŒYC_„kJςƵƠoA{]VyfIc/ݝ]Íqh H<YNW͌!#|i~8-v:Q,b#X}n}Hْj`O:Aom"jAk1xp3YvG-m endstream endobj 518 0 obj << /Length 235 /Filter /FlateDecode >> stream xu=N0\X&G\�hVE"T+*�D49# '@|{SYO7-մ-3.ư١m--Z.sUwE/oXmϩjG;vd�)3v(&_*r) ԗ(G^KoNP=:F#Ȑb0caߨ``u`;}!A%gyY$ქ<K~ endstream endobj 519 0 obj << /Length 210 /Filter /FlateDecode >> stream xڅ1N04�8f�eH-�AK|%G2amCEg[|w[>]r-;mzM[.NGxSӜpϟ_{ ۇv}a@ZJhD2Ȅ$2c4dvJuNͨ� (p7Rij/M)vAm+uӿ@"S endstream endobj 520 0 obj << /Length 232 /Filter /FlateDecode >> stream xmαN@ `W"yG8�DJS:TD$02ʚY%AC:d) MܜSE-ԬiSTk<CsGMJhkڿ?\PfG5U�T4 vF@i& 3ȍ�9� 8 6TP=B9ASFBpYvb|TdvdpQv�[6} endstream endobj 521 0 obj << /Length 221 /Filter /FlateDecode >> stream xU1N1Ei|kBR[ AEQA h.SD;&O͟7+nykzeayH={ɏ#~@~  ,FI# $Hy!p9sP SlQ S]BS3O?9Cz 5I[lIݐ\N+*iD=ktSn'-o endstream endobj 522 0 obj << /Length 190 /Filter /FlateDecode >> stream x};@�%$p.$1q ,ZZhQ8%aaD)e3&SKp4C g0GgԂޠ1mx܎ cncv`3TJyĨJ6$(r&;;/Xy9pED]Kv6}zκOY8ˏywf.'+yWana Oq endstream endobj 523 0 obj << /Length 286 /Filter /FlateDecode >> stream xuJ@g"0y!SZYZZ(]-rvABs.ovI{F%t\tZSSc/ش\-iYqaqKM%ױ 9UXl订 d� ybR.aa �cX"`?5̆o,, ߫0Ȅg_RPg)$.z4/@ciJKJʓnyA u%�>@+ +0@:ɝs<#Nz3b:%^txۺ endstream endobj 524 0 obj << /Length 207 /Filter /FlateDecode >> stream x}; @49 �SZYZZ(f=Z"x�Sg7 ?2Aɥ ^H[]McajIj*UTNp>"՘VkQrtaQ d,ɹu|--"1^JBR̉*z&v:N{X5gS\Uo.Nb\ endstream endobj 525 0 obj << /Length 168 /Filter /FlateDecode >> stream xڕʱ 0+[| LBI Njh}x&A Ifz9mPkcaP,IkSע03:;|L EI+Er$ �4./ @'PE \b<<Iya9PpbpO)T< endstream endobj 526 0 obj << /Length 221 /Filter /FlateDecode >> stream x}Ͻ 0�C>B Zt vtr'utPtS,GB1EAA1$$wKҬ`[43\%4}r`^jijD1w5ޤ l. 0Nߚ`gTj*YO8:uȱqJꂽSyXND!uаڻ7ԗ:1D&/e6 xE3~0)<�|] endstream endobj 527 0 obj << /Length 159 /Filter /FlateDecode >> stream x31ӳP0P0b#S3CB.cS �I$r9yr+r{�E=}JJS ]  b<]``Q"? ?8 8{0u L?�` .WO@.�R_^ endstream endobj 528 0 obj << /Length 177 /Filter /FlateDecode >> stream x}ʱ 0J-}{B(u* ftr'utPt+G#t< pwxb1?p dsԍaw\XL@y B-r@) -=/4mVgu𤆚N-.Ѧt+.Jf{m?FN3w!ct1]a`/B' endstream endobj 529 0 obj << /Length 190 /Filter /FlateDecode >> stream xm1 P ,jEB`A'qRGE>֣<;B|?Ns42!Mgohu۶՞Lj-)tC*.G'}4!�r8FJp-27s�X;+YJ>!PD�hxհ#qʩe#\Y.D*~ps endstream endobj 530 0 obj << /Length 217 /Filter /FlateDecode >> stream xe=n0 ^ !Ȕt"YkMG4z0R :]ށ"ħ=,\'7O>i:aAOtL}eÞܖ[V($FFUG"@'C;MBMIU (5[resKMSCЩAgC4jFV"j"kJh+�bo endstream endobj 531 0 obj << /Length 247 /Filter /FlateDecode >> stream xuпN0/`<JUeTD$02G#d|P,'?.n\uۚPk^kozETkToj/ ׯԭ 6~9H$؀BzF{baIu=L1;<Ydسjv&`EbVIR%5?qqxY_0qUt.+ endstream endobj 532 0 obj << /Length 184 /Filter /FlateDecode >> stream x}= 0� kI NEzbIJS$.(qfc.1xIjsq$Uj"ۯ1)Fy#ҜN&"Yy 2$P5sΚʮTz)z@=qQg5椳[o }6 dcq endstream endobj 533 0 obj << /Length 222 /Filter /FlateDecode >> stream xm=N0_4{2�lXҲH@j D (GQr.L(4~sr>p>ܟq q<<v$@Jer5?\';=;b`dD+R*b(bb2L M?H@2KЈh)jKX^EjU:Ԫ/`r`Su8&]ix2UD6a]tKq endstream endobj 534 0 obj << /Length 187 /Filter /FlateDecode >> stream xuϽ@ ^H.1::htG K6idP@ 5E5^0PጙAKaRݮzNi)أ F�8/nO+y\җ�1DgiP->Ձan,Oz౽R0ʞ^ endstream endobj 535 0 obj << /Length 187 /Filter /FlateDecode >> stream xe=@!$p? b"VJ--4ں{4 Fiͼ$)%)]"c0;9߰jP(PlL񺢨v+Pt(<aSܻ!{;s5휠&:ԜR-0GEZ̲d0s?[<쟚5u{�)i endstream endobj 536 0 obj << /Length 192 /Filter /FlateDecode >> stream xM1 @'49(I F0X]09ZRY73las.O>t%ߓ1y8^(NIHdK*]87 vI%w9PpHZ..XM!/3(ѯz?Gh ź1n_*U JU@h ;0" cd:0&I˔dU~ endstream endobj 537 0 obj << /Length 206 /Filter /FlateDecode >> stream xmͱ0# $'" b"NI4)h< бZ{upФMGlL%%c<a:u%vG,*kJ(綋Z|=,SQ)bUg(߼BL!< +_A�-k/,PO5Nņ*\'wݛS8n̰֠|9/[;{{>4g WfY endstream endobj 538 0 obj << /Length 232 /Filter /FlateDecode >> stream xMαn02 ݒG^:DSD$:u@LЪ:DGˣ=D1>$N}q2QDcMMtR1% '3̶{FܽBيԂ4570ze(mi_,h[i[s?v%| ϛ'a73UVWhvV۩~rk endstream endobj 539 0 obj << /Length 179 /Filter /FlateDecode >> stream xm; @YL#8'p+U F0XٛQr)$㬈k ?S`O'QD4>&)"fwļD$E3\|=ɗS)bY� LTUB3K2Pmr/*qOrZv_Ծ~bnJ\ \T endstream endobj 540 0 obj << /Length 244 /Filter /FlateDecode >> stream x]N0 @qK?j`Jc N'q@p%~J>a)ODiVkh)Y5a}[mpaxfV;x|ŰÖj?D˃yp̓gYYC;@!&_@b�˔?ճGefoT8g~цv@Q6tozazkz4Ut_)ΔQMEј�w>7x@ endstream endobj 544 0 obj << /Length 171 /Filter /FlateDecode >> stream xڭ1 @49t n!he!Vjih!kW/#SL N 4!6a؀Zt;(vfA(:"}BVsJBp܇#Nxr #u_[X s endstream endobj 545 0 obj << /Length 171 /Filter /FlateDecode >> stream xڵ1@5$p,HEVJ--4Z8 G ЙLi q8Ew>$rAnA0JAo nx]A '*U>QPjĴc#1Ș@(rt5tQ=P:R/t endstream endobj 546 0 obj << /Length 105 /Filter /FlateDecode >> stream x3532Q0P0QеT01U5RH1*21P�AsDr.'~9BIQi*S!BA,Ճ�,r �N[1 endstream endobj 547 0 obj << /Length 233 /Filter /FlateDecode >> stream xڅ1N@ PG)"#ɬ&PFZHPQ ]"qt\c0e~졁?vlON7Q:9 Fb/_8ZI<Nbd1Z^ߟoo.$}ǝ!Amuf<dj+сjmʚ*.c�mCf |g59-vU]__j\Y[tԚD|"fVd#7J t endstream endobj 548 0 obj << /Length 244 /Filter /FlateDecode >> stream x}бJ@9R#d^@ kL!he!V`hy<Bʀˎ&QP8S|0fݚZL-gF pkЭe׬Gϼ︺pu>Wݵ?qtr; YtblqʧդSuLUG2,RTL:*]-:o~q4bi4,GvHqD CJT![Q|-< endstream endobj 549 0 obj << /Length 222 /Filter /FlateDecode >> stream xmN@D6 )U$\ AE2EHtS .]XY@͓vvfk5zuK6T9^~?=dJxF u }J]iǨ{l3P͔,N.]r |71Ղ]g?.H??ҙUz6 Er_n^�] endstream endobj 550 0 obj << /Length 259 /Filter /FlateDecode >> stream xmбN@%L#케rKZL0Xy| _7x-?kr1J_1L/7 M[OoT7(\<Үn~zrwwŞ=?z<QgcL&#eJ?fn?ߎ뺳nr12\Z8L죓`d2 9.بj} ަ jV gqg]Ԕ6jb7xEFĠ_حl3uuG endstream endobj 551 0 obj << /Length 221 /Filter /FlateDecode >> stream xeN0 u%p~Hr'*EL &C0G#t)lSۿoUZ"Hgg5{|~x+}+/AwDDBdT9ՙ6U&L6ZbHAW FY1_?(dhB̐2 Cfr\3[5:U��Fq "⻎ Fx endstream endobj 552 0 obj << /Length 307 /Filter /FlateDecode >> stream xu?N0 ]uG/�mQlH017#V(=BKv*$OkO:j#;_96tzq7`}Ga}%qkz{}zwsA-{o9'�`fGy )OZX#Ba `o ``C*BbQ>*g1O`ӆa$ "ҧ[bšriΖ,JufR꜊* h2k f{\'iגr>1f2ǢW,2f7_LLn1� endstream endobj 553 0 obj << /Length 207 /Filter /FlateDecode >> stream x}= @i<sHr0Xur4#XF\2ZF7eIRL= <b:.e(b4)FٜΧbL'N(`6!0䵓?5n?ly?oVa|\Bުs˶Z*ڶy{|)jlT [hlT 46*vl[iK|ϐ endstream endobj 554 0 obj << /Length 178 /Filter /FlateDecode >> stream xڕϱ 0sn'0M[[V08G#ttU;QRDtLYL{'L2#_bw ZS)*z@U,Qmє�7xw4_dX�k$?[@n@ G\C̕u!U837>_0 endstream endobj 555 0 obj << /Length 162 /Filter /FlateDecode >> stream x3532Q0P0b33CCB.c �I$r9yr+[p{�E=}JJS|hCX.O {LA08v0& =hAԃ d}F%\=�mh endstream endobj 556 0 obj << /Length 216 /Filter /FlateDecode >> stream x}1j0`xKt86pR@3e(Z5c( zҳ!C+eە"yn)pǣ3'[<{I_'Nʗvk_7('B<P; �!,G GIJHIPjhŠ]Ɛ\fa:Và'f$ ?U?~ endstream endobj 557 0 obj << /Length 198 /Filter /FlateDecode >> stream xm1j@*x%¥V *v¸JRHkh>AB^fV)~LUx)d*{y-V; ^yײ{e'|^{)5r*8se%5(Et){o `{VfdNjW|n.Գ墺p%Euщ,7>F`1wCG,0w endstream endobj 558 0 obj << /Length 225 /Filter /FlateDecode >> stream xm=N04�8fH"-D $(PRv.]X#!|ŌgyoOyÞ,n,Ş f2w\2>n.ؒ9#zЈ�-1p҅FcFR+M*ȝaZ~)\?(ߴa<-֊w%<2%RTN:ȱP5772L n endstream endobj 559 0 obj << /Length 266 /Filter /FlateDecode >> stream x}бN0 �P:TO�[+D$�G1!j#8vbiSB'쌊S|b- m6*.$t۫3J6}?�%wY X7�:([x0/Xw?.1}Ď~4;V!0X^G`Yi|3KK[�륰ӃrIsz ãFav+_ endstream endobj 560 0 obj << /Length 203 /Filter /FlateDecode >> stream xڅα @ �B~\ N܂'+~B1`A%!DyH>-Pd|Mt8E'ZKUyAoJ4!6�B0s>a~1[GBTG@ \hYc&W=倢'ci4XQ\K5g)YMbW) k: endstream endobj 561 0 obj << /Length 229 /Filter /FlateDecode >> stream x]1JAE`]О^5XWpA#H ޣQNPLYb" O~IgD^c^up;a|<`o}~|b_S¸} |N$@'" CCwDǦX]X<M"J= ЋVM67xQmKҠk:Άj*9hwcf{ endstream endobj 562 0 obj << /Length 199 /Filter /FlateDecode >> stream xu1@PL &T$&ZY+h ތpJ 8FHO!XccQ>Fp4 1|*]QpCi 훑𷂈Z~]K9@ae%d p-5J҃J!Mq^.q@GaOkn endstream endobj 563 0 obj << /Length 200 /Filter /FlateDecode >> stream xeͱ 0+[|VP Nj}EбCiˡBKd0L)1ok)>XJ쎘h֔Z4s)t9_h4S$oR^2Ӱh!l P؞ZɅ'z3Ē@mP,g({b_%C>G ׇid endstream endobj 564 0 obj << /Length 242 /Filter /FlateDecode >> stream xUϱN0 �PW"y'$_@Znt`b@LXnRB>cꌝ "5q8g筭lߦmcj|vJݝm83ͅ}m"(>(g@@ĉiB$}J|D| >&A2 ʕ/*O}b1rt1'IK?tQ fTr%?B-z."&~he )x-�;w! endstream endobj 382 0 obj << /Type /ObjStm /N 100 /First 902 /Length 3359 /Filter /FlateDecode >> stream xڽ[K7qsJH=F�;^g$ b:Nfxe~Tz{ vC(G81\,( qL8Gǹ\p9;Wr }ceF39t-$X-^\ QOQRp#9D%. &qBПr"aI 3 BIV J 'LsXʊp}g6ib,ʄ~њ81/~h!fxf08eA3֘Or!7YkSl}ӊI .X%٥IH. M Ǥ Du)CZ֚J׳K5PO`/DRmNXdr[$6K+) kn WS\ 4 R+gBP!TČT]*\HLЧlú֒־V* (fZj2xϦ=lݠX]N)%5v41Ǻ WRU5ehTJ2@4I!?Mm, I&3\ɓj<qËdGܨ́M57wL@LDK$nj1ps}rvniڝ-ȸ?oWxuG;se1zw|y U=gh/ -o@B{{e.e, z߷ #ے5y[<د4x@'R T>EHӫkP|tg|1|wybxv}zuFg_o_Q11gPAJcsLr$ 6Qt7?];ӟ/o׫O_`vׯ~5/ue"odohu`Lr)<aV7ܚ:״T vU-A\ р̒}MAW֦'O�rO?Ç|X_|\_7˫wW?y~~| 8sRb<5Z6[]7:cT3V$E8S[{vNK:mP$wtZ:Pws~Nf^ޢ͹ӣN:=ӣN:=N;=N;=N/vzӋ^b=s;I'tz}i-ۜ;=ӓNO:,ۜ;=NO;=Cxd'a~K@ߔ)gٛR`,P,@`#m('d BKzm%A0QOȄ"ɖ݈('ZϪ'd`[p##4-GjT+CLSlz ܳ%DT@ <JD+[H#d@<E|(UR ,}}gs5Q�*Ki18aHKR,D0QvVj9@9c:ăOh> փg@0ɉ%)CD4 Q'x@ ;FMFW(3YfwQHl<Eb.U|('k"0R@RbwP#gm-rLRhDFT$V4Z=w84~*RLjtT<hhE <ϙEoU3LLl3t[d)ϵrv) RLݝ ۱NM"YfmmX:Z \4ٷ5_B~i' 1dnB[f؞E1Pds+Gâe^% f)$LՍTu0]qز3dRĚe@>> v�%)L�1lddTfJy, %D0P+(9~|j4ضJ)-ȧGl#ݪ;!H틵m 8Ͱz`5N訤2"˂LEhg!,S$V5b)1@c yXՙxvT6[FD+mO0xa/0唆ӪQV[�S+t@TW *y C"�m0BL]S&bYePR�FV}c"oF̊ ޢb+ZM_w_E\ h`ڶ�.THDCĶ#}\݃8<4w~)r_%NL@?Rcxn_2 K9x`&mUpf\آdGߖoV /7VC lYVpdYlqo@Ycͻbno0w;կX_#9z;ڷy_o?識4zwlGFiB;/euC3,0ZS|NeXZ]NKB�~eۚtX"MijhAvӧ-T:pD'N붵aY+mUՉVh:W70;ж|5Z 454kl+&Fn#DB|jdPm$˶�)7�T,BD&Kޖ-BjԺ٘%xcxcAzBʒwciߩF`dS2fM ox<nZc=wi{g4GɂI]JY<b BF X*g�zI..چz2cCcslTώtꙚ_ l-o~uSMH_GxbKt#!HP?6V*tG*|ƠÃ桖p\FIz~~bA<xa?M�ǨP}'m5�ee'-w -wHS F,qN>v b<AyА1^&۟07lKF'l0"h#JɈ�H!OačdOwlGwJ4҈_VGqJ0J#oX4A TH;2RTLxTwT9lf;<am۬UcsA^弃u5ָ1#-/-/V`~kbǦ1Y�7Я�?Pa ::T$cx޺}>¹=JS75?E endstream endobj 569 0 obj << /Length 143 /Filter /FlateDecode >> stream x3532Q0P0P54Q06Q04TH1*24 (s< M=\ %E\N \. ц \. ?aC? ??PՓ+ �.q- endstream endobj 570 0 obj << /Length 99 /Filter /FlateDecode >> stream x3532Q0P02�F )\\@$2ɹ\N\@.}0PRTʥ�(Dry(37�73pzrr�{ endstream endobj 571 0 obj << /Length 284 /Filter /FlateDecode >> stream xڝ=N0_"4>BMKiiY$R AEJ dD"9BVhqIw^6-o哚 6T+7=[;/먺綡ZTu7LkP@ݞb+"EFL@)mҍyd: ^{3zdb*D`F]fe_6/ֻ2XwClKbWN0;C˧4 Yb 9y1y/wc堙~G}iV^պ 眲RΚ0 ݦE endstream endobj 572 0 obj << /Length 205 /Filter /FlateDecode >> stream x}ϱ 0[|Fq+ vtr'utPty>JЂVCAn C>)NB<pmkq jZZpTvfJp4A!|ܚRieuݪ,;鷸"Umddgf$/qF+Q+]KC8ptj䐆ŀ "#$ʣN[ywa endstream endobj 573 0 obj << /Length 208 /Filter /FlateDecode >> stream xڍб 0�Д[ DZ N⤎S ;!b #wBaj/9A]FG oPjT ߂[|>^Wn\1ڹ^Wöe;>w"ȑbne!'pΈlr1wE@vؒi`b5olOkuV lL$=o endstream endobj 574 0 obj << /Length 244 /Filter /FlateDecode >> stream xڭбN0 `:TG_�ҖpCL &`J~> Uq,ĉ_]"hKZ_=n ; Z0+5RaK�~5C%'>;*\ $U+u+}e'}^ܧ_"�dj_V˿*'1S9}q2.Wl9ɒCТfeDE3vgZyٴfȅ endstream endobj 575 0 obj << /Length 200 /Filter /FlateDecode >> stream xڭб 0H-} LSZ N⤎Q;\Oh 䃻 jh1W/qz1pAf@Pki| }Qa|cpÖqA# KN2lɠw:RE99[CO#/Jǎmݐg'7ΐl9gXɣ endstream endobj 576 0 obj << /Length 158 /Filter /FlateDecode >> stream x3532Q0P0bK3CCB.3 �I$r9yr+q{�E=}JJS|hCX.O@D~DBD00H2?� Iy0i߀ZNĥf2TV? r �> endstream endobj 577 0 obj << /Length 153 /Filter /FlateDecode >> stream x3532Q0P0b 3CCB. HrW01�r{*r;8+�. ц \. A=e?0a``'d~�"$}6$.0hO$8,'W �k[8 endstream endobj 578 0 obj << /Length 241 /Filter /FlateDecode >> stream xڝ1N@4M�/R.JHJ t(>BqLM󊝑v*.s|Q傷}-1e&oﴪlؖdL_;2;.Ȭ5&r2x:J缮4U3izdS!a1O*�.}'%6+_%tlsp,)9SamG{Kj>t{}Ȫ}M z�G endstream endobj 579 0 obj << /Length 115 /Filter /FlateDecode >> stream x3532Q0P�b3CCB.cS �I$r9yr+r{�E=}JJS|hCX.O7@�s ?F?H\=�u endstream endobj 580 0 obj << /Length 128 /Filter /FlateDecode >> stream x3532Q0P0b 3CCB. HrW01�r{*r;8+�. ц \. 000LC"A"YFsĐ@$R@?,Փ+ �V~ endstream endobj 581 0 obj << /Length 199 /Filter /FlateDecode >> stream xe1@5&pj,$&ZY+hGqblGN}<p.;OF9spu ny7.|G PA?PI6^-ʘ`W7~Ewٱ0Q fmmmlVR58W. JG0+rc_V`тf endstream endobj 582 0 obj << /Length 177 /Filter /FlateDecode >> stream x10gLxжXX &v08Fg<G <`v2$)"SUr¢8((kR(J:)g%A[�=D:4Lhn��&~^i/c.ĭn,c endstream endobj 583 0 obj << /Length 197 /Filter /FlateDecode >> stream xڽ @ p؞:jotr'utPtnG#tt(K>ȟK'S7xp<k8^{HWQ4~{!-6 q{B9QgLEDF31Koc;s@uQVOf.5̤ϖ9_ݴN:+qhŭVWytl#ӗh@ endstream endobj 584 0 obj << /Length 215 /Filter /FlateDecode >> stream xڥϽ 0H>AAA9>ZL@3wS̰o8xp|)30-l1Y2rf3ǝtC)"l˒PK^Q<vYD;W?o)d<iz89'l&"uQQ}KTwHlJt>tJ*X endstream endobj 585 0 obj << /Length 259 /Filter /FlateDecode >> stream xuJ@'LyMr.'BBNK Eኃ()2dოgw\nZe+tyiZtW?zEN>?^_K^  )t"Y33BsrA㙢ƑJF :jD.$ &0X@ X {i6zCEPL> �VlqZ`I'<EHf|F[(<|,ޛ endstream endobj 586 0 obj << /Length 225 /Filter /FlateDecode >> stream x}1n0 Ed0EG0/ ԡȔdР7 dPK#O'O *k!XnKVz>uөg^3e݋}N7Oo#XnkR 0,H"`nX,2d;F)ԃ"G ٦)eC$9َ}r9H>Gime2bֿɯꢻNǀf endstream endobj 587 0 obj << /Length 223 /Filter /FlateDecode >> stream xڭ=0 S1T#4T HbF(=BN�1#2|QlSL``: Ҍ f}a^cstz�=^NЀ`|U|+Q܏JfL5IbG|86*Um%1x(VDFN{ܙmw^{Ǜ)5xu Vϗr endstream endobj 588 0 obj << /Length 208 /Filter /FlateDecode >> stream xڕ;n14s5,r%[D ")S$"r4Gp`(RF}?i7<q\}8YŊEg Mvo|$x_#@݊0"g"HHTMTQ_2)D`o=D?1ΣT*\C i JB! e̥Jփm )a* endstream endobj 589 0 obj << /Length 232 /Filter /FlateDecode >> stream xڥ1N@Y4�78n- T)UL(ԛ,IdU<iJ3zTJ!7rd\H !Xa;b;C̶V۩<9) 0&L�s=AP[L0LTuÖ#pOIOut;QV?kZ]qoz}Vmh m_h>q n#t-l#k�&ĖH endstream endobj 590 0 obj << /Length 225 /Filter /FlateDecode >> stream xu1N0E49BM,)@T@"萒(9K. #3?pW=w<~(ё6[;ϝFOْSxϟ_dw7qB#h%^J"s-,&ï& M ugTi: d)ȧֿHee_3 Y}ETԼ4rs$jYh%t;#�k} endstream endobj 591 0 obj << /Length 166 /Filter /FlateDecode >> stream xŎ1 @EH!%q1[ZYPUx!㎝Vd7<[W-SÉ@fޒYFLXr;)svdJ9{ %_@"-0*rࡐZ'pGb4"mz!IoMSK?7W endstream endobj 592 0 obj << /Length 283 /Filter /FlateDecode >> stream x}J@Hfa4]<Vr YlWX `D9-4oɿ3eP=յj隣{^u\\:ݙ{z|bu~*.r冻D6 !#"%I\(3}Cc{mPD߄%:N4@&qTDMK2v ;Q9(nhK Idvd="Т>y &ɹf{[ӎ N4:58x'_'/t endstream endobj 593 0 obj << /Length 178 /Filter /FlateDecode >> stream x= @ L2'pH-,J--ףy2ŒmkO1rX54])/ UԎ URvL,=&dk6>s]PFX`* tB &66aQְsdmN|*38w ]ZZ錀 endstream endobj 594 0 obj << /Length 141 /Filter /FlateDecode >> stream x3532Q0P�bS3#CB.c3 �I$r9yr+q{�E=}JJS ]  b<]0000PX?Po?=``D� x�r �"cn endstream endobj 595 0 obj << /Length 231 /Filter /FlateDecode >> stream xڭοJ@=R#d$G \%'BBCܣ796[D@~9nֺLҮFR\3dQֽTvRT>o_Z_j7zh}+F e>XLΙ垞tQ8rnl`l`Kv❷ xuw0$nz_,ǟM 7ݲ]X`DtqY/W ^ endstream endobj 596 0 obj << /Length 127 /Filter /FlateDecode >> stream x3532Q0P0b33CCB.cK �I$r9yr+[r{�E=}JJS|hCX.Oc`'\{0 ?0%\=�Rm endstream endobj 597 0 obj << /Length 175 /Filter /FlateDecode >> stream x1@O75pD ,ZZh:JD<@J ˆbb%3򎃮i0f3c3n[6DM8eŠ8NDRrpEEVn4TKUT|(UBMҸHȿ(?� endstream endobj 598 0 obj << /Length 170 /Filter /FlateDecode >> stream x1 P t*d |BB`A'qRGE<G~"^!O2,3+Ze.ʱ JO37؊RS6JnMKnk(QS<Ʌ =!8 *TS C)"=7K5g8E~Pz endstream endobj 599 0 obj << /Length 202 /Filter /FlateDecode >> stream xڕ=@ #0e't$$RheaB5pJ 6&Wd^狔cy9ƹjzPRei.;-+RGN R[&U|H-+֤|Z3/PDx"_  {MءlQ5򃠳RkD0qM]Is Fk,Uel m*:9n endstream endobj 600 0 obj << /Length 235 /Filter /FlateDecode >> stream xڵ1N0EEirqd":K" * D ra8 j$\<̟|Ҷ9~JSJ/q]Ngr |y@T2bH!iY)0DI�~B& #;NvWV #tb9w?1&쵹+'KUwι9mkQڎHQ*mAi7t-} endstream endobj 601 0 obj << /Length 172 /Filter /FlateDecode >> stream xڽα 0@εIG882:Ht>85g<G5oHYc\lːIN͌Od>"YJq&S"EE\-u׋p*X&.EZ7-}K7-^D_~417yi endstream endobj 602 0 obj << /Length 227 /Filter /FlateDecode >> stream xM=N0j K.�Yo?)@[%h(pGH"1&+Ai4絻RF.x/~-O_yUì o[^fv'^TGnBe*TRUCQf4.,�B"tF) F#a~̇ Lͥ2~"1e`9Cf1YD5- VM4kcЇA-ʭ endstream endobj 603 0 obj << /Length 177 /Filter /FlateDecode >> stream xڭб 0+ 4%q- ftr'>#t =/u AIn(ƚ!kxB%N_C!Q-$Ft9_Ռ$h+3;tA|y=8ނM?`|ҋ-xI ,vQOzxE:Vv܄#Jsk|jVmx endstream endobj 604 0 obj << /Length 165 /Filter /FlateDecode >> stream xϱ 0]r cptBp" hX ;;rpcHQT2kv%d‚ϧ˞L%SrPE^ />" _*?_^ӗw/ķ=yD-L@@+z]l endstream endobj 605 0 obj << /Length 201 /Filter /FlateDecode >> stream x]α0# $XJD1D'㤎]GQx!Ԥ%Coƒb Ly۵-(v$S+NQkg͂g\:]:r9쒮 < �د׼C|V{ˀʠB6נ?b}gk{[[\2e endstream endobj 606 0 obj << /Length 224 /Filter /FlateDecode >> stream xen1 } p~r$7 1юZ(yc+ d/dj<JvF ~UT /whZ4+Qtk9~oԠYҮzݒZϬ2+ #*�> I8&,‚}bTl+bY\2L5N{Gs/Pܠ 1?3W-%_} endstream endobj 607 0 obj << /Length 251 /Filter /FlateDecode >> stream x]1N@б\D&Gع�؎HT+  * ()@*>Vu,7O?_f竂RlSqAENObQ4xz|M=%&>ǤgL6aV[2(̭v 9LJt'XX�=Y�jUI+.~ЉgPws+CF`CHeD%;#7R NJCwX}xU~ endstream endobj 616 0 obj << /Length 146 /Filter /FlateDecode >> stream x%1 @E/d y+p2dbBB`6;%XZ<\W%Rp9E^h1ӞjvȜj,0vEzP`K$%b$$T$E d+oѥ׭�{/ endstream endobj 617 0 obj << /Length 197 /Filter /FlateDecode >> stream xڍ `4w/Pj)MPԚ>#46_Gth =(TWC# |=yrϭ3;/ft싳^l,N+=u-',]ƠBR"/ w]OJ Hѐ4MJ0?_9.6վэ-iN͋eVL endstream endobj 618 0 obj << /Length 196 /Filter /FlateDecode >> stream xڍ= @ GbVbh%GH"/Vef Ʃj?8$C(gbg(X]r;fwPL@ | ~nF <z/@:Mrp\3]8[FihHOҙAHVxuO endstream endobj 619 0 obj << /Length 197 /Filter /FlateDecode >> stream x=;0DQ m#'1�Q.@T@Ip'Xz&p:SN8qjhBq&,d p’r^ %mW|O w=ْ\%NfN‚R8Ԏ;?]Aq !帿;$EC3NMYBvҶ6n* �UKe endstream endobj 620 0 obj << /Length 194 /Filter /FlateDecode >> stream xE10AH M�R.@T@I< )) bex{6G9avὡũ4!H#8%5))z -lH1r-9 "HE H$;5ƚ2 @Ll)a7lI3G+�lJ endstream endobj 621 0 obj << /Length 157 /Filter /FlateDecode >> stream x31ӳP0P0UеP01R03VH1*26 (Bds<͸=\ %E\N @BA,B�?Q"A=h�`�;�$@F0A8&TT#`x�xrK/ endstream endobj 622 0 obj << /Length 180 /Filter /FlateDecode >> stream x31ӳP0P0UеP01R03VH1*26 (Bds<͸=\ %E\N @BA,A<@ fČ@ a@@D�9e :ɑ� $aU?pH\\\�o endstream endobj 623 0 obj << /Length 179 /Filter /FlateDecode >> stream x31ӳP0P0UеP01R03VH1*26 (Bds<͸=\ %E\N @BA,B@0�"00ԃ@D0� @a"W" ",XL/=  p� IS�p endstream endobj 624 0 obj << /Length 106 /Filter /FlateDecode >> stream x31ӳP0P0UеT01R5RH1*26 (C$s<͸=̹=}JJS ]  b<]�L�!�W51 endstream endobj 625 0 obj << /Length 110 /Filter /FlateDecode >> stream x31ӳP0P0 )\\@> IrW04� s{*r;8+�E]zb<]@� 5 \\\�deX. endstream endobj 626 0 obj << /Length 142 /Filter /FlateDecode >> stream x31ӳP0P04S54V06R04TH1*24 (s< M=\ %E\N \. ц \. ?aC??@P`�4,r endstream endobj 627 0 obj << /Length 96 /Filter /FlateDecode >> stream x31ӳP0P0@P!Ő H(`\.'O.p�U()*Mw pV�]zb<]�\=� endstream endobj 628 0 obj << /Length 162 /Filter /FlateDecode >> stream x31ӳP0P0UеP01R03VH1*26 (Bds<͸=\ %E\N @BA,<�b@N ?8�$D D`#2f2X3Iq,63� *@'W �yK/ endstream endobj 629 0 obj << /Length 104 /Filter /FlateDecode >> stream x31ӳP0P0@dbUeh䃹`\.'O.pCC.}0BIQi*SPE!'EA0XA0Փ+ �9-I endstream endobj 630 0 obj << /Length 157 /Filter /FlateDecode >> stream xڅ0EkHO-DD'㤎]O:2bg'g/18ǂS WqY2˝jCHo mvx=7~ &ĈdDVvUr9+G^‹aUnF;~ZQ:?8 endstream endobj 631 0 obj << /Length 111 /Filter /FlateDecode >> stream x31ӳP0P0V04W01Q0PH1*21P�A#CLr.'~PKW4K)YwQ6T0tQz ?*�1pՓ+ � JS endstream endobj 632 0 obj << /Length 102 /Filter /FlateDecode >> stream x31ӳP0PP04W0T02VH1*26P�A3Dr.'~BIQi*S!BA,B?ĸ\=�E:( endstream endobj 633 0 obj << /Length 118 /Filter /FlateDecode >> stream x31ӳP0P04P0"sSsCB.#39T*9ɓK?\ȌK(ΥPRTʥ`ȥm``P �!\`߀ Apzrr�]7 endstream endobj 634 0 obj << /Length 172 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.rAɹ\N\ &\@Q.}O_T.}�gC.}hCX.O&4Ŀ�,`ꀐh2B0 0`@?D0pzrr�V endstream endobj 635 0 obj << /Length 254 /Filter /FlateDecode >> stream xڍ1N0E"49BD.!ҲH@Q V9#Xqabf4ҷoy5w|pw Raͫ~yzH==US53UKnC#[J  K(R( 4]7^/_2 (`\ <Lx\XgA7A:HÝְZjIKj)! "chI(QUJ{շ1Ge/]tG߹< endstream endobj 636 0 obj << /Length 190 /Filter /FlateDecode >> stream x31ӳP0P0bSSsCB.�1s<L=\ %E\N \. ц \. P߀ J2~~d|"N�`%값 hL F'y�,$33oAYՓ+ �H06 endstream endobj 637 0 obj << /Length 198 /Filter /FlateDecode >> stream x}ϱ 0 [|TkI Nj}>JcҘ 4蠄|4;.ˇ)Jq)+di#  3 bnA5o3bDTYk[z^DyÒ1 <§QSHhUsjD0N/QG<T]KDbh@C63K[xGj endstream endobj 638 0 obj << /Length 230 /Filter /FlateDecode >> stream xڥбJ@/L i +P<Z%r֝k_ >ysQ%o镶={[r\/䶷\C#;"L E(JdG)23!_#2C[�{GE{ʐ :Z2 fFb֘9e)QSFO?V2C鎾?9ru endstream endobj 639 0 obj << /Length 197 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.C �I$r9yr+r{�E=}JJS. @-\. 700& @Y4$)&?H L2A :0Y&q RbbH.C _@|A!� HC, !�݈I endstream endobj 640 0 obj << /Length 149 /Filter /FlateDecode >> stream x31ӳP0P0bSS3CB.C �I$r9yr+r{�E=}JJS. @-\. �$BփI uD6`D2JOĥj2|$(47Ae\=�WD endstream endobj 641 0 obj << /Length 141 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.rAɹ\N\ &\@Q.}O_T.}�gC.}hCX.O$3``'Lȁ|DAjD  \\\�, endstream endobj 642 0 obj << /Length 230 /Filter /FlateDecode >> stream xڕN0/?BՅv`b@Lб $R_.jKŊ-}oﳻͦTИJr&7R+Ly?ocv~K*^�d`dPɑaDZN{8;@Ά:0GdzT 3#'d!Q M4 >15Ȏ×t*ć5 endstream endobj 643 0 obj << /Length 114 /Filter /FlateDecode >> stream x31ӳP0P0bSS3CB.�1s<L=\ %E\N \. ц \. p,~BĄ'W �NP endstream endobj 644 0 obj << /Length 105 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.c# I$r9yr+q{�E=}JJS ]  b<] 0 %\\\�6Qg? endstream endobj 645 0 obj << /Length 231 /Filter /FlateDecode >> stream x]ϱn0` n#�' v D$:1NClf1t#4Cd?Ka@?>ό/�x7e`+/l2 .|w9be;U:.Jp΂Zг j@AR&B n ~x)[yF^}lEƪ# `"P0~? endstream endobj 646 0 obj << /Length 126 /Filter /FlateDecode >> stream x31ӳP0P0bS3CB.rAɹ\N\ &\@Q.}O_T.}�gC.}hCX.O``'!P:'`b\=�jo endstream endobj 647 0 obj << /Length 201 /Filter /FlateDecode >> stream xڭ1 @4 \kP1),J--!9D,,T]S[̃3nQ*9zK5.sWj9!!qSdaV o,cP$nPPBz@Q(>Zll/5.K=&Mإ(o9)[-_m0v`fs8 endstream endobj 648 0 obj << /Length 199 /Filter /FlateDecode >> stream xe1 0-wӖZtP*AAAQPPRo7iqpT I( 8{~B&6}\9Ol[L,7@g@GEq;>:@8w^@8@X&as!eV^zH4 6Q25<Jφ?֮ڪ(hWz2H;z)瑲&0 endstream endobj 649 0 obj << /Length 184 /Filter /FlateDecode >> stream x͐=@XL #V &naRK (҂.C l}/N竌BJh&)^PF ] 厹Fq(Eu1 }C$QtQZۂgmJ9Հe 7Fд�?�oaF k ,|_F&h endstream endobj 650 0 obj << /Length 182 /Filter /FlateDecode >> stream xڭϱ 0H^{ӐZZ+AAA(}$]8N KM9&xg,\Od+ f.S0~ ,Ђ)qo19/"jB.P;UuDF 'aybhF4j-iMːO*"`a oƅt endstream endobj 651 0 obj << /Length 218 /Filter /FlateDecode >> stream xڝн 1 � Y|;? N⤎磝"b/Y>Jڤu)&cjiɈZ=qYh>&xޡG*hɘR.� e�ى/".Ҭt ҪwVhO/o2C xBbMn7ݥ| "Ԁ3ï>$$J endstream endobj 652 0 obj << /Length 250 /Filter /FlateDecode >> stream xu1N@E'rai=1IL,  DѶ. (ig?lncQiں'Tl=yE&lk\FZ,6KNZa| 9|t5iûH Jbz<rd'0 (9qp&8 %?cFi=H^Q #t)g/pxLkDυ3zA endstream endobj 653 0 obj << /Length 127 /Filter /FlateDecode >> stream x31ӳP0P0bSS3CB.�1s<L=\ %E\N \. ц \. D?`OY$$ ;R?$XՓ+ �VX endstream endobj 654 0 obj << /Length 174 /Filter /FlateDecode >> stream x1 @ ) fa n!he!Vjih-GL2 +7&.&RY S2sjOƠZKFe7?/4#ڂJ"nݯ;QO7ZB؈U$fMYD@ �ϝf+;|WW endstream endobj 655 0 obj << /Length 197 /Filter /FlateDecode >> stream x} @\|jU$A:uNձCQWQ /mU%v?,Ŝlriz mgCsb ۓ"[YyAm }$E'}2FZ_V7W?Wei f )XP>V*5yMg9V/zVJAf9'*LCx8 endstream endobj 656 0 obj << /Length 210 /Filter /FlateDecode >> stream xڍϱj@_pK@{98Sj@-48 -rpnA0f#VX܏]і1ey8%dIL2~Ar<"9hM锳AitJwe�B# LX6vs`RaF$i4 ;QWytExݭ'{gk~϶,O*$=t %~ endstream endobj 657 0 obj << /Length 242 /Filter /FlateDecode >> stream xmбn@ �P#$/ "L :vhծgO@@$2Dv."PtO h"+4}ih//hMм.tI?hfs ,hRtA אLZ5;�: Gk?ޱR/R7ux;xl;3{gߺjmkxN|סuޔΚv:T-tjO;Q d,ŲZ8ݎ[+R endstream endobj 658 0 obj << /Length 201 /Filter /FlateDecode >> stream xڵͽ 0+ zO`ZE`A'qRGE6Go t(;T%w.z!h>22J;@j)bAjPjJ-SYmEc-wy 7R5�-!�l·<дM nܝޣtVWYw8C:rb endstream endobj 659 0 obj << /Length 186 /Filter /FlateDecode >> stream xڭ1 @ aM!L!he!Vji(Xͣ)ykk|x$ 0 S9|W<O<-m$[ؖ]vd7]$f6hE.) Ń FidjBT6-5ځRPRB *szGHv*R*5�{} endstream endobj 660 0 obj << /Length 220 /Filter /FlateDecode >> stream xu=N@ _b%79 H" * D[n&"ymafYy.\O:/wa\gVVOK{Ǵý~~|m]=(k}fϋ kEm&fhF hrá +'2ʉ3q4|PY؁0e齳s5\@e'XreSU4Q~MQd endstream endobj 661 0 obj << /Length 206 /Filter /FlateDecode >> stream xڥϽ 0+->Z+S*AAAѹ}>b$*.bBz:ԥVDJQܣmT;fiTTf3:; :Yc6\;lhkb⍹/N-Z6*p|ZX?4>usn tn �N2\KKv endstream endobj 662 0 obj << /Length 205 /Filter /FlateDecode >> stream xڍn1 ]1%o )$n@S ZYG!i _ϲ=gzp;:٨T6{hh.DmyءQvF0`80cf̱b9)zA}T$"'S|_Q((M I +TPGey?4dѸYz1_ S endstream endobj 663 0 obj << /Length 220 /Filter /FlateDecode >> stream xڝ; @ )i<BIJ+P5W rod7Qe`gٙz- iJ? [=ʛ{3=vGe;M@xh D&DTv!U־5ƚAKJ*2ۅԪ,\))u8y_yewŲ޽>sJE"b=A aS~�] endstream endobj 664 0 obj << /Length 216 /Filter /FlateDecode >> stream xu1N0E*ir ,-D $(VT@Iv(>–)VAaYO??V=ϝz`U6]oX?ݕvⷺ}q�E XXͨ̎p[P0LhB M 4ESDiDf( DETHIc %)>/~Œ\r/_})oG endstream endobj 665 0 obj << /Length 164 /Filter /FlateDecode >> stream x31ӳP0P0bSsCB.c3 I$r9yr+q{�E=}JJS ]  b<]300? C=`cf ?F%5Ƅ@.N%\=�CSt endstream endobj 666 0 obj << /Length 275 /Filter /FlateDecode >> stream xڅ=N@ M_�(E"T+*�AD \%7!H9Ec{BHLid=RI'tT%=VjIM}h=<|ŕԱh UXiSQy :!1{.g t<A9Nt¿ɽ`n [Y'(3@ ~sPoi5E,b6�y0ɬ1$V �ٺ[Lz #h&;ij$^MR} ^x?m endstream endobj 667 0 obj << /Length 165 /Filter /FlateDecode >> stream xɱ @ : Y k 7:9utPt>ZpcҘ(@>?1t>C1I0IF*x܂ڡA ʮv@F G` t>'C/fH= b賚'b6l Q"Di endstream endobj 668 0 obj << /Length 137 /Filter /FlateDecode >> stream x31ӳP0P0bCSsCB.cc �I$r9yr+s{�E=}JJS ]  b<](B` D00 aDHpzrr�ȧYA endstream endobj 669 0 obj << /Length 217 /Filter /FlateDecode >> stream xڭνn0pH' Q" vP+ċekdUGk?>48^iƏ%Ii?1B4,Ⱦr'd Wwc'/kL8TEk%t:u=|?Q ;DN d~U7 S[v0ؼ?bjv? k1N\*7V*=4#S endstream endobj 670 0 obj << /Length 123 /Filter /FlateDecode >> stream x31ӳP0P0b#S3CB.c3 �I$r9yr+q{�E=}JJS ]  b<]``? ×0? 'W �g endstream endobj 671 0 obj << /Length 161 /Filter /FlateDecode >> stream x31ӳP0�C CB.sD"9ɓK?\ĜK(ʥPRTʥ`ȥm`C}?  Yo`*?��!*9=g!@d\=� endstream endobj 672 0 obj << /Length 159 /Filter /FlateDecode >> stream x1 @бa1[ZYZZ(ZoG 2΢]<rArY;#b6uj Ձlj#WTnK늪ܭȠhHUE�[7(S�#d5"${?zn<̑9 ~qp%8} endstream endobj 673 0 obj << /Length 198 /Filter /FlateDecode >> stream xڍ1@E #0eV$&ZY+h+{4(- 㲘ڼOϛ$ͦ񄇚1'O6MvV6&U~{I7 ֤rkT dR" "/x"o"x Aā, Ң~~5oU9qNȩ9IR 3,hK` endstream endobj 674 0 obj << /Length 221 /Filter /FlateDecode >> stream xڭбn0bt @Y"QPNt@hycs U.ɺϿm˧ <qֲy[Ўl՜[kIӚwe SVAtZJ10U�Q"-DױÉ<NmAQ/%n:~DG9ir2ݘLy?RΘ<[S|\OOeҼ7FW endstream endobj 675 0 obj << /Length 172 /Filter /FlateDecode >> stream xڵ1 A i832VºSZYZZ(ZXYz#llXZO7荆d/9C;GtVibs0W,lQ9O=l1!洖}N�)!0Z2-ygg"(.0P5tŷAUɲ+Y0\%-nYW endstream endobj 676 0 obj << /Length 218 /Filter /FlateDecode >> stream xM1J`b`w.~7hXW0VbZ * vnUra!,ǔK-tgQ ->Gy劲p3%WtpK-Ϗ kxzX 33䎅rCF40@:b� #LɂY.dČ 曶AȺ lB{,Zxώ`1K{+orSN~o' endstream endobj 677 0 obj << /Length 160 /Filter /FlateDecode >> stream x31ӳP0P0R5T01P05PH1*26 \.'O.pcs.}0BIQi*Sm`� $?�` #�$`'0   Sd.WO@.�] endstream endobj 678 0 obj << /Length 159 /Filter /FlateDecode >> stream x31ӳP0P0R5T01U0TH1*21 (@es<L=\ %E\N \. ц \. `,dF }H<00g?`G"?\=�kqt endstream endobj 679 0 obj << /Length 174 /Filter /FlateDecode >> stream x31ӳP0P0bScKCB.�1s<L=\ %E\N \. ц \. 7P�& eJ``�$? @cg@%4*PFF2?F2~~F2?N7 H{ r �V endstream endobj 680 0 obj << /Length 195 /Filter /FlateDecode >> stream xuν @ <g(xAAAQPhrpn g7T =P%ciZ7qX(Hft:w(E(ƴ5&cJmZ\Ym?m�Q<0�d0w*+qkW[:K(VXeR~LiC6̂ p?R|< endstream endobj 681 0 obj << /Length 206 /Filter /FlateDecode >> stream xmν 0�C(vAAAѵͣ7Q|AwݤGr6&آt&=>'|z zzBQvi z0b zoU YUX)է-ؽFF'{DžyVJtlH!r&u]Ŋ;7RCSQ񋦠iwH>ʳh endstream endobj 682 0 obj << /Length 237 /Filter /FlateDecode >> stream xeαN02D%{pҊ.TD$: &�73Ea+RősƂ)eTQS9mr|IJҌ.kk* C秗{˫3Q&l [f۲cvӨh+켍 R PP�ÛLm55wۃQ?ڋ_"|v։&Ԋ*Z IM ]4O`9kb{0D>7k endstream endobj 683 0 obj << /Length 218 /Filter /FlateDecode >> stream xڥ1n@E?@#\ ^ c)ʅ*q"QQ8%Ŋ2[$r~y.9R3.#OcE_/T_ܙt_?g~)O)'o6`Pv*;k . , UPC< èzDNe{Υ]ɷ~+| 2%E_Iqhҁ x endstream endobj 684 0 obj << /Length 143 /Filter /FlateDecode >> stream x31ӳP0PbSsCB.crAɹ\N\ \@Q.}O_T.}�gC.}hCX.O@l``z 灸�C??P szrr�RZ endstream endobj 685 0 obj << /Length 232 /Filter /FlateDecode >> stream xmN0Kxe�' 0Y*E"L vd�(~wH`O,+¯.wZt7j='(IB??v7ϭo^x# `0#,yB=:F0A.O= {řs2t� 9FtJ:ZTTwHsͪTU!,)b")3t#}wo endstream endobj 691 0 obj << /Length 137 /Filter /FlateDecode >> stream x%; 1F;]]hL!he!Vjih7eIY@5`NKnn;[.>Yʬz8nQuĥ>W#D*L"QCĶ5e" ьwO)B endstream endobj 692 0 obj << /Length 132 /Filter /FlateDecode >> stream x313T0P0S01T0P05TH1*26 (Bes< =\ %E\N @QhX.O 27??~0?P`�G( endstream endobj 693 0 obj << /Length 192 /Filter /FlateDecode >> stream xڅ1PDPl Ċ1D+ cmq@IA;WL0 v xlagnEt4'g'Ty!n{<c Z-VS!)Q�]/70kXP)5bIKsrL ):)j` ?`Hju^Lv{F endstream endobj 694 0 obj << /Length 187 /Filter /FlateDecode >> stream xڅO; Pl {I*L!he!Vj)h-G,-$q̃T;LNuihuɗV'/2O4Ĭxq7 $$M | ,G\W{F9^ـ"J[|rY"ֱ4nT?pGrjݬc_e*[M* endstream endobj 695 0 obj << /Length 167 /Filter /FlateDecode >> stream x313T0P0U0Q0T01SH1*26(%s<=\ %E\N \. ц \. L@�$AD=$? ?@P&VV̌...SG;&.WO@.�n= endstream endobj 696 0 obj << /Length 162 /Filter /FlateDecode >> stream x] 0->KNZ N⤎>cbMN8>] y GGbO%T2[0YFK&pOdLSA<MB +bJʰ_Z>ZZFHW 2"L}Tߩoﻭ "Іֺ? endstream endobj 697 0 obj << /Length 114 /Filter /FlateDecode >> stream x313T0P04W5W01T0PH1*22(Bs<=\ %E\N \. ц \. a`?r �5ez endstream endobj 698 0 obj << /Length 116 /Filter /FlateDecode >> stream x313T0P0V5W02W0PH1*22 (Bds<=\ %E\N \. ц \. c``pzrr�lI endstream endobj 699 0 obj << /Length 152 /Filter /FlateDecode >> stream x313T0P0U5W0T0PH1*26 (Bds<=\ %E\N \. ц \.  @N5 D؁{! ?8�$ &>� F0Tta*`gr �W: endstream endobj 700 0 obj << /Length 175 /Filter /FlateDecode >> stream xڵ 0DQXK�'2҆  * D h%##6HWYM0p sf؜Tz2{XKf1)Kd*rdGR/RA-%a|ݠЂV$QoeUG+O;a endstream endobj 701 0 obj << /Length 171 /Filter /FlateDecode >> stream xڵ 0EQ  miCp  (0 i~ϧ{~37 <& ~9JϓJu }s7&xܟnKœ(4^Jq^.JNQr?)F#PQ1H)3R;;J~.؆xC?ZOYb endstream endobj 702 0 obj << /Length 104 /Filter /FlateDecode >> stream x313T0P0UеP0T5RH1*26 (A$s<≠=}JJS ]  b<]�'W �* endstream endobj 703 0 obj << /Length 113 /Filter /FlateDecode >> stream x313T0P04F F )\\@ IrW04� s{*r;8+�E]zb<] P\=�AQ@ endstream endobj 704 0 obj << /Length 148 /Filter /FlateDecode >> stream x313T0P04U02R06P05TH1*24(YBs< M=\ %E\N \. ц \. ? 0`77g.`r �j'. endstream endobj 705 0 obj << /Length 171 /Filter /FlateDecode >> stream x313T0P0S0W0P01VH1*26(%s< =\ %E\N @QhX.OXǏ?1 ɁԀԂ��2} pzrr�xS endstream endobj 706 0 obj << /Length 116 /Filter /FlateDecode >> stream x313T0P0V0S01T01QH1*26E-ɹ\N\ \@Q.}O_T.}�gC.}hCX.O A-4v@ ù\=�emH endstream endobj 707 0 obj << /Length 136 /Filter /FlateDecode >> stream x313T0P04U54R0 R M F0\.'O.pC.}BIQi*S!BA,???PP'W �,5 endstream endobj 708 0 obj << /Length 99 /Filter /FlateDecode >> stream x313T0P04F )\\@�$lIr p{IO_T.}�g E!'EA0XAՓ+ �; endstream endobj 709 0 obj << /Length 157 /Filter /FlateDecode >> stream x313T0P0U5W0T0PH1*26 (Bds<=\ %E\N \. ц \. @�#HD؁:Q'@&>� f0�d8�2�>3 df ��Dpzrr�@: endstream endobj 710 0 obj << /Length 107 /Filter /FlateDecode >> stream x313T0P04F f )\\@ IrW04� s{*r;8+�E]zb<]�:\=�{-= endstream endobj 711 0 obj << /Length 155 /Filter /FlateDecode >> stream x313T0P04U54R06P06SH1*24 (Xs< M=\ %E\N \. ц \. A��# ?0` @.WO@.�8 endstream endobj 712 0 obj << /Length 110 /Filter /FlateDecode >> stream x313T0P0V04S01T06QH1*26 (Z@ds<͹=\ %E\N \. ц \. � �\\\�A endstream endobj 713 0 obj << /Length 145 /Filter /FlateDecode >> stream x313T0P04Q0P0T05WH1* �!P"ɥr{�Ź=}JJS ]  b<],j0a||=CC apzrr�/ endstream endobj 714 0 obj << /Length 103 /Filter /FlateDecode >> stream x313T0P0W04S06W02TH1*2 (B$s<,=L=}JJS ]  b<]0 szrr�$~ endstream endobj 715 0 obj << /Length 117 /Filter /FlateDecode >> stream x313T0PT02W06U05RH1*22 (�)Lr.'~8PKLz*r;8+r(D*ry(01l;cNJ l r �\+ endstream endobj 716 0 obj << /Length 168 /Filter /FlateDecode >> stream x313T0P0bCSCCB.cs �I$r9yr+s{�E=}JJS|hCX.Ov;: PNF01`u@Qf f2J~ 񀿁�;'W �Ǟs endstream endobj 717 0 obj << /Length 251 /Filter /FlateDecode >> stream xڅJA'\!Ls ޱƅ+,J--;y4B[O"hWf,4s n,͡c%:IRc{l3yz|c;9?Tj fDTP&E{h+9G2D~>/BGE$E7~ }KvmV:$,H@%j}W}azH O#bA=b2~|0 endstream endobj 718 0 obj << /Length 239 /Filter /FlateDecode >> stream xڍ1N0Dg"o|$Q6ZZHPQ *!p!eU8�i=opZ-uC玝|H?Я\~4wJ3޻MÍ?ε/2"P<> ufA@5ã`cO4s1d1gʮɧ:eP~Kٜ-˺QvOh9X܅H$% RM Zlmb dr)}A!</}L~ endstream endobj 719 0 obj << /Length 184 /Filter /FlateDecode >> stream xm=` .߁1D'㤎]ċ8p n #~$(}L<L6y6-<vf{Ś\(]p9% ED-4�Ӟg&{!1q?\ PC�#AdZz4u ,iu8q/aoM endstream endobj 720 0 obj << /Length 190 /Filter /FlateDecode >> stream x}0K:#pO`i1NI4 Kd0FMj\ijx@½%\PPGL2P[2;|=7P~K<Ls 9y|9#l K#vӜ_[ZCN _CF,a8[NXTQ� endstream endobj 721 0 obj << /Length 218 /Filter /FlateDecode >> stream xڝ1N@4�QY AT (�Ar 3AzWJ_kN|y9H/vI'Zun8-)\ؙBwoVWg)6r}Gݚ3J~ ZTMa.)- o̤/`tR27V֯ifhh`+-RN]dvg9 endstream endobj 722 0 obj << /Length 183 /Filter /FlateDecode >> stream x313T0P0bCSCCB.c �I$r9yr+[p{�E=}JJS|hCX.O�D|�?b0 AD}&>� f0H0b!On%rv?�s?>  `szrr�ǁG endstream endobj 723 0 obj << /Length 147 /Filter /FlateDecode >> stream x313T0P0b#SCCB.c HrW0�r{*r;8+�. ц \. �   `|�$lthvb)،6 Q .WO@.�̌r endstream endobj 724 0 obj << /Length 145 /Filter /FlateDecode >> stream x313T0P0bCSCCB.c �I$r9yr+[p{�E=}JJS|hCX.O�H" �$`@CLmQD !( ,�x endstream endobj 725 0 obj << /Length 227 /Filter /FlateDecode >> stream xڍ=N@\4�PY AT(PR$ގk 7eUI"Q|{;5袥aC]8<r@HaV;z~__S~EO-5kVE*#TPˎaa'\Bكoҝ\Q4pf<`2ߔO$̘gD<gTIcfKo=uӖ�x3t endstream endobj 726 0 obj << /Length 120 /Filter /FlateDecode >> stream x313T0P0b#SCCB.c HrW0�r{*r;8+�. ц \. ?c4 N%'W � endstream endobj 727 0 obj << /Length 108 /Filter /FlateDecode >> stream x313T0P0bc SCCB.crAɹ\N\ \@Q.}O_T.}�g E!P E >Փ+ �HX~ endstream endobj 728 0 obj << /Length 156 /Filter /FlateDecode >> stream x313T0P0U5T0҆ )\\&@A "ɥ`l¥U()*Mw pV0wQ6T0tQ``HX`'$@DD?`AH?` @OjhPՓ+ �UX endstream endobj 729 0 obj << /Length 218 /Filter /FlateDecode >> stream xE=n@E.,MvNm M,#EPR%)SB9QPr.]lȢOLt&c&FRf1K~|<MәDH%_whPK}O4|3Eӵs|@F āA֤Ha8pn\]ϭGН-8j<\ 8hPHF=a,o>U.k9s endstream endobj 730 0 obj << /Length 123 /Filter /FlateDecode >> stream x313T0P0bCSCCB.cs �I$r9yr+s{�E=}JJS|hCX.OLŘN|�? ?*�f endstream endobj 731 0 obj << /Length 177 /Filter /FlateDecode >> stream x313T0P0b#SCCB.c HrW0�r{*r;8+�. ц \.  B`W${1y 01h͇q|Fa  l?`!'W �, endstream endobj 732 0 obj << /Length 194 /Filter /FlateDecode >> stream xU-@%&c 迨 P$u�[GEev K1h8&nL؃-;CFXA_>pi ?!�&+R"c(ɉ(N+ƵGSroW\"Ϡ+tIߣmśh5| dXB]/qs| endstream endobj 733 0 obj << /Length 170 /Filter /FlateDecode >> stream xŐ1 @ERxt)R-n!he!VB9EqW7seϨxAƘxң3U5ݮr 쀾"h `,T'uID x�/H 9 Zpqol endstream endobj 734 0 obj << /Length 174 /Filter /FlateDecode >> stream x313T0P0bSCCB.cs I$r9yr+s{�E=}JJS|hCX.O0"3�70`�H؃@`?#^^Q`Cƃ-Y  f $700 F"b\\\�wN endstream endobj 735 0 obj << /Length 209 /Filter /FlateDecode >> stream x1n0/ʀ! &HYj کC @9j1CNjKޠ{iˊs.y^,V\.x_ЉۜWH[KEԯ|9_do\g ƃHLd pLi'�Ai ?NI i&tZ0^gȅX{cY701<5  endstream endobj 736 0 obj << /Length 197 /Filter /FlateDecode >> stream xڕС0jrf{::"#a� e0XvtmCOh)T^ aLiOvG ֤FscT,r0ʖSiNfEN�`Y9�Q3pqNN3O0n ZJ4&}5ty+A -ؼ+ԀW2>z endstream endobj 737 0 obj << /Length 236 /Filter /FlateDecode >> stream xu1N@ E"a|$H" * DH$*\!G2HQwmT 娔DJsՠg?x#Um<>r\Iq+wn˜24wC0MLNLtA 9�a=tC68yF̛aO2/a<<A<$ql^~jcO?>&E>o�xv endstream endobj 738 0 obj << /Length 124 /Filter /FlateDecode >> stream x313T0P0b#SCCB.c HrW0�r{*r;8+�. ц \. @†H0 z(QՓ+ �+T endstream endobj 739 0 obj << /Length 167 /Filter /FlateDecode >> stream x1@G(LtYY +D ,ZZhq@IaGhf'_Ϭgɂ#}SqblF.b27+e=Z3bÏB&.ْ`9:Rs)U*H]J^w¤%HRQC�/~*hGo8 endstream endobj 740 0 obj << /Length 189 /Filter /FlateDecode >> stream xe;@!$p,1q ,ZZh.F5\5o2s? q98^}G|9^0vV2#kgdfAYL{NELi iww?>, ʐ ] xBi �LHʛ1VL0JRaVuZ-�Vi endstream endobj 741 0 obj << /Length 197 /Filter /FlateDecode >> stream xڍϯ P#)>tœ &5m.b_CYN wzto,NvE69Wh .-rZeD/@sL@56Mo%n} :}�v%$@FTiXz[V!zyM-+_X=Ey>J3CN.{K endstream endobj 742 0 obj << /Length 226 /Filter /FlateDecode >> stream xE1n@б\ M<'m JHqT)"*L(iRZt)GLᏱEW23ɢ}ɟ\YV>>xUs&Ւg9pzy^Jz-NS={kg`g?EJEAJ>.dt &JI0r熻qM 5.M_f[݆{GZ>_?WKq{ endstream endobj 743 0 obj << /Length 192 /Filter /FlateDecode >> stream xڭ= @ )"U F0Xmb aҔ)®p)6 GqBQ@O[SQ6{ t&NExޡ9OA q@#~8 ��7ŝm'ch/m:^[ endstream endobj 744 0 obj << /Length 191 /Filter /FlateDecode >> stream xm= @ x Ղ?` A+ RK E[)S,;h%Xfh< }:ex\T:8^pVQ>EmqF;)C}FE$� sXBט^Hȃ�@?|bezYETZ_q�-`R!a~K<.Kj/\ endstream endobj 745 0 obj << /Length 187 /Filter /FlateDecode >> stream xڝ= @g"#Xraˀ!N;GYg!BR@[]/w%ܔ|q&?,Lƹ�+x"ҡ@yRx -0遍~*?um�ֽr!0e] EӐ`%Ж*sz endstream endobj 746 0 obj << /Length 182 /Filter /FlateDecode >> stream xڍ1 @EIk9 n!he!Vjihh%GL2Φօ}g?ofǜlS>'t#k5?;2{Zd܆L]rBC\"iJzD=[5/jLAOQ~ߏ@B_Zh4J5Ϋ^RMuZ9uEJ endstream endobj 747 0 obj << /Length 193 /Filter /FlateDecode >> stream xڕα@ .<} L &`qRG;[pqᾤ 5)+H+9s<^&|XLפ*L,r0S⺡MNMC� $z11wx!"><Zi&N?>cH RaH'c ˁ:ѴmO, YK endstream endobj 748 0 obj << /Length 201 /Filter /FlateDecode >> stream xmPE4K BBrmM>}}V́;ܹiԥS=T'u9&a+NFF⻥OK+ VZ[( f#2;܃J>PDCv@Z }•cC 7'* 4u.7mp b2rcZI_ endstream endobj 749 0 obj << /Length 154 /Filter /FlateDecode >> stream x313T0P0asSCCB.c�1s<=\ %E\N @BA,@Az H?*;�&p4Aka[~ `1.WO@.�^ endstream endobj 750 0 obj << /Length 253 /Filter /FlateDecode >> stream x}J@#E`}!k.p` A+ RK E#U(y[,gǰzqꜟJz`;볟 Z.(wk~x|ws%{/xv�4lnfxYDdItSn\#7@efd=`El6X�4jB*`f}E_h0bj1SL̀,x>v*!*:MƢ:?-y%ۧF@-7> endstream endobj 751 0 obj << /Length 161 /Filter /FlateDecode >> stream x313T0P0bcSCCB.�1s<L =\ %E\N @B4Pe,B @d ?  B~o�Ad $?Hz�I8'W �z endstream endobj 752 0 obj << /Length 132 /Filter /FlateDecode >> stream x313T0P0bcKS#CB.cC �I$r9yr+r{�E=}JJS. @-\.  @x@@?C1;}pA|.WO@.�O) endstream endobj 753 0 obj << /Length 169 /Filter /FlateDecode >> stream x͏= @_#d.͟ B Fp !VbnxK q\`eW񊉣~2c!G<h͞rCjaJj<)3#֤ ^id :�ꃭ4>Oj .mO1dXV|-�M -X endstream endobj 754 0 obj << /Length 198 /Filter /FlateDecode >> stream xڝ;@%$p.H)L0VjiVW(x[_~0E_cƃ=2b4gA ΄Sp)-8l<g]AaQ+?Pc4 oLu5ZԌ0v-L!skܶͅM2^deADW>sQy endstream endobj 755 0 obj << /Length 115 /Filter /FlateDecode >> stream x313T0P0b ebUel䃹 \.'O.pc.}(BIQi*Sm`Pz<7�,�{\W endstream endobj 756 0 obj << /Length 171 /Filter /FlateDecode >> stream xڽ= @[&G\@7!Q1#X^,7[n8ȃW3r9Al&]'-\,cx܎` s0 n ==Cbq1 SeKvI'mr/)T8R`5zf endstream endobj 757 0 obj << /Length 155 /Filter /FlateDecode >> stream x313T0P0bcc3CB.�1s<L =\ %E\N @QhX.O$$PD2`�$ȃ@H&?�:7 q.WO@.�ll endstream endobj 758 0 obj << /Length 183 /Filter /FlateDecode >> stream x}=@XLvNBLH0XF[٣Q8ab^2}KJ)*%Kw4 +@@)juE]VQzB[_�P :9o.A@9(dq%7@'a/=ߵG.^Tyh p A!\\[>P: endstream endobj 759 0 obj << /Length 200 /Filter /FlateDecode >> stream xڥ= @g fI"SZYZZ(ښͣ[.(wS|7q4HRYs_8 LWCNv?$#(%p:lHj&5pGٌs V,S*7;(&A]t, -GT@8=F> $_ȥF<5ޯ endstream endobj 760 0 obj << /Length 211 /Filter /FlateDecode >> stream xڭ= @ 4 وVVb&7J{ Lig Z 6_B޼q;QH1.#ܡ$ )ѯO-3 # ƒcM?n0O$!Wɾb|31P_6rilxz+=Տ>jO=]quBVŴ~[)D\|kse8'vG endstream endobj 761 0 obj << /Length 158 /Filter /FlateDecode >> stream xڭ1 @ПJuj!Fp A+ RKAEh9JAqc![̃I`4-ØԈmjw쎜{Vky\Y\/|9êe_Hx+5C8#$RC\B"�xo<Iw endstream endobj 762 0 obj << /Length 185 /Filter /FlateDecode >> stream xM1 @4!s7q5@T0XErr,,2ԎgDM&rv=pr^ًYMyaoY!RrGB7 }KD#"eZSW!("PB Ca}96A=<Uīwy^A endstream endobj 763 0 obj << /Length 155 /Filter /FlateDecode >> stream x313T0P0bc 3CB.cS �I$r9yr+r{�E=}JJS ]  b<] @AH2�`h AA~[@ Lx�:B endstream endobj 764 0 obj << /Length 148 /Filter /FlateDecode >> stream x313T0P0bcc3CB.�1s<L =\ %E\N @QhX.O`� $0()D? d=H2c�ģd> endstream endobj 765 0 obj << /Length 186 /Filter /FlateDecode >> stream x5= 0W:oN`B`A'qRGE7^̭ ء4ؔ? ,&Q@>0[}pb*Q)QzܟvI>>yG:J^]S |-,ZH�ZX:^<r[C准qzb&gaQ��$L endstream endobj 766 0 obj << /Length 174 /Filter /FlateDecode >> stream x313T0P0bcc3CB.�1s<L =\ %E\N @QhX.O `?�aC00~ @2?Dv`N2~+ߎ #ȏߏ``� ?G#g``?A6 H@RՓ+ �ɝm endstream endobj 767 0 obj << /Length 202 /Filter /FlateDecode >> stream xE; PEoH!LUBBBN!۲t @!L@,a̻{ې lfOÄܒZrɌOp>ܘW!kJ/LnRQ;H(+�p{h/ O�.ok> 44W&F&R$}xY& endstream endobj 768 0 obj << /Length 237 /Filter /FlateDecode >> stream xEαj@ dz)CB=ҩCɔdnvj:t&=$%p!:d-"zX!ZnhyxDQd}LKႲ)ֳ[{vȭ+OPy5 @U-G[;z[*�lB;v\ɼHer;SHR Z88 ~Ka{ endstream endobj 769 0 obj << /Length 203 /Filter /FlateDecode >> stream xڝ= @_L#8MLRL!he!Vjih'({!q-6߲`}t!'<8 91 ũ piNfqJf)c2ot=̜w{@�^m W÷x: dTLdO_'X`*w]!WҢqz9KU" }�}d endstream endobj 770 0 obj << /Length 141 /Filter /FlateDecode >> stream x313T0P�ac S#CB.# �I$r9yr+Yp{�E=}JJS ]  b<] X큸7001;j?0�FJ endstream endobj 771 0 obj << /Length 222 /Filter /FlateDecode >> stream xe1N1E*i| .-V Ab $(U�Aݣ(>B,?kWEwk.i;O%/$=iI^>$nF6x�0ڄʬ ͎X⌾T~fGvlgOȠ<|HTGǂ+ˇD5WTL3*=2,<8h endstream endobj 772 0 obj << /Length 226 /Filter /FlateDecode >> stream xEнN0 J^ @ZHHCL @>ZlDZTe}9W|Qps}ů}PYkP|N#5[ Sj~??ScNzDDFM&4=:4WL� hLVښQ5A1;,wKi sęǐ dw;-y"ͧ\ۼ>[z3Vc4 endstream endobj 773 0 obj << /Length 181 /Filter /FlateDecode >> stream xڕ=@!$p. b&ZY+h pJLh$%^5Y (xTHN)74 U[QcL uM��ĄB9ƛG3a(if M( /#`cV2OZ˿Z;5t endstream endobj 774 0 obj << /Length 207 /Filter /FlateDecode >> stream xڥ= @4{t&)!BBB,xxqFE惝}ov)ZRGk;Sʱڬ)Nюe6aܠOi(Zb>$\Cǹ.5Tº)7 P \)'ߘ'-,e$9ґ i `AY ֚ �G9-c endstream endobj 775 0 obj << /Length 241 /Filter /FlateDecode >> stream xm1N0E"4 @TE"Th+)S �͓=3uE5w|pWs/ 5gFGn{n5j+UknS=6�@! `dHp糢0g0p \ύF<'"DMbLz[Zj6]*7DE??(jALP5ˠGԡ(OY*G@BR栛 5pI endstream endobj 776 0 obj << /Length 213 /Filter /FlateDecode >> stream x}O @`qM>!zI 0XɧSW؈p w3s3Y:'sÄ1P{~s8Ӵ$4'tcot=w {* (D`D:y#jAԠBQS�Q]9h@9׆mƠ3/"-PIoәn ժ?|R3{6nR}Zn endstream endobj 783 0 obj << /Length1 1424 /Length2 5998 /Length3 0 /Length 6970 /Filter /FlateDecode >> stream xڍwT6ҋHD= MzU:J !@(IHB/;JM"4 RD#Eҋs=w3g<wv05$+Iuu5 �$" sqñ\04DHB `q:E"�Z��,.#A ɿH@  KA}^x�_�E7 � # 0BB0?B8a() KBx�^p=a˒z7؟҄ȹ�NpoA�8+ C`p.{`G:?� e 83 E 8�wtX�a b8' ~)� ԇ(,Fwxw̪{e Ő_Gàsi [r#.˰@Mpw NEo# I0orc|B�2`pEx�X,? `=Gǩae\poG?0�tkec=o))_F%%7OPD (,A;E?܅$2e;g?$3!C  1?QWwFj<wQ]$n 5]]=Xn8J E@pf:oH y@eMw`pm`p#K桊"/OXL�A!>$170_�H,9�D_6ZL�DẃR8ZB.KK?vzѸ~ �A?N!auaG5,^2DG‚E֤>q$ܜir`5k.=%~+ >jv SW&YoMQ=6KSb*Ee&w3C7}vVI/ vƫb{r{guK[<ɫzq`hpElgw, (Ik?K=h-8lYId{FW@Er4%bL{2/+?hEkLO-N״x#${^%#!4U~�'<fNr%amA4""*k$|Eϟvv*qOW"i|glqʾ^nKKV:nJv7i!�yO7bڢoU,FW'<; fxݏl!, ;=董|^6rxG/Q\[~"hPi~Я C $R8cnʊS CzЍGq튋{,_ I>'¼#{âӆisiI0Iӎ-L+M/!;jDް"m{V8r*Igr^kP v_Xv lٚUt/{^6Ԃϑ#9]QsnsM)k�tʆUtcwafSOKL5 5K>V0zyKu]RwVRp&i xlf :!2G4Y4Aܐ{ +cՃY1@SM@VĊln/?;Wl}ͦ i{'TŤO<oCNINbWMKQd0'q_kjSs޾;LthmK<͞u`oh  7w~oMw;G|ZP3M>d+<TxrqAN>nz WĒy${6uCݶk˵Hڴж[wvܱa'ݴkc)5F>7her0 ΩKm\W䶅/M **!VA\Q37?91ƐX{|W_%؄Y/*t5ʓEY낕Z`{W nUjC7l~i-cky5|S63dRT+f |_D1ePjTC cֽu  +ۊ!Klљ=}f^hhp/ڋYwPD7S,@XFM-qH{5ؽڡo65 HfF݁Ѡsor^I24z{v rfʶb`h\қBt Z9A,zP?{ȗm8iP^[GSYz8ƀ҄#LeZAGOfKgqq(c</kF{^U8 ͸>[2cab 0ZlwȂkt/"jg1qfSt i׭tx $ {zb:?_Ą+ E8F8�V+k,szUܩ)L B@I|1+o|S8K:L>� \;{/yԆhh�NfR]ޫAzmr]XgԑA`ȋ!ߖg~L1 /`qȨ M7g$K 2iu{yU>QqLy[Z=hF6ƌv:@Q1/^O0"^ ]ƁzUkF(R9ZCm\MXΝ j1 C#1-:6 Ҵ49z |`dp3t_;,Բ`L t&H{&^ p" @|)�<|()d߂+OȲΕ7& ߾u3=sSc8M0LQm/6wNzGUZc fEj[t8>lJ צ꜍i.n’9+oV~6 l_l<'b{YpBCMꚚg}']ب}#1/\H nt흳}n߆0fÛ{?swFzKYlZyI!6'F=ୣK1#Y^ [CRN~5aDAT |68 eO'By]Ug_v>BWQm.s+Sc>K(1s䍏=AV`TdZRJug4.[\NkW))~D7-�!mRł2;8{4l♄9zҷV2ǒ:Q [K%ͯyػ/ &&Nݭp89`k,wQŹI ߉8&Dջq(ʠ l8?l^UU>saR7~-9< K&1{&\ei|]IP!󸚥s͙K!thMaaO)e oY[X?o9GqPCJ8U˓4xnU` Wٮ .ogʙRAmF)|ZrX]ӇM^V8DƑPb)aDojƳo)8!ۡ̆35'¢nAP0ia HX*3s- BtLːWN aH[Ϥ6 7U9G>j5#:@EL? T,h`6:r~jܛ>{e־bqL!ЯaԣNh ExG-suUIuB*e؛HKdq! oW_|/M#UǘWÓύ>uT7wN{E]x 2{#{(PjBu[ж"X*MC>}wd~Ranf9?uG}1g=zdL;?=oY-+J?ItoNvW EY͜<;&"tY ˻D]xvŶ;g+M4 a:X5;]+xwnH g6D;3SX 2{.~/\4ѨW[ͺ?&ROg/9FA[,b7˓@1o5MܖN.-zFQĆ9$6V@?Ah 'E;[3_HQ+JrbkO?tBS %UH_ 7*<T?f,+W51WGZTRO>;]Z̙};Ptr o*BѝQޓIEN^ENQVIVhqRw�e7͐ӯsLU)# 37,j%A=|ZM ] p_$C,^wEߝ,0txأSɬaNƺL fnq6og2]=Z|@Q?*ʡg52qK(CCXm'rSCu`#%gKEF޹wd0I©bczk=h϶hZ;Z++,ŮΡlvs\+y2`,)z/(p kil]pj]ȫidgsF-98-P"x[<p%j÷-@*RT&H!Pǔ.v i8D^RϛjM׵7>h~&RcPR$TjoDj ~bk=@M&6&4TvMEi3#hArDvp;!C\ù̽?{w5/M]g%ۊv +\{,H s]e=Qm˦5y? ㇩6\n%)kQ^iX{ȫ m[e}K}=DxYƜ뚺K>xY @]6DDXJQ !vubԜ+QҲل3JP1B#8]W^+,6dBt^ݠ=T?سĞIq)1V J3٩λvZ-K_(]WG;MfO"?z\_r5B1`%Œ5M܋g&Du/<'tV^B</តJ.7Iv4/^ME8t in **p(t|e4$&NCaǘ))RwG4mk92c{bZCϸK7ǜi< w1CYu1`_">^7_h^A^87ө e3اWѣZ.nqՏv F\ܺ->R쎗[Jkv�X+s UW\Б2ĢGC6VQexV;/+ZJy"_CM`LH7p?E9dq:|څMR>`;$D&_rM})qI봹E U>Yl�t<Drmޮix1m«�>x.X3SL):X<޾ZAw}Ң:B9wFWBÌJe)P(l]x L6u7wg[ *%moO!|KB åwӵۻ~Nz}~q4t GOo$sK݋mL,;5EGkdS*f'%/GRyޕIC;id\sPƺ\8r@ o~^b]2x`L@yg-/XAN1 ޝ+<r|'de_Ţ׷5<^-< 4`i'ɡhcjui|XB52TLVnbO凛n|9^X?ʾ5vO;YRwg_LQC7ͶGNT7kn j?-F ޺va uʳbtYx3'Zh` M2Xp.^|zrw-y֗|'RSma;<_DQUw%X=0v2t "@|GM_S7+ϕQoY2_AgN;F,oC8~VCG| B?YsqGv_Mt:b{[ywxk5[d8/3D R*Q"0̐lu$z~~[\ӂqyBH֙2'ej+9nRUQk):1Fj #d]!E\9Jqdbk)EKERɒ3VN!r%3>zYȷ'Kx4RHNn[PaYrTYk ng3!Cż|a $[tE3lCzn.vޠۼ:;*B ?Q3gv´h<29JKKuk/p]?J,Ixvuϗ'f<>P7-9_ endstream endobj 785 0 obj << /Length1 1384 /Length2 6013 /Length3 0 /Length 6959 /Filter /FlateDecode >> stream xڍtTT64(ARrfnf`f|AEBPJFZIAR=5kusum.vCAeg# BbB"1Xqq±eCc(8aP,Sb~z($�b�XR,%+"BjPo3'h0 Kᇆa :`)_ဲ; w"=( 掿 �LPNp)xݰXYaa!;FvU�|X7aφ};wgB . \>P4  Gx!ah�9` xu;�fJ'g"8W0 E  BX_��E:t"0(|< G@*e#�oO{'4?[?eu*b@?SaN ]$G:lC iqCc0, !"""%#<~_FOAPp7 � `^4gp‘g0gp_Z=0 7[<QH߿W{[[w|�Aq@PTB�$%i ?eG?+C�?Kg- 7mD$DB #B ~y3'/�=^vV-,/e+_cc p_!-q*C0CW_6?<%`xJuD%$( ᗌ?I�`aH  !QX|o/pAA?7* a^_ q/6 K0/ 4>rSpJR߭A%'|F+eܛE+?n:λ4vV[y).ŨG}R=hcޚv2fASS@ĵﴹ=>9i}ݎY2Z.!?}7or+1s+Bzzۗrhos6$~PzX~9GŦ&&Nی,{=* Scl(O ^ZM/![˽{߂<;hS iteq4r0շ.* .w3O|z} QX4~!xBsKvEfWMu7ةItq^& U G'_版ܖJü)APIն۹!QmyyLnbQ9$Uqs%Bj~lc:9ŵ4ZFKcm94/1O5b_\] R lw^/*R2?.Q~T*"篷ơϚ0iqD/[olxW'PZ:^mzq#Rk"8n;*TPъFC^Wpe,O߰o6vvM庉sz? ,p Jl^�rӈI Owgoޏ=s1Q`.Oͮw\PqQLVo]+ɘ=Iɺ3t̖PscS1C'Yt˦ɊsVM1+Yg|5rEן2-˸FftE ʭR}_ciyi*`A~"!1z{l9Ym2m}XwkId9Fyk8W > >Lb8PF}+}gE I뿸oUVetmdG̖| %z*]AqW*uܾ'Ҿa[؏ri5Ah/OT .ŸWjbK*YG΂Xlf=Bm Ľ٭ꞿz]vBױwMdhGOHHqOw,V̳)ӭ⇙ttv5 0h ƨVjM^j54\*eɉ常F0aκqmwyIg[cvS*XX+9-;zH/([(e*<wcͶ3l bƒm IL|S8mTk& G>*[J{:*]Z ^ RTx]$*ĹqVngQ[u(?Ur@鵚 !a_!Ku&-<41@( "u&;>܅kʲ4 d2I^9m:q? X4<z; ]Wh[ަTm1U˜W>%2ckrRfS]Z3\9|&*8M jrA&B4C91ˋHI2i�1T2Us)6YN JܞfdsR#ߢdhQv]Fd�^$|c{F̏FڂhFikb:!!$dQGB)˜J sЊ9_)I8@V-cjzH|'10ShQ@}1T ߍ(L ó@g!n)5)^#;#F\$ŮiBz_=]f[쌧.Kt ѯˍ4 ^.52Ț 4HKFE>eskN2w94q$y/µ9sSI4{*n8u#UO0P$3i_'Hxq~Lz$w%OvY7˟6M6NOCJSK~Ɲ<z3!GM�1ڑ![Z33x;*%d9Jաh%xDR8ws00 >ɋ1Z*H_Y3!Oh:۷v~ V*e^P(d-k2& mî11TLs/Ky2Q[k%K{VS訙OզjT|˪|QM3 v\8Uf}D`Qt1Q[!7VgIU~{UT7idJJk/BIR-QaqJ7 G"m:󒐏ߍ}A(79arՓٛ /r-D1M/d4(T"Ϳ<wkn3J C8qbb 2212ф< % #Y]·lJ$.3X,#E} ˜C[4>ӑ2K/Ѽh ~oTNQuMܔ[>leeZNG*8md~eNa j(cw0fmx!4S{v{P'iR>OEm#>J9,WyjFuTۓl>dr/V<CЖ7x,!CiH{#bmzrRT%PJ*}�HtǙ` ݲ\[IhYam{I Ts'!4hwM#ږYi cQ鴎JI~#쪪lq NB!߬o.0 ="]1O9lҹu=]D\ N^=nK}WپBſ}C $D_wF[- LyhFWqK C%mgDi%Gȗ2LovX{g7 g1\ }C5#^8`jE!]b|d `5!8/mIBP *]r[&ތ}ЗH Vt^7E^&f)c+IsWbreߢ NXŎXx>{*SBBeمIڭK4K(9>4psMۂ9 8bdYI9rW@5,4nMi IWNj}9BJdQPX }+mrUp}G\mIXۛ)U;#kECdU]2alW']~G+opu^r}utFD ;5κ*%y9E誂S,�kAIm&M̹`VX7h/XvGoUun%aw} )BSXl _ 4V3dv`WYл$f�TG_ ؇H 1p:嫗լH2ޣe{=Ԅ|�rcm놳\l>J�zVr2m/0XE*I&O^f$)gWwiމ~~uC; ZjQ)+xqM;W;D>ECug-'%MT ɛ`HiL=frX.DϯaA ?m{{F,$6EFa*U fi~UuU[Uy(םNvͷ[qݽɭFW$kx\QuS H0a<eRJ c&Shqe mrSlʂRw'MPƤh?*ΤX țԡG }2WξTy7h~=s'[<vacnkw27</H{MqwRwy\<[%Om36_1(!|[jd5l-}a='W(ZkԐ?<+2] WنX+Ex?P}7bK-i"X JSa.O zv Q,#NR_Q}]MFêqXCgs=۠9%j A$.8W7NvB[-#1O:rE$y>kО[b.f^š-Ӌ;[럨W&O8^2'RTq|uP\^wG롗^&+2:LTm:PKE7Dq=;s.h7ܹ*Tę6Oc%ѧ*lJǼ *D8z'סѵ lt#S1O;&$o g pnP袈.닽mzVnϵPs;;_t+ȍ] j\޲xsR2敀+eۅqS)ԬHoypw qP�* ZRoN?wٜu3n}GHɆ3Y(fd _]{*!i4~5~ D]⊖-O{<kԅ*2m_>ONRXMD&f(Kq| P2Şw~?,qWF{Kna�4/,_^ԕ +2RՋ[w&)X?+j_/ZyW[OJ=A}k/U?gSһ䚩_7&Ku\QL'ȳ~zap6_k zV^'tNY|tt?BtY�F4٪ޘ>y 7EasjÁ,)^c:LV]O&?4 1ؠ?x/4 fP 15br4ƀM= M!s'<Fb]r7j8RmLr`. +18`Aτ0ھ%iPz\e<"@j*]C/)7j֤h*4bX?'db<-R._W6g1B(R QvK{mJggrq@5t*@s[F_{yEXX'Л1ٙg H}os|8YV`erUgtUI-r}nsD /dnjVpёnMw|ZdESOwbqWJsHv΍ڲ)K `R2HXC*a$Ш?hwF m4͗ u 7lQJ6!mŔ4bڹz,D;f5=k ce ;tY,]i@Sw[ !NeG3''FS3f͖ML*:s͕mOHD7&eqev]50hXhNJ2[qCR|G{?e!ҎV]j/̀~,쬥zA8&,$x ء9v7LGit"d0TF6uSXT3CբE`Į>ZAgνe:[ou$8_8&ypVS?F"ZN(F @ H`'u R8NUŭ+Z_|[$-I<oZ=5N L, wX#߭iH%}z?5}~x88mo*$uL*?"E䛬sZo-U/߳~Jy7-O!q�L`1n Kӧ'V4`T^,V[dEvCRf֌wU)$ۅ=.�YMЬJ37 BcNmlzЄ_Xl\rE"U7[ AADΘ7McVKo։.:^oWT%/Hc_*J&RR sШ\~h? endstream endobj 787 0 obj << /Length1 1385 /Length2 5981 /Length3 0 /Length 6931 /Filter /FlateDecode >> stream xڍxTTk6 ]H HKt00 )%]! J H   qk}ߚ羯&N(G �ez&V �HM/;)9 G!e c650 C!�8�$) b@_@,@ w�nP4)*dd~ݡp c\؊0`xȊ"(Og~!0P'ϑ`wDH.po {BX"/0x@B?�ODp`0r�#Hg�  4tE0!�FQx7�;bZ4�`CC<94mVG:ݡH gjpO(~ ANc8yy!wj0X6g( �wP_~__f A(� ;4bH`o(� o?W  �p$ٱf({p_ K?�;[,ÜPH_G,lb&g8UTP�a1$�$RR1_H ]>ղ?QXB|P^@g gH `w8\/ Vz(Z@KWrWƪAe0o;:1߬m77 5D?0( _> nاK_.(VC~MLB�b�t"3@T`C��0'σbP> #G~'Vl-P_(tap}y^#~pe;&j ZQ.Q]чSs,}< ]*9~ ewB1;OH=YlF`oÛj1wq_W|fe7zZf(=`+w>ZŌXݡJ26}�O8Scn5GE:}5Lt9GSsoqxT$NU+ғ8J#y v${59뫆^5٫%1'߻|jcE5%E! wHZqDA>;{ Jw9^$C|v2H6]!=!cfxq+@Mk5zCHxTvΑިG6$ˮmW꒘zר{ę`||ÎnM9k%IDsqBSצ[8$VCf(h>V=Y|H>U>]:xoiчDF_=Dňt ]yocn&.UC TӖ߻S�ySrC5"&g:xK.gxӷ|:hqF %Uǘ u;OZ={_šOlnnzm7VyWE @C;_F|F/G&�,<X4 9x)Ll)k&@(,2p=hnqpU? $LCw/Q=mZeQ k#RvJ]d8P@Rl^jM[J+=twnxӋ)E~~B:qzQ~V[ 7Lu wuq]@O5Kk&綀Ғ^>Vo,*\6! XXcl\i[A ^Si0<}5o[cf,z^fy)ݨ,j(7 pg {r^z/~5 Q4&EBfMc|y;j]9w{ކrio"˪pV}iNϾ6eOm>_kBD1d/?0KFCl)kV6d,dӖ:ikA}%~013nW},<q¦<{.A^Vxd*ͭeCބۏGg9]OWS=")^__25)SS$cL7H#~FQm@in$d_Sv&\ޜ( ZSIݝ lp!-U=[^z2D.ZdδyE'⦛UJsf7(6p_e PHųY pe|~{#5W O#[jiDzF '"hښ601jDžɆU.B /;Re,Iy"oR:qMVbD' Z[Q1ࠀa p+rxiql@%~E'nʝ|�NUbC=lۓmY!2#GL!"5ӅJ2Aw}$>$6Oɳr% =2nd~ MZ)~rjïLI9aз%>c%Ɔ\-m?^w%ߘ.q{"LB Ge�}7Z "] g' nulVɫv7' ^Xu\!{w @1'd=ɝ<S:)ǧ odl_cֶJPCƎ[Rъ>석<7W{DN8"=5CM&5~yi> K*.`OSo$z7Z攍a3B `ڸqSS2G|&Pgqi[u|m泇+0g7M�ʛzRƾOLou#bԮ The6z<UMbiUy#y]?uYhc+bo# H,v-F1k}¸lC=441[҃=% N?\LC݇62-{:”|iY{Ѫ{e(62q Qf:"$Bc炎d}95OFxg͆HIQIB9E\ThčNQŨ�[Jx$Q83ՠt|{ h)Db{tcqqNN�r},uHꨰbg fxv:>BDN Oc{ZdZSz)(rz6 Vmݘ=p mEm?`c167n K*\`i)ZL= e`){Ka3[V`lY ;O'Nqd �FO.*8Z.7/XTf['A~<0kڙFݗ;Bq{юҦ@}+MX/!ݲY_$#`Sfw C.ecJne6ާ :{( =tV<K)<+UȎF9 p((c+%saf0 yݘs8x; ըTW`Wy:Xl͈~GׁzQ;C<[E@v^A=YG癞y*Y9˫hV>8lyfQ,{TqGC+c9ɓNGe6o{;#l'LGKDHPa՗i-LtkeA곓k8].0U)B(Cc,Χ ۟ڥԧϣ0cKqisU<Wnf n{ӈvKʻDJ?bKbOZݔmS7mX@61f% % %^@p(/xZo?<fbޯP) iUxϏVN}7nQ RO c\mi C_rDܽhŧ -{x̭O{rKvn[BŒD(@=~Oj 3&ߍ͍^-=ZC"ChxCGFY1W֘Ʒ>L҃ܣ5zE]'!_lO>aѺ \C^C^˻!WG[,qnGĊbLյs|܋,TeF칢@o lKJz'O6Egx\_1 {$᧲dΠ؝e bc)ɗSuzI0Ts,РfꉆGa5yTd{~ϵM]_?5骞^;iSCAoڑ3Օ8ͺSCdtgDݹaAἚB5>rvGF VuN[uChU|p'lF9g7"4|VIq'?9om*Ok6>yjJmZ h 2f"}ĥQ*CKmȜYoa2|GXРJiμK=FV|USiɭ+7꠹ۼoI)ÈP鋹(RyTGޫ=':Kz3⊯+lZ0Q{_OOI`&Gr=$̒6QpU[Nô8 rvIxe)bC<C0 ~롎xȻ0,ʞ+wN YuCq Sy0JS/M9盋Sr-^; r_ߘgzw\|Vנs;C4ESLE{"Fh&92S5%zYEݶ]}]BHЃhAhE`5uIKuͳ 63tXA#DqkfT/%6KY1/pP 5LY pyc;n;`҂|2s;Hㄚck([76mwjh)]<G/82';MW<Nku]'9 b`bV).״: 0 > t0 zWbK-275"'_ZFrcˑ["#H6,Q̓9l3TD:hkl*bM !b6% B,UtZ?VʐKI{ˬk%i]58UY Ì) eT!qStQ{[hC %NLp# 2N_AyОdqdIi('] )e֎j8s;ō,~L8S3J4H#rU! فղ=HހLg+aA2F%!χw뚮S}p-u<!ح5u>1(O[Yg3[t{R1^v9iޛ0<rsTߑPǸ{1 XFPE jD\е2/qciа nKn }<JBʍ~{ `";8Bվ'Z~V- y}m֒q܅\L-i)o3ԝȗo�FTpHnDOƨc9tc&G9O}q]XS>qDϪǒ|9s!.H h])זs'SNGTfoS'Eɭ >$Kk.POU ls }~}f2Gh) ˩Ќ5~0/�;+degOԉ3sHyD;^IuI˧T=j:DLϣ`9|J>R^{{q /;v$Ck9ӵbWH7m]: \xKx4MD,>T6+X}$y? ɵ[~J?VzЧ%7 8(UMl? Pz)XةkcN&gfǑ@z%ok}f1f $}2.m}G|=hGy2y#?u%"_>Sok磻1nzd-JJPg3}#1~n}mQgbM^s:t/31]}[w[FOOL4$&f"o&吵{":w c#.w֡bzPt¡!CeĦZAѯ_rRY? 7<|S[Vesf~~6îMcV]!e FlhجUr[0ZQ_`i{`J&X)4;m�{GGNo}1|.Bjy9tޤc~; (|''<8/ܨO~>9L:%zKg_M!hg~%;7!`8@fnΈWwLXuS2H \\_1V) c #A4$ƦD!͘XѦB:ǁeYWӄ V  <w .z|gͧ9;oʼ<8s|FM#kV 7R2㼙tL4>>LČ{mCĚϞ/zؑ>[Mۊ[9~CgeH{k@eTDIBmY/AY?om endstream endobj 789 0 obj << /Length1 1306 /Length2 1243 /Length3 0 /Length 2081 /Filter /FlateDecode >> stream xڍS TSga,LuZŐ KDv�"*S y$y/KB rTePEA, "*(XAD ([E¼\p朙s^]kMh#G\  �Ƥh M8KvXD0p z �ЙF_F)܀7F 0Vl0Vĉp7꺌lV |.ċ|H0>)!"QILaOjX�%H OF!ـppaB\)`@$FE ` ^aA` F'A�2lSM@|L*P-!"*nO�Bz $QbRC%�!Qd}JJkmA^T Q|Zp(AuoBeT2jU$0>`hL r�'ETZlpfD !Qa⏤SBj 1FӁ� CPN܉+Fȏh߇S40JS9^ȥ%pzzb @bG'SĩqB!d2O&%>e&LʅGoh|Cn7OW%vCRD@$s@$<�QI?4N}$P&dbÄr}P>&Я ҒhttbpAJA1� OBLAҏĕ&Ҕ|BAlarěUOj㻧ƗV ı8>g84~:ŋny<s+oszeh=ٔ6\talySÜ# +ʕu1LT7u9V3+n_wEoψ^^xI13H7tqaVrr+<9MUK+_eZse߸`=yx< i϶1xzQ 04tVXKHMUօ-ʋ4&;b[,SN E Y|S(uj6i]9>{sop2;7&K`f /,"~E/>\xX;EyRlJ:4e-`lo5,>GJᓱƴ׬Ib-;*O_rVb[nݝT]>=2_ސ)Hv<\򘼖ty<k*hw]]p$Bk<%iݢgC~ -BVGѸQF׺Eϸ6.zvrVL쬒a]# /fE V(k,{˙#Cg/?yz|Lλm1<9gͨi]sw͢zmm:~Zc(Ø2c3\@Ӯ/U�cIxힹ)Ʃ'_JiFu E3~oZ=oy3tS_B3.;ZLs*>1WZ6qfgz# N8ݕdivyD38Cpᆨ +/;KW[XPF-ι^'&i2`_>aDeP870|~CEKq/"+c[eȓuR A4͹֝[ h[O<8=ܖ%:[y3.imZF5ٕvK6h}=苏Ƹx~6iwI(VY(Kf' Pi .MYw۵#:v!/&B\yfne{ƔݕGVX'+.mx̫ VT^\]z}uMe!9W%֏}aWdY{]^:vXl,]j^oelu]!IloI=Oo昭_oi9eXW$aG=d_*U8~|;}BTAQl% endstream endobj 791 0 obj << /Length1 1608 /Length2 4269 /Length3 0 /Length 5073 /Filter /FlateDecode >> stream xڭTeXA@šP ifbfP܀ -R(J "]R s>u^׻׽ֽ]PP"XAQ!Y@f1#P�$伇p$B0( �bb 'pF�)/?_I p~<aH A a0�0c 04wC�m8x$p� H~F�q`^<$�`h78 F`q3"8='; /H\.Cbzʪ:1p\@:2HyK1 .� žײP8 Ɓ 8/�FC]a }>{0 }qy/p, D&* j;d狢p@"<a /DzP+ w* }" --oѿ]>v- {a06p\?dh qcPD8 Ǩ½`P=88]q3#0+iy1F@PTR򷘑8E'oaC M]% _Ӌ,=X#o?8PRBz†422~_}0 ,qM^/7 =C,ŭֿaSZ}0 B65ȅ8fa鳻)[^zzQeXl H );){,T= {=ɷzݕ%m˽4R 5H߭1Y )w6'D,$[ @Z?$2M5o]-;mLY1r`zUD{R̄!=DBeKL ,N֩wg!coh TX{] y+P |}`X<'^)H=0QIHvԡSeLJQh άD4qзrfORGcR5rƓF_#YےHk!yrA*L0AϾ U7ҘA0$`Xޗk*dR3S&K�^v+T|&U{1<2lTA'rCh- <6Zze 2{Oz[=,pdKڢhHLWDaeW9&{g1<|Y'[O O }mO?_>u˦2Nۧlv5eOK,߸ j+NWګY%$$Y} yî3gnkRm=W5Uo(e (Ћ9NeH=.~K2o>ڥ4 #z}恂)v璮Z\ }0!Q'Q#,RKL)ldc^;|BF]@ ˢa7Z'EO GJ)X?WDG5OKR աH?дvx "'qSNL ;~,z3}NHnf=uǸ( H{Ǐ8N?7$_jyYϰne�e/_-hxZʨaDžUNQeE&ɪ]) [ MRƻas>ks6,m}j7F /< Ovd$?VSEZT[`}fGSDCmOƷђn80w;گT ;#qC^knJuj8{Gܖ?*YMm|pJzޘnhEu难m8v+lf+fM(:J34\ښ/8SeJm43Kg1QL{“YF"4qq0V aܼgX С#$էmdR wƤnY|[ulP[$2q'ϩhIH5ܽ2U&lpMҌ콟Gn ZVݔxdxA3"-oaEC6)(d=vr1 e&Ocפ1"f֕v MWe(Gwן9;:Ɔ{os(euٌCNF^i0Ul5? q.>!7cMې<Q32 =OiC&P[¾˲"+eh׃:=Jp/f!dJ3=}zna E5~ 7<6ƾ?KXm$$)cUt#XnE=k"k! `HoW5yl[n\ҩ۳�Aإq b5 bfdGQ_^eV*{bɪF2 Y$7r~}[hPjEq=v|[h*ي5`Š]y2'6$gk^5[xL7&Sop5`;a蕒`Y|Ȧ9 08n}ts &WBh* 3fYj?o^Q<[[0:zP~0)ȕ`}BGS4HeONǮI6<ԅ?9d|G=#bS?%'X-(zs]xM4~y38E !y矫+W GRKg+W: 8"1;2B7BjuR{j r9xse-*Pj^;THn p^o)µIB~~cbl.y} +g4xhC93#jшtMKye[AY-:čSVd7"JY_hEc*Y]LD)9y8SY$ ,yj9Eαłj\n.ͬx~[04 HϽ0I' Mgf:A'1?d1͈3gmEo'7&7$a{+oA#r KZ~;J)4<"f;e A8|8*Ƙ@M^1聥}s; 'q�{f+% ǎ9V'$a{SG,SsnuWUHʼn8>Qfi~>Ka^ +u;[tc eLW*w5?m$83-g .S6=dΌsOs -=?iO '"qRsW_K>x>30vX#qgLi1ԝrVݐƼ?Hp3vgӱ#YX:Ud=Ӻm}5E&AL:<Mfkw8}mx*\mnQą}jl|&NČF esU{Ͻ8T%/8NnGwfߢ,r6Snw<~~cX"s3+6mXj޼e-xkAB$XY˼VbeWڢ�K*!wk9 ,¥:1K 5I$lzB;ў-jms.&pRRDϥ`~R32^= ]"hKN0^} ^8fis{Y[psT(ZpZp}㼩TG34&e|iw?-JěW).Z]7c\:{Tq[aWYpN ϛ938l UO[ ltOm< !L%醑lÇz7;~ޡdl1Z*ӂMmnnþg:T%L-?>ÓX!t.:}nQ*kѸ.ypadϕϛ[\4i/kt-u?7&%ZP# H(l/ɪz1FHF`;x:$5s]PZ᾽ox/V&I:w[Hu+i=_9V}|k<6rzNG5G+2rkY qˎ(B|i 'mֵx~4Żح(֙%w RwW&lTD#$G MwI1spݯUҏ5R\]<Yִ?$x4ǃۧFGV4W2L9(7'ˇ93լ^%WhUZGܮ@h  F\_$yb՜]tipu0"`lVyE7wlYj.&[SW?FV3\%I`YOM>x\w QH1;Ѣf6_OZ|*QwЧ1<oF oNɍ[0>Q᧿}<RXo1УRk(♎& ˂{ۻ,=—:b@Tlub>dx/kFlK}݇%> sT>^a1cUmKҖQZ:5~0mgl:W<Хxn-bk1Z{+RVKvwo唉s-IDC 0f:7 |FΓʋӲUsGėه,Nʮ~f "[{1Ӕ $mjRR$k}Q' VxfGL8Qn+{1ԩw5! %_$ ّXǭ3?+oZc#0#ju6 endstream endobj 793 0 obj << /Length1 1144 /Length2 4578 /Length3 0 /Length 5332 /Filter /FlateDecode >> stream xuUgXSYi"̀7齈HO!$ �ұФH HSDzWI}(MQܙwֻ[:VFb1x,Xh$l=0f26p$H""v(</L=(,FO @s�U,g 6@hÆ�xx�!SX/%Qp %xq@ga(7(no(!%%7QQQzdp p4G&8@.# a�C UA 8$A.�1>*�En|1 L` ǠnLƐp< @x7GJ;?' {``X p1KP^x'I0 :e`kBP&n:]gEbɒ2%2 TVac  Tp,>#(ӰTQ^p& <W 3!ٿɝf=Bˁ:c@t0H_cB Qp 11_ Cf2(7I14xaa( h'#�"g#P`, 4V?Hf|w%;hs(g[ zkV;SSQƥQ Um8gȷ%LBy^|#/6oփM=+_*D49lknX VT1X#I|ciZv]s3>ɤaXS!gUW1wtϓ鱒jpW6SvNIb!%'iyS̬#QP3?Y/z޶1~fϚ B <8$786E#]nq68., u. Q]֤ 63u*x%YGET}ޝ^F}`cv(UAo4ʷ*EYioEߍL[`HOPs2o ОCȆnXӃnF́eBO ucQ԰o[6l9hA1GXRB+S˷NmKxaW6FNb.(IU8PDW:INeؖLէUm%VsHgŐX]v³C?xE^(v$iB%zk6V6N8{+{$R5ikP5+]:5(x>ӰZfG:ˉ7uNH tЇOH\鮥6Ϛ~"X^hlܒ-bJ1 PeYm{˶r$# ኶z�_sylUɡdFݱNGDm)֡Qv:&!.as#WB>TZj e|~}{r&qׅV^g_Ţ܆U(߾/O1J5ϊY/r񈑷Dq؟Լ9gI7/"tL4%^'z$rH:SHy.VxO1÷a짶l3ܜW^P=ly3m2'MBUea{ "I*i[ ۏ.7T�ᢜa ׻LilK3zdIzL5ժX$22-tp4:a ;tnmpDyDܿL5}eБya: e =)OuvDP}bKzI{[Ot6E2Req)]w7HS ԋWm t܌0KI)7;P}ydt5"&aIy懻[7/1|mk6kDg4+rZ$s,`l7#xt>BpLEx 0SrYV((suwN) Ջ:%jA͚MW;^I’[,/4=ztGI~ ϿλMx)*Bэ=@evp74ˆդg.C3K7]]WN=Tk,YFz!7ΙYџ.YzlgWf\B]xFc8\6EIg`0r~waŔ9<u-<8qF/'1N\蓏FTjYBW=F5TakUCtٛ4qid)"é# J4C E}5MaKjPIIzc2GK+,ǭ5D>ͥ?=sACCd^ǁʪ ûBR+1g{mܝEd6UTeVZp<(.(/GZh M=K,i|zen_K,jgJi>F"rW _07ߞHQvCh(^{?kIovo�GڤǦH?}=l4#y~/2z׆ /kfL v+jcu(0Pt*#I '{s2SU65ZJo&`B 瓽;8pڧ^:kWܭq}U=u.ų:T CjG) ۹s"ϵ(o�)q[!9:bSe3+G 3Լ/ɵbB`{i\D P#çK__ {&`}L9=[@BWbP �C7&֞eo@*}_DZ#hi *D ޼ ڂ5CH&Wtт[kB KG|K-bk~=F'Or_a- PJz\U(,hkY`MsdZ4h/\2y`ja0]qE|p}F*d(c@SBɌKE8B;9,,8bb;꛾Vs><_s|u~i_쫕ash *9P]<$\rw?uf1SAtS.zEB. v rHM/9^{(lhX(7c#k`}W@N]cC6W9:Q#r.,S7*s&4I;18BD_w fFsR0i6zQ//ěД;PܫL>Μ]\ c73~}d4Qob9uԲj\crG_BuI'Ѯ%YYaRcPu[ΊIc MtNߔZ?ʥzhZagXVN 8د?,<1\\ 8A60`}MMIypEyZaT?Kŗ\:{ /|EY cBm9:furp|M{PIW0RHoۇ8ߝ&r$P67p[iKNx&{x_GŨb2dV @p'P'ʙF׿Gejԇ$/3f?,{_J;J/1zn:ox&qr:)^##J3+6R-8N I}knR'D�sb5ŤtQ (ItQ^XYY;1Dd1;T߂X69~ELBHdy:eBv%dE2zu )(P'6lYi%o^÷Uk\(Mk+[K_J~Cn:T{^[[+=r>lJn|/_,XS.ROh][3E8pS(/ ok K<ԡ^ݾpl�CgG^~짭( t}rdcĥ-)n~ŭJ )x]N'4"B>JȚ*? O1 9TIZt-7vbj,(R&)͟qWŁ5JojYW Q]w'g\XVRe[B{ež\j2|:-繌5ؕ5_ HQ%5za.(1D[hg`3rw˽tds/^ mt;ۤ-Aj&YɍWf;U:ZUwBc! ;; ixEaΊemNkc�%jDc9iu4;yZbjb:(tE7TRl>wR|u=5SU*}cUp){ZC>1m86Q6}[WK5\> l=-"^sm$wNo_w Uꑓ>Qfd&Bi5FKl,HZ[vbV6Sy#=M0:Kv;x>ʘԉ͚5*vJQHJ2IVYgZz5H$^O|&cjjO+LPmEМêv>p{uΗbَ򏠲=KL(ynm;᯺BD�+ Og6E%+݋AFVQqp( o>2b6R J<4gQx!ĜJ'9$4.cnMϼ!օg|:ʟwIS6᪢3RLQAYpBo*a`#\lǻ͕7|dR *zYv3aYE|WNOq-"g1 7ak ݑ)0J{ߊ>mi'@47 Zw2ֹN�:a13.6u0_ DAwILӥuc{lJXvК-4b5pD|}4{G3!.'K#oLz#I8Fw\j<GuS'R)fi 4vSfM(e4\ lLM2S�D-%dp<BDŽ#YzF%nqj$KmCQ fR >}2!?aQC2 endstream endobj 795 0 obj << /Length1 1177 /Length2 2165 /Length3 0 /Length 2898 /Filter /FlateDecode >> stream xmT{<YGrȐ'&fD!j<Ó1`HJ.QBD$r_BK"XoZ%KHwdy8|GsoCe{ >�\ ?.Hf8뻃}2(ġI;H@Lxp<"�$0#{7C& XP3 E| ˤp@ C d3, �4~g<t<Ah g�ZMHgfㇰ _8uՖ@#gm@' 42 4ȁ1v̠�la!H7ƃ7@3.EԯQpOt $c @! h�0J�|5/J"Wa2 hd:h `C@ₑK$DT@|·AO氠0a@ ·T&nB8H":?L~X}ohf >(U!;cИ�zxԾ5|U:_E ; Q@@` PV r]!_WN?˥ӿ@gy=pV y :o פw6 :# @ C XSɠ~} ɆV3( K+2?$1(L*,?*MX9})3 a Eb bs2~רsnf,D|i xf|KXBWe.44m` *'+'䐠<iP#5%?hUN=֎qGIҮG5戫l{Rq7Ot[?:ЏaD:񙒎M5$k&K=~f+TNH7M1=M N֍v_KwK.?5$%LjR sE a@SlX߆q_yzo7sw*qE>p۰i06s&/ԡ/lCդ:Gj&.U?hQQ$dKaѻVRa{7&K{*KnMvPX)}nxhn;*!GmS sr|"L¼Q(<xdZ]' T9UgYDjvh|eV*mKtq $]IdX1F;T;9b[nX\IWaI\-8BҷCq,0&w.yyB=7I4d?EE˄mIw?W}ntYlk/YM#t(zb3_8,Ws1VG/ qQJ -۷rG )Ч&vq~ԒZ|E([E$ª*1.:?:LT鼢`/$NvE5{;V)OM$c$hu<C8g \u]2m\@RRq0k[u*>:㓽 {/[Ӳ=;Α<[]2"5֎l|H)])1)M`՜ˡɨ~s|+v!qb}�уƛA!'⳥ מEݿS'VQvxWU%,]vije&趴,ֳ(A@K f!0–*vXV߸@ BajV$wiSVe'ږ3!/6YĕXk>8Srt YL8PNҶ:JǏ|OH)5ptܵru]*>d4+V;LԷr&t[M]t6)/Se60fmOnפ`K+ OLz}PyqƤ_cРݱ?9yGTo~BO-_T|RVEu'9ӤβЈ}iFQXaC|`+LRYԬcT1QZ@ m}\JwJĠQX~Tc6LiiH_QoML Ibܱ} ^Y;GYŐ,ų-?+J%=z7htafkw4Hk7WE}̉mv\[qG3׭{GNt*6~>vNX=D $vU0mp%uExNlFKߣ[M}--+S>/S 2_I)Bh'd{PO}pARٽ[K_Cɟ3y'2-Y2Fj͸M�ی2~m:wU͛\dKn+ YޣT\ /_y|Spf"M T?)'\֑90oö#&*VWLD?Ehuy +TWwE_@KEEbȘ)j"Jխ Qu{xbbzaMsXT5vʅ1S-{rp~ r[j%CjY-3dG kG6;+/|⭋Ć'9,ᨺ 됬BJw6aw/ܠ)}eRұ`fne+ߺX8<}2BcF wu*Fd]_V)$A}dmhcy>RbfW6CQe[|BCvV5;H-o*S㔨u}죌U壥ҝT{vT3EBi&*K/jS3 endstream endobj 797 0 obj << /Length1 1606 /Length2 975 /Length3 0 /Length 1772 /Filter /FlateDecode >> stream xڭTkXWA6K.ZD@  D6v9!DҪmieYiնh/BkW *jx*H"k+= ZZv#仜{=R &2 Kd@-`4qڤO2ɦ|}gpHRu X B f0#3t7w>P3Za)QbH7(A z3!9%qF!"qDa�2 34AI ,It qCAy<0Z@8e _@XAzC`*x#Y~yE1F<QJ yL6c9At� $y ltcY88~@ <<D" IW 2@.Yl z!`hIUϡʼn$}!9?1 20zi3(*#i �= Ń$ez\a0np8APtL"w|,ipb?& G4D:fATgI:B&w4qϊБB: &zlհ(dSeb2Z' }䲜Ŕ$gcG,;2f&3jO a&) [5ft!ǾS"% zyD .E@{f;B#E nO˄=>k<i4VԤn-ϯbyIj-t&w=qRz/ϼC/]XؾR½s~avWsR[O͙hۓac-u9>K4}{:yrs:9q{c7o6*w%mvpX̦ܠ,xHW5"q~KW/7Pn!ND;Gw.тH"rܻ&9kG#^brOVh(2CYFRٞ`/<ݮ!yn\ ǖK [Ǻ O[ּ*[`G,BwIWuLp=ɬ\sGoX6V.s~m.mb[ZX,W{=V4ůQߜ]\k_-_N~d҂YT~{yBg:QWyymSw];Q~dSnOAvvklĽ|~ˏDx-#S)nv&Wrhg/z/,&;"`j VoX>tN=8<xxlŞމܿ'ṃO"K.)mjM%Q_e]b9^E d᪝9䉕9`b>WWJ0IAg>uIBvˊ]>ʳ[ 8|pZF8fݥ4=<̣. .ֻZeGKN m_ʦ] yZIm郵|/mpc͗m܉[,gwU:E-u{h*ݷDGKE _Z1U< j1+:U+\_^mi"w3-^cE-,Xm]0"vnIA |c endstream endobj 799 0 obj << /Length1 1626 /Length2 15679 /Length3 0 /Length 16524 /Filter /FlateDecode >> stream xڭct_%;9mb6Ol*N*mTlTl۶~0\k!'VT6u06wwgf`[:+;;p˙ZĚ\Ō\x�f�13�  �ttP)kPxf:[Y(~:�]B_'\,�Vf�QE-)y �@jlke21w6;8l}�8؛ZӚ3_,aghfb7 �4srv rX8ٻ"traL [UQL<],\l p0i`OKu1wyS `j 5[/_4\-/_}@[e;+qrq65gcf[om +{8vEo+?|nfN?;C'QoI� }"7H"oWKz+3�Y?'/FkI_Ymr03Ur1׿jfNVfuHLLŧjiebc�vٛWyFU--)q@ſK "`8x�9�l_BLbϳ@oL_`ۛ86*.F7q:9_oqΛy,:Xfb 0KT SlsWׄ24N|z.?i{0m).}I{Q6(9iK4e 9vƕߡ&Y`HH~&)APk N(~?=R쾁ǣ͎%5K:%Nt4to0|uWDM̫6h3i4vjԃDŔ\kg$!@҉ _z\ G9k!Y+k[~Z<'(`gaO* 3c0N?4= 㾀JZF6Z-,烹!ؾ=A#˽Eu9l'<J7>zD3jۘk葤}3zxkju=`3Yޢ~k)ahFSYԬ%;?ApbKQj3tNJOJjEJ <C/D=˛"jRњjg+F'B ^f Af CP}ce+Zg LwO |͙BBVq_3zqsb RjIPk \.qYΧ}+o[ z1M>q5[cb'74ÌQKzܧ6 76*UC(o}XmFqԆ x4NOdB-"*'.QnOGmP -Pz__{}[w|z)L_).ғ%e=]'+uM5 Qr<i1z-Z @ H,}|r 1앀/lgg}%w?2ӶZQvB+ULǰ1]~O46L= %\~F9MG_7׸(ETlL0]DltgV 5u:րade^)f^ AIC%ԕ�dYB9z$Bx_l7w;5rQgYq$|+ѡӠs\ݳfE$\lBJ 9g§ANl5gLgMC4z]k64!i)gNF)IFرPl I `G 'jΑ7f(V H[d,"Cbn/ǑdG;~RI,{P&U1$i#>unj,<b�W(Fꕡ`Bp?Xs1#V Ĩ9Y5sŖG˛Mo dl2?m#iTJm'1ݪZ{m: 7VQL V>? ˜$.$%Ș! acDozָ;;)W\giHg'\?Y7!_Dbt̀DIe/xs1;vsQuޮ4 <>KѹPLKN`)1T71/>f$CcFH9`-<&5=*_;gFמn]cb$+SeUqՎoĩ9+؝D('.*K"V.jH7|/gvln1!D@/io'ꣽαp6G֩fk|M/c"| 0 {.>6-�ݽ~<Dڍ7ĒwYe%g7%ݡb=XcLO&zH%y1hk'ԷWw�1=ۋY*3ǎ!_LSGObe ͶYon>>T*v8QRuxjxӪCwb)ܻMED"/b (䈃d3N0 &F|;_WkiZZzw;p׾~!ßR2eđ0e i/KeRf4CŖ1U!HOXuOqVfLk7B45T(y˺;ZGy]nڟ֯LT횡)!^z)1L;b59捂=\ sLGc+ua|z> 0q쮖N!U唕ٝqHoU^aehxVfFԢxYFXWC|K'KLٲ4u!K%MF]6 /:fh6ʨ% | 'cu HavtFkρ s#,g7ʱ2=PG5{ː`Z hP:Aş-oOxyk6w̚6)jʞp~NX_11`dp҉u#6 =BӕP[fJuj)_+l $3e̷Տ~ \~nYpܮ?H3G*+{/OxNL D̙2=ՄI[4Z3Eb;jR邭s,=rs5B=]@`N}W;1J2$B @&lp;, y§pwFU\q5lII~<Q&]"0NU.#dw6sPA'].Ӛ ғm ؁+T²4VysefvpLDm$-(H`$+Lr*4[gk< _MMŷegu`Zb;kC:.+ q+ݦFep.\B 30 5HҩكoQ7@c3jDfp5Q-"Q<Zq)_NxĈJYAuzI` x#:}p'2O^ Ժ2,4 Qs®WQH.Q'HRc\}-Q(}>AV&;G0O Lע>`?`ŷLb�5 P Zi;u1;R7Y+OHYF]ulH;kZdѫfs)ttPxIC DUۣt!jgӻNaٙW ӿf(UL�M -S}+# &T-QX7NyHTfBgQAe Oϑ ˱\t%J3KH=1]FN8eGw\hn씞6OLWV5UTIrMΧ@QlS3V2% ǁ4R ʖ=-6_f$JC׮U89E:j f b-t748w[JCx=*V2 [:<w%z:Xf s*G0.hejh3ʷD瓒䓕rz,!bėNO;Gbp-Aĭ %"(Z<7Ծ"`P׽#OQ])ygꬣ:(2^PS>xH3)^*kS9De X7;LCx}qKw +Jgi՝@ gi2,N]MgxlʈX‚$Cqnē{kkAIDGj(@'$Sڪ ')Z-wӕD?~MO_$ P}pn(YH 6;8GY,ü&@eiQseP,"̵t:F+%#[raǿ薽`NVʌP33<,:`g̘^GzD^n,F؝p̂61G~ͨG΍mTt5LSA;U9[U٠2,AMv{+'RZMG>6L w2g;l͈�놶鏬ܢXoXdq5یԫAJ,4,:Wu_(lcS d [#H޻n_,'4r9pxXzT4SP8-"I4RmM5Z[$Cd B-eUG4HhtŗZh |KHw\Gq`:0H!$<i;.~bu,:U@ qRa|JLs՞-0b6ܺF\etHK=2^tJLyf< {}#܈z 1_'(H:7&>80(q2X9!좋!4r6'Ѫ@g͇f&w0ZGDYX<N-4!"\hhBHƓyXR'Sv,}PAqD8'nl5B7DO  g37iaȪ<r�8m02=j^\-V'PJʚ"bt?"+=+E 9W)dJw= @3 M]=)h�G16VF,.0- hXF,\ x8 `KGҮֳGge6/N%hwd7` z[Kx$+(2n)� i[sy[ wg4*^`tQ"ݶ NIw6ZiLtͷ'j*-'+ gڷ-.o,'Ŏ5Ȓ[?m\<<2[,EF^߫l}m~GV24 N6b_xȶ@l&g"Ikγ);O98+gX6^wTvy{Uh"y>ǭ$ſ o#R=O�:NKK\{ss+DA-6C+46|Cش̝!hc5;fUt xw`3y9Vj7jdz:8.!rIg!}X ?@hc6Dhaƙr\#4FPTƤk1EJ˺0F}oPKUU) >ezY nX v6=1p˄9h:FC>Dҋ($ Ij U&(,VAQ:āiE n:ȶ^urFF7;̠;M2F# [ џ_nF `c-V,O!ZR}Z,a^z~70[D󥦱ꉒ}1*hkM05GvXp/Gd[=cR.1tlQ D[P /ff6z _W,V2ωS^Bua)Hqdזˮ M`!Yqb>�iӝo`InwېQ],֌'I"_uEƉEXNTJ XG\Pmc6ݸ4I,e Q/%7FM~R%o YDj8Y,Y7s>K[g/qp+-'6!9WD GS_ >][|[{/]Y"SyQ;E"-:޵? xP+|_s.Uyҵg~02tjҦJJ3 ;dA-w�!^ 1%(An/X`SF%ߌ^AʀRRy fqj? Z$2;tTa eᑧE[.6as$p ƜOد01ay,ӯ25Q0Lt #vBn,wIXc?x˛{[)1V=}BJfD}l_B[H&%f$`L67ȄF:!#oJj}5֠4ChwENF 9Wƍ?iEn]wNX~O3a1+Άy{̣JuXcy}jy(0K vCMk }׾\:}\!d\1^i ~Qj c 7yWl<UV1z]{fK>u IHwy݉ï<F] >=eh8yGIZsǔZ'rD;49>R0;iNGE#zZ1ͅWЃ@(.aROl#vBHb1/oqPBi"{yGʹ["|61!i6AR;, '1PSH~a3#HGC1ĻBo zϻ'kڭF)J e*f/1e:,Ŕw 7&ZK4|JM Aۣ ++XR1fMs"v\uH?$ݧ P4u6^+C x)tf3cfOY'oZs};(r"1E9lY6ԡNr?lXTMVw%Ʌ3v ]߇vsE7JѶbJ2D$<IȦ:/ L顴9b2=%Ge_n**]3T6x7Iy-֬8ss"|aHYf`|rxz٫z[|]5NlmB!WYE9uO\6*ǭ,6n<>4<[;z6W"]K18rAwIkf:9PNÄN`_8&=7Goxp7 �ysOߓ3?c;Vu>c.]M 4}:ݼb &gȜ"4SOtB瓈Qr6˒sP>?}k͹z˙( Br_c:<y*N뙮G}qInjUS-t'c]7<)zՐUg))wT/Xs>pZX~<Vf㎋S@SÔ G9TrqarL\4`)7Nv3 R/iS8ǭjlE~Cѹ}<I\#u `0<B8A5V?FZ\|I2ޔ/i MRm%$"5#CB3 ϛL|U&z ]t~CJ$ktDTfQ*ϛܼlV)l86]8 p~WufӅ- )0;lxĕq4Zǧ:Dݤ8Lwy [Ny|xfO%+bxˤtQeqx6A QnJ@_-�QK2E;l]}~}WFDs܈qå>k ȫ- g4`G^;IXh_J8wm h5:@MrhkFu0 %e=b ˩k%p!WfN9i(Ù[N q^1ւ#G#{<t^BLrc@Hx4Flj3<Pnj/9dN<tygXK>{bHE'<.K sNKylUA.05.?g;rux5hAɂj0<Y0Y`R·aSf`@%WwI a0x%AB� j?^Z`~H 1o>p-HQn7u-OQgy-RM!FB0a5\#on 1"J[]hꄢS2>Urj] $>\?f,Qp;)M躉({q8W!`� WXIserTvH3$PsS핮Mvln$w\e_*d9ǧ 0N=D5⎟LͻOkł ފ#&wYD6E؄\Q- t;%CLY'B%YSf1}1W:€1ٙ4}2# AF3pxHeVgeZMj33,u X<__ރ>^ՐSK% mQ ۔|6(Tⵀ7 o4wi%!Kd43_(d󊵇v0?%%Uy>aUUL9q#/υϊtZzw44mtZ1$ɕDV=([4R4gy B'UJxD^2 xcB׌sR{ttu-s&Q&&ꛌ -"P@P2;B! IW�moHwePN!V,N! JR̛ GUmK):a݆؈r|t:n45d/hbLi,9^NgG-\Ũq[(u! lnfFC ;>.N -cZ#WN{_mg戆yc&${bN“#x.n!$ AGQȄi w(2Ϸ^UjzW- �JoP;_rPc^YBu;538Q[kp&iJ̈́cŪc#N?�d 9ȉ"PT@>Uj]o+] we-;`zbS%)|ä:FGto|v]ٷu7ޅ%X~fϬXx)DLFgwA18v$D8B@vPLr/'sVC#ekhrgKm/zhdRRD. CGF=2 fCYN[06ꈄoHaȶʚ3[ĭAqE-3@=ր t/,WFA. TUm>@rki髳\<Q67~uk[^@9 2JG`~Qqס~0(vCrQ~ɗA!- ~f|ܞi#M0DXHw&Q/M]:̱6aShTPt54:rՏ ~9NRDq'} |w[Pgu*b̽gj=tGЍsRm^a/R8pT`ZKbWNUowz)fqN/{ȡ#@e\tʣF6B1E|<}ʍZģhGyIbUy E8r@ͯH'*V"&rL!~ k/<7]l:RomGTB$tZ(̆E!Pvɛe"ERȩ%] }i-cn5iPɚi]黽ĦoLj')NMd_Ml5q=3gxrh\{F`BNi%E15#(|*q鞏E#<R3R>[ccekbHfpMOi)W}<"D,:xD{NM;zȒ>~ty)(uB֧PE6"M#zeiИ7k&PO4WDBT`3Ƨ}tAI0D!蒛k[--8s!|c(DFtku/n_h<j 7*~ g{nj){ \ j6JkOUe*m̆noz_RH# G5C6gRd L7ꮱ 4CːxG ZLڷf#>}HDЇ::%Kci|+iuG  Fd!©P8jϏ*ux+[Ӄ d<vWQ/ aÍhcvzK`_ʗu ulgчA>'ރ<bڭh=Gx >uR6QoFCη*}")E) i `zHp8oyTy' )RcK|aw8}h_O~￱b[7񬉑>KkLmK6-m,ܤ\`W\芐 ǤYA͞3T|'Z?NSk^ގtH/�c_!-8MĶNI%BDVi@(~~c49\ 'GxN5FEّ1N= e^!ú)q쒿T\9+h2Rv|ʭrdӡ`d3piJsjOdr9}irj4e%J`2̬.Js6;UXmyOQ[NbKD[J yN[|\39`݉ks76Nt^7y?5i/,RzMLzgI`q\J>ӕ9 4׮ ߫G0.H[CsoA38]ܗ5ft?vKz#B~<җYeK7 �3P}K<ɎK`-K/@3xz4_ȎŤg .z4ѭ_ګOvXe~+go;8RAMVuJ\.U}Yvdwk5MGTM0m&54Tp k/$ɒuz~t //-1!zh=>J!'~'g6 @W~\;L)dNJ`- !$ݱй@;Y//onV 0.]cHk"JHSzXery!%mM<H^03Z#0[Hk#1 |ʶ]&?ZІ]J$6b(Bkyr44`t~g~PŖ_?"ʵk(.(\GC9?JɅ+k�`KIIE:Xz_m^i5.Xs>@/UKLWs6)]=CJ*aO»N֢Z{qOY_Q vAX[j$@5Y͛R}ΰځscphU'LqnQ0#T *{YoMBa -'cœČC/$_IycqâsƖт,ץslEhbxKY=m5ٽAcqh>>f> t Ħ9?8ߑ~%w@�G!h~Ύ*d s<d2i#B<.vy/dӁt`Z)#%!ح_l /p+)? 'ye�Ms<A|1st%mԎ-꼍2 -S#蜂9*KH/͒-dW`H%:g|lIu=8_td:$PP+#`:wm9ۄʫkT9ZxGxLQ<RyYx^Ճ)&pȠ֔e ٫؎L2q101JQ|xEcDϷBc/] P/`Nvtv4yK͢;AruZmvdメ i<=,?| S˂ջ@Y^@i0MeyY+>BY|s�( DxS[J@!Ü5ʑg"ӷpTn9P!kv 1>h4hQj42z-8/Dm<YlC֝Uh KߧiW!|aW)!)v^s$,SW(i]Q)8{0jĢ~7TI'_ƺl%o0=? 0 :$*iTCu_c_zְ[eJ M 6yX-ߪLgN`S{[<۰caz%`yTeƴN3) ՞V 0VΌ\> +#}G)O!6�iy>JQٽhh<Ј#f 1"1zA`|ږ%Jb>^@#p d{vo=I2@3M k~$jNb(K/tt )FQ9ꮺ"EcQQb#Kh.HYZ ?SrVm1AyMw̤e3ԓ*-*J7r-!]`8P-\=Y-mm(YAeIl?Sqlj岓i~ઁs}pûZ֦9b<c#t8B/̴Nzj->aCD|h@npa9ϥ`5:t#Q||?7%MDw oy, Xsmf�20ݻl 2\ %3i*4Cר3GJ}b:HUdLGtw"B3qSWN@@^"I5bIrUxІETgmx4KU ;*f ~_:[b} UBoX ?G'g~8m+sfx+c�]0)Ufz`'Cb_ ޳wkڬx@b{.$oBB .d�6^)l?Dž@1p1!AĪO7efa@AS5'yQ�pD ;t<żLJaA _zcY& U’HwM'$ߐqj5`o?yk0w<FS[]".ߴ~owdICĘGŸ ~Űm{R"挲ݥhd J|+JTkgثIǦΥy?~+;9^IV±�ݧN))y֌VOx-)CŰX28:':j{M 5mK7[^A1CIJ^0`t_wG7FHC4GF6RaO3=yIl06oq6uCz~x '(+eGL6<i,)|" &M~R-Gؙm$-R3?=m4ރtw iB,{e3 01V<GhS4AJ z&KqI{_raȎ1?v/#i+eF#]J1ˉM3B`F^-Z3}~0cs++8mT f+q!(n&S"Ôk W|r= Jr‡q5"4@Fȴu)mGCPV451-�X:B%9ypS_&#:;IQSk2;xz%'Q=<-d.4$~e+] ? O| h.G!욗9$jo$h-ƘFTP* t=>Ҝd/�yS%/¹em i<u»>�B2smqaF'"6r4<!" M6*b0e.Nƕ>KcLuJ+6S^>幨-R6]�CYlhꪏ}~L:>GG qBF GX{"O[?̶̟w=PJuD?lL-^QMFid@U3J2 uQFWͪ۴0r` l>3XI so͖8K0(H]Yg4@P~XϹ#\313_JW}u/;XEv#K. @u7ԝ*S}p,Z5Hkl4* K/):[I"Oug?S)0dzgN&"z">-h&p׻Vž#H??0zwD=bscwktb_ ,0:rJ?`RtuEm9 8ʾIgeے_ :xz/܈PYN+YR߹v&SE yXED|?6xFW, Ѯ;PmFҜV,V^DVד]L&Ẓ+ㅚ5.>hlNF`- qI;O{ፂWC!n$myLÕEF;&W d(I9U"x'ADљ)c#7:%{"%1_?2LN+ koe1؉#MD3\M`gjsD762m}g MF!L@ `Hoa9 +r<,ANȺ6v6pMVfD8]{Tท8E#K<4 $>O^& O:=6 sd'!_UM(7dَQ1P!~na׬vz VnڨCȉ>z`ǰyZHc!*}-Z2 wHoWхw#xߑE@&Ns*JGx'EL{+zC kf{Ae55'ZusW>h8O=K/.Zv-n!I$vwE};eSI�)ٷIG+|Uum.j)8q[睟4eyYX,a? i .&_Ck2FFwb1 Ӕ@Lqz99[%u<2yEIX0OfLWu �YS) …py@5DRDŽ|wQ$#025Xy[|؀j^̀S$&vDơvy1.9MX %2Bpu`!XX=\Z8#˖\0F,wH@.bY,bfϒ]5$ԗVҷap+2ycq_+ endstream endobj 801 0 obj << /Length1 1630 /Length2 19479 /Length3 0 /Length 20309 /Filter /FlateDecode >> stream xڬctem&b;pǶm۶m۶mfvŶzt}~1=qM\{EB D#`lgh"jgL@K 1tqR㐦Q41s@98[ 8pL&F�FF�4 @@FAEEL�C@/ `jamאɪ�LlM .F�i #[' #?9p�M,؛8X89}X8 l`akdbOvJ__0y;'g'#G {gߨ¢N�;ӿvF./_Zg ['? M�NcwW.Nf5/_u =m/)-4ߘFcYB3+v�ˍ]_ "gf(&a`lgk061s@2 B -bm-k`w�c�-HY4? kV3w0 gm5K =-N&F�S=\/j+-l!*[Z_?�fP 8+{?3`^4 �FvoB>bϳ;@o ?~y/0"FviF.I[8kMLMז팸-ӳ21F&~ؗ5)rTԅ6Os~ux,JRG&K5*!(D"b: -8W^dW=ڛTP-�ǝbr~'r-G%~5JkCFlB/:;'MD646:2w 6pMEerFdTݦVOqɄg-�|@Ͽl'v XK?.4,н,qʺ~˙nks,NT̲J/>`,Jώ3܀G" _?V_ T!\fM ñ[7=?e(yěbs,>7HV3`e_zKlR 0$-f|h<{ݶ>t@>f=H Kr)(X|_OEúfj?ڻUٝY}\Ykf}RW>qPH+zd1G=:3zSZuF�WfiKA Hꞟ&;Hrf~})kR|~^ AgKW 0\}S+xFjyoZ\TP`)I <Wwe'l ;ih.)o1c*a?Dr'U'W {TBy& y@+ǃ:0½eK ! X$"^p?8q/h{SM~ͫ-:^]܆%B"@-o 6Nt=vq~EjlBf6;-z%/.ScMumUm-Oz⳩ˀUMcj؀pjY _ڱބeN@B%ebT Ֆ;>v,SUI5* l\7oqonbY-SNLh g>ҙ?@",qgbF1ֳPX'fGXap]7pNc}f^/-)U;56jH8ATwN\vm)%�*˅'ťAi(#^}iB=ܮK0^}#)9pkl' 9V\- l@Du&`o­_ߋwlWGN^a!Փ;,qx$q߳nt`s'F[5.G+x5}xdoCN;ٺ&`͝g;YH .ÁǕp<³x[mNw;=D5WV r̐VP24l u%X~yq:xNQ)_v R޿U DZr,eՔL)m]{Q6k@FaRvFGS}!@],Fp}QbQآښK"JY 3*Ʒ]&ˇunVB*cYV|3L}ɝ4kƻQ-,mH}1¾CzVJVjj9M-9n RKeC<rAnYyTXj4#"J' c % 3n(2.UA'lڏl&>tYlGZo^q�\FnA8ɏ?79K_yǫT-:yA0%x&u`Q$^NK V> q8a[-:X0֩}77*a0{'l.ē(^</wi7aV^ v0&o@JC(B}R1ր-6Aa/A>Az엖KF0f 2{xvqFNDq:"ƬP M][nO(VFDB֟H@\7<EOaUlg엪]$w3!vqQjO\{`BWCDi\R)E&h%5e ^⏒y^ҥ[*:߁<bhVV4XzІ�j�oe 7kD"[vdiQz҆UA86#oe_Td蠇q_A!59+.D;O%Lŏa6> Wnd ^RmJX o[8y/GjȮ[*ٲ= ӯ}fnA(-7YVd^s_ >D7hQӒ 4h7='1R3\RF!hI04~ љ$9ͱƄ?VӘj4~[< Jq瑊P ꗫ k;7h,S5ng,+bs8 q\zG%oAd˫~\,N,c4=<z)'Υ;4-f+Woj�x<ME CxE h(bU\Ls\]y.{6bR$ZKKmY`BFDe6+aڹ7}EvY|0^^ZZszW@&[k c2_q]!pP)}^ ~42 d״K7vm!56:IS6<jTocrRDyH >}&9!NC<)G~Ul' 㥙TiuŪ^StZ7(yWե 1p�>h}CE43k)2uo[K\E{ppШP#n z1]̋倅?9$Ѹw4)WȀiC If%Í 88vZHra$!AL0:PSmtBU3WS65D~E郣A͏ Lmx|Er`Z&R+U +2uw(*t~r,~> 3޽hG I{:3眂}$Dߣ. ETTաe?E 3Wㅉ~�/ sarYw%sRsqZvL:6: Ҩ%1:,7 \v?n}طbMm-mW |mMչ%5c^Ξ,Ykq9*V=(I?K%^WC@JR~Yχ\y{;+Ry} s-)n/HE!`-:Mi׵՞ b JC8`z-᠂g|{Zmd%kFUMkkOtB eQ񦬢^ ĆW PD'TWQnc�Ѩ6d q@pRb"m4!(xN&Nt%||?RI~#\BB6&(!}˚LJƌdwy͈7C OoE:A0/۫2yEUCdv~jeo.E{6aN[1+w٬JېUֽ/'?�LW?UQ PI} J#(TXELׂ4_PS Ǔ j ěz][1|ܗn[9 3BnGwC69Լ$IQJU`W>nNG"`AqNSu K l=rǚR1:7{̆d{ʳX(JMDҧKQc^5j1H$}vix@'`MvQ].h%| U=kO^U@tX0f%%9s M3XKKᤋ$i~~Bcهa|:i)([Qj -G~&gFnE'^Y�0_!2 A =�q#ͿJkP!,iQ iH٨F@DIOzGl],/nԟVO_?QTLQl#RdD μߚՇ2A3VukxE{XLlO]@0?Z/j8vi&'ǀ6&龡$�2VaP*mjC_?4P`"0ܠ�o3?aj:nVu:額 ۸&[U0!nޏ&<j?'ku i--x(ij#f﹞@vbv׌@d/\1Ŷe&KͷY\,MՀ:!ON3slw?Cb 2�<bt-Kd>t,~oxވZv�cZ*&o Ґ9‹IsFhœ"lNl(u-(HtEZ9u֑# �6+�2�WfS,!yg19>W۴.|;:i{,{'Fe2r(5 v:<(fkFS /pĭ.^ D4!1x͚r9Mcr>ڕwnX3\Y{PkX'Sc'EyK;uiDjP%r$ivƑ?%1@q`OL/u֠pևB!6+ie_n'ߍA R}ȍ)@:aGWlneC;p@ po?Z[ H^: 2B {z`& !>/Z͖EЧZnP; dwδi":Jg& 1K1^28"$]l_ T.uc[|@3p\z 4 FXjI2Y˫۬'}g,λ|ː>Px`HA :fM͔Xqh鶑*43IM K'UHC9pш|FKƫqd5l}v{D$(�l0>ga^9=pN7-3r6>/)pV\!%:%%ˢݞ qĖwYbb:v&q(y)ť*$vļ�v+ /=$V{ x PHӀ1Lʋ^'7Ls:{y;:yV<xe0Eu |h6u-(ąaVnze<#vDZ?L-`1\KЪY/6Cߋl7<mN ~RTA3{`e[t dIx!;sV`{(8:$iF3Fq+$K of7=YwG*0մ[�4he 7 t~cOGo5"#•* 7#_+Fw#aHʥZYްm :NBzq s9䃤J_.ᤏT? mH9E >oMq8;;\uvNyI&]6Cq4 ̋_bF s7(DO[pk ʶIKBtѰ2XELDقȁgWQ)FF; KA}.E"9d^Wwg:mU\KIZ8a_Wݚ#ܹ(1!DU zİ  +Dٰs <>oݤIЄl+ftc sfl:d'Y:u /-G^uђbޡDt_Xk5~/:rxȴmhYS-Q Y\mU|K$u6㝣ˆ<6M!u(z \s 75S�IrR.;ײD08 .<(aȫ`Xda޳7h\|?2_äMSHOxf0tB9lPbL剹g[59{_UkJ%rdfK>M1&XW$.RCR+� 4 mE1U v0<nub8 =ǁOc[upW:^o5"�I-AhH<*+ P/ݯ Ơeǔc /UBw viW*ѡ&z)_F*M>s; &Gm2>{g aQp%\6v+;D Y{ooKabNp{rL4A0J!vG,.؁n-gd _ ΌqM3?kWN7V_z;klnd%J?dZʫa<lBB@@%,Y"w B -2s><ȈPiTG73ߪ:xeeBĝ?P#3`Ӌ;v=M=t_d&=t Uu�B\d|i}c1xݟ2ܒ:wwCջ:G.42PB;]~k# :&Γьz)-VBE ~[r 'ƞ_ A ByҖ./ {p%`}Hs}_;W^%`6$/i7Hզ{jdEj*e5D%, 5\*Kr#ږ4<E|^ #Gfs\t]�t`ܭ&A~Bi&ߢjJI}WcVpmn~-h[5\Iu.p1D- sЄ@@۝]\r4GH3c`]&+.E$d6aq_CƬJ҈R*r*Vy~1=:.\IG^bn8ދkҌ!vWر77e3?@s.K/D.qrꡠ:6=`—vO[m?H+ ##IZ1:T>IGÅ7utf(<W^a /-z%ht1q7ax:cBSЩ2KaCz'E߻<_l}#s ϣЍn9xmsʃ=^eWUl?%zt.]J$(+GC2k|TeGO Li>ppHW3r񐛺]e@+ !@U rtUͱg831A^1%y-)7l֨ ݒ&/]}lֹ%e=Z+ŋf֩qvcmŗªg298G]}~5|Jym/{&ߋhLQ, HoJA~#|Gw3KL8 ‚^!bc P;X;< WE>)9 4kGJvxăID3*` ?H8ZWXEt8MUxOY37L0C7tVJME%Ui|nݻ0QɥeO{h4}0T)? 'vi0Id58-q)C`oY#wn]Uco//p#y ВbLtU;Nܡ*XUs6czqq$p�gKYakqZsͮfT!2p Do7nPC s0&{OS!~̰t,.%?X >rق2чiZLVaΫ$._t$hcF`<4>4ބ%<T0}،|O EP.wjʸ=T�i:jޅc&7 $6Ii>5v1ZXV6;̰눨zUL1/@A†M]7wiZ9J+hWtl=(1d=yb:B(M9jޙVxACow~wQ6nRT!C7eEi(b4ud= 9TN]K >:E ~9A4L̞}HlHt Ҁr:\NT ad֩-;نz5qZn0p`�~c><R/3 ٯ[rN>+,ˌruGH#l}4Aݳ!QƖ W'|*1E&g mAr(Z Yk`F[�tsV8'L%L؍*D*9ʓ%7j '\C9Ov4JϖTO glDO6X0(Rp!wu"Lo7AgW2B4h!0L)8wq5D%O2/a 1b3By 4G?۱ hP<Q udLsiؑA&Pysk5 3R sםWBcq]MaףnMF@AV'9f2̃MmW$k_=f,Fk37TPjw)VAl(#,  zp93N6v"٪3|F hy$faO0Ũ܂';5ĆMZLoFzϽ`H9 m;=6[ lP ˍrc|os༒so`#[5T(WSvycP,{Foxύ)h},$ʋj;b?Hb9' XOtIgf"u4sD+kET[�4QA(_!/HC8ߩUhzb7zm\8Y8 Of,Å7'6guo%چ2cEQkj~H4śkŽϑKT5asqdz; Ԭ[g4g3\6-G_hJʡ9viOQe턺aFf94ym#-W wEMd6g4;^FY_r/oyPiH]BBpWXkY12N1d_X{Ra K8g*p]xpN3 \ud –UxHWR[[GiK1^D@cĒ�2>(f2.dLmr'!?P{x RW,>(1\ .? pر�)lC?oЮ%ۦpbSՋ}Lya};HE 9)^Zx~٘Ut'Dy ඈ; mW`yX ˥'IM O'Ex1I_kUqQaujkޡt?-c7G$J""A�)oV2Zm8UJBvor#14xE QFTKE~~IgkBV-FMϒ=Qa95+:40,/�¦8/I.;CJ|ܾw8Q1Z jfR[)M@CW4,&=B�Z TSHy2QG&%1'Q ?c2'3SyDYE;T%z%+ATiAZE.P~!vU'5q)�kT-.yYj͑XBb%I7k`@wL~vo\/&yk F_~Oԣ\~6 DBjm[ϯH2iy^c(k$/ca $]4e eTpXb%\u5&`�~7i겭uhNr} !hg nvKKxMi3}lGC`ӆϰ8,eޙ?ߝ}[YLWAfe{2704|D< ~fD$,h +`Q$3ɸ[埊1sS-*^rLE`[% =C! ` ô*+ahӶ%+p8Rޏg1JM� 7D._Tq"uNȁIWXqa'|`[| +XsڡypmMH+5\B|~x].d!0b7@ )pF_ZnSnyO[xc 0xӶ{e_3;̗z8 iG˪gŚ=9+pER1Bi>+p1ˣ/cz5`eȱj ͣe,RռkRDox Ui{G(d�ǒڗyJ'ޟI@&8a160IKq wid&ђrtΜלO 2~\S~S;d]A7$Ma#5JrB^'6rVocƪ<3b} [bn _[H9xS{˜1Cm *4^.LvEziTGhٵH#7p|C}nW LS~ ƮPppxX,%_VZ%/Mk!)oP֑8:g0y$-!ak �B&31 aorYڑKX>Ljh0"#{|^/NRGU?\$)^d_gדpH DYQvGɈ 8T*Ksey!kOyu#\*1Y-DBc~!4 _uf+YE=t*N7RmX^v1POUL't-ĤkҮ'5 zr%lɟ1¥]M }B9%ƹ_;94+ 5Cr;z-W%^J®/_弢qP4 p<9p3phF ۭOT,H Gt�u[+BF"*~;?teTp6I=aD,=Ęp1JAХ̒ 󴼡}0NeATEE]$%6Wn^ LrG?sAc#D9oClmJG)(Y- +_lI#H�M{?*Ը7MFH7]:0N f�sIUe9ˇ];F0L=DuVZAUs b a+>"LƇz}<[L4PAgpFȿ`J*u`<$*! `W3N%/z ;AhVuuzE.=ѿx7>Ŗ?nS8W 񟩸V3WTnm^S,6\;0NR*4CSR}cCzܕ5iV~( &w@u>vfFhV=ViQOEW?AmbIQc.;v=pe.>p"dm N(RNYe,*fQg*ieiY6:yl]tФDQs;^Po ݁E{$~?Lj]E })sBmS\t<ܞ ֗=ZzipnHN΃BԤƐYGRcz{xN)A^)s"#< lteC=׷`ۋ("Vt}xkv8HU˃,C)ɽzxfye2:vFFh2|o8qA_nz}җ%}28O;"vіxںt&̶97YE4Qd4制47JpQc$1b�#)12dN5z z7\ҧ{ěS_kdBخw0P=D?diMs56! ٓ'8|Xw~IaظmDQ"9vIj+h"<vhuk=ß6h10@>NI N-S.o.Ƒ|kCa޷MyLlZ}吇پU2KO8oM)<$2K|*ؔqaqƊ]9 Y?|t*D:ZNEYG;H_A/Sbe^Kwg˝>rRhwjZ-(W8( BwVZ5u$<z$R)Oib;ZR Ke'v8ҫi;(NOzOI$%A QL"j'fC+C'b`ֹMsݻxw�)7wv}' %5,DX|HK'슍xN=/6Pnh2>|vGg(,y|Zt`n}.Ӈ1}iǵ-¡WAgr6 jMh#NJ&X୘? ? ,Ȼ]щ#D9ڹ-*,NLK񅱳-0q�<&hx۷$0BCU=D32]ܐjKXq ހ(|:~ݩ*hx fjWaee=U?Cc#4 y(>JcTʰwMi$}w pCO,�oW֥]gHPxVi '@F�O; Ÿ ynK '|3֨ܚeRE@@jy\y)t*z>ե^I xj͊>~NJ}`iuk-JbÑ A1/dSѢɱbߜB[%iզĎ}�UvH?Jh|x6[7ŲgYƭ:Zy$RpP Ak[h,aӜzM>Qlf]<3z [Z*̀ (gLO?LEUȹ!?dq**3 H"[fu oEgQ k3'!$2AmzV7A0o,&9.Y0ά�<>v ԡgF $7%&ysAsy?8~otz:^TUT\OR[g+JXͻF'gI1E\'L-<].99/3�򶔷KG+D..mc_ @ Gja<?> b|DЭڬH%_Th 5~8:mwr۾iXw۩\Dv0 ٝ*#iY52b%NZ8Off0X ӓ'ڏ6fG "K?ez<M!K٬(r?ϗQ/+S"G <rh�LN}Ki. = h'$5/zc!%hjTP7#n?iLpJt;EU-?G*9n/ 1vlmx-ܩ/JLExyabHeF>�SC .w'cF?YȖhԄQ< /&hayuFmx~5 4y #Tv=Kh<UE>#?n4#bnD&"{dI7r�^"rt[Woa8Ait҄6l^ɂ܁~mwu+%<!溏@)0e;|@_[CMɠ (b+83>[i RbXّ! dY<A^arU=֋FNlF3xe5ymbZxbE~Jn D2$@X-LЂwCNP)s�BMNLdP iͷ,%ZpЈjsT4a/ Lu*V3KTgR[@θpé)"-r\eO dp *X*PY x=>.Ck](?޲psҲ8HO#G䨣pAed/) B?Kx" ~jL0�,,%KZyP%tY$Ɇ t Gp^.""ߍi-Rmց+FnogWAFi]8Q`n+8댥k *g7~b7fF epO"8. 4L mOC 1:#\a+U ^f6gq9I0n{7vVoa֋pʡ_9h2(zINMYt x ~,F~H5ruYOVTmG6;G3)b`cT9" OhT&XȘ<w!hKX_j 57"@d+#Pl8*O~3Fix!Ê?3KK$B%de z^#Go:ܝS5hUnCS%G.p-5�k݋v"rE:}+?Z|n9omHbl]}˻ux:M)_,zL_/4vU`>ٓGs/R`e"-FG0OxzZ6tMs% rW"OQA=+T<.T 6C h@ZobpzIpyʼa4C7\&Qd 鸹!C14ZΆ`^2K7uaVӣ9Vj{fPuv:^X*L'Q|mۉ&݋N|8JT`\m;1Pby p .NB,{hJɊY~U%6u~f<CN_ZOR. ,͹`.v FbBam0:%jX^Y`ɬNv ZuF[%" dyZ6QŞO=c˺!ƞVO±51Zaց$c{"6ʇDL1)ę[q3Aa)oCrg%',rQGZqM;# %V>4@N=}j^`6$#g4#Ϗ'1tk=b[}l-F 0V@QJ &ʃ3e 7fi]Se }@QHl92:wp]\bat6p<;8mfpɼ~])f}ƚgZN YDzVF#ʉ^YFJW6V&BnLDCeñmk#bJ0q'RB3Xؙ sNNֺKþwfʺ544'-B>NQe2ԩrl#F̻,UbOV L$OmI)]3XOc5ekp $5a` { J1Τ|@!QKIzEC\iyYJ#_1m %tXu E"FO`O; 5n=8'yZKec P)Zu{~h6U6bzP/UlG<;_ !8Lsl�ytHh(p>F;%6L,DK"F~!R6U=E$)Sxu}DW?-/"'8(8e[]J2wͻ;B@c e; bSiR?X Ïؐ<[Q}  5w)1.lˏKDX/b=H%@i##4.=`WLg=ׇjs]t=JRQ ^BEm9aO &CAn<nFpE[I0F~BSWOt) ]f*]("aփE}nי.8Af;@HQȥ^{C3+:Y&zk O$0J6[:ۅ4L 9 r<l˷: 0 lUެ!{GE`oap.`l)*2S@ӃU;<FfRFګ et,u/QXӘ;TfC0͐A2=#@/೑IQJ%T24&Q3=S -Sh"r\c֗b$O^قK\1C&U>wJnr21*ؿd/!}3S%}y 0+xqz pg+woSR)s_z{gCs.}<e8ͻ$L,_gv׵m9J)PMU*d/s5]*Q3&\S9\#c;otx0-Z0'ĩ r$ *'u,ϺV/9G<GeLG)ߘ[n7 ;hѻxfvG +uglkzfC\0 = nVE Ml2]cb 2Ja!@:$*T^C{ö[mQe .zl&V}=vG.0@g鑳2c v*&a,`{(hK0 = 0:a:X; 1P6A Y{NGvc&Pc3wDm((�U9_U)TM#;% i8~<>l</>w\*BYy]AII>ZHkD#Mae׼ .T3ؼXIRcȓuWF<أѻrTR�0OͺTYz,Hb >/L!CTFo|ZNrm`mkU4o7' yY`F,6Y>HW,C̈́ʙMy;hYsI2־X c\1]C-WiUh߻ZjJKOCKoޕ<d6j1Pl˳, ܒFXá)+W΢UZ+Sem>ǘbLO.pslnnܐWX�XRKBƂ׾ӝKO~@2 ?_y=R A唱$ =gMչ"lP,c/*@οo~NaVO� ev5yP,"cQ;aX r8~+[3 ]ȨnAp9b݅yf4vd8ЋP<AEswƝC-qm7*6?CDqbQփw|AGxxL?\Y<ժ NW9@}6@v_J=V=fTUx^$:fK<eASeDBYlEۿ+x;O1MAL0,_ҕn0|m ȳH|ZUHMN,ek]dF0T!`XCu:L$"C2}3{6nػh nmgy 2ҭg@9S-N/ i9SW ~l(qe"Ȳ1A{nH)�X,4 PC&e7Z+a͵՛_u'$;tag)R~UiI~ &n6ZwR>] \5ESTAJVN]b4ߨ?GBׇ#n#O*LRs^ҢZ6pF3f8~<#NAa))d;nR`ʳBZK�Tڟ֞ #޵Cz1D3noT_!Kit}[^K5zk^ DݾH6ՆZb(5\x$Aq/$͔굅 xIW8|ۏ}1۟*V`XAJ3�ͽ|^?O j*c mji3|*6זy5SZ,Kgz[MT'QAtZǒYn3[fy-AWhk!<'Pn'l-n+]qްitrBatnPQaݦ_'f8d^ u+ [W`ߓ!p+ϯ$|H--|! 5N  l>,^"6^n"7p5Tyat9qj[w_׍L^)#1^_0+7Rӟya?M[$)hٴJ86gc@%:Z' ~ˌ6ņ0HW>(5}0"!uŇ_rK1KO]CͶ_Lmô돖qJpt E%@H (:Ңc*ֳӼb7@F"\hz\~mw͖Jc!A-s<T&9!zoOH/:":eߪ@ZY_Ya bd>eLtifك?8CNw#*NmJ(j R(Rx J6ufw 3@p*I>@%Lo_)s(vS@}.l ¸9F{\drEgš᪸Nu L$ N2ui̵T 3Ď!o^HͻRI8~&i#Z=:& w<r!xSE_VnkE |pli%^ �0l[Sawu>\�Eu[H endstream endobj 803 0 obj << /Length1 1644 /Length2 5523 /Length3 0 /Length 6364 /Filter /FlateDecode >> stream xڭTu\m.Fn`dfRAB$$AAR$ApGo<s}8@0(JPTHD`�tF>ydܼ$!'DaPu $��A�11,!'@ G#n(�C ^~~Y~_8`<`7(  ( Cv4�(w  4<f�M�B�FN3@ "A�W��pA]KC aT� � 91n ?g7$�`$�#n  �C!.]a#` CfC0D5R+O;;60WM` H�  p# CGC��r"\ $Cݝ /p7ϭ�F!AW!BQ1LLg&J({V0_vo?0Ox~ /& A\@0&$пO-Fߩ5!'f�1�̒B=^4 �=_ȴQ@L[Tnie$dDdH rv!A]@ �AQa`go!$@PWO *} @0 *%f,Ph8,a.<&TUEd�b2׈IMVL"H_g} ؈bHE~`7PgA2A.7@`$0@~ gs0g2^hsGm߉՚=uEȖ:^U Ս4gw:|h ܝ)\ vޮ<eViPa"W{1_g>ZKo?/goG1Ogp`Ԛx6:,ʪ7{\/q u~`ώ''KBko.}e/|yrƭP:gq.<{A'BQuXmTǾmN{o^jaFQ.#c^6LU|N3=_ 9VLuD +c+  JI+W=z\kߊ bЁUnSg$د�%+뾈գۗK$3,Ѩ{T6RZ}\;E:%}$ֲg\vII}cM{GPi%lj/uwеVZXźq%Ig*loۮ2fdtFK%3g�ξJЬq( DE{NUQ a:@vt*, j�l\ksx;ͯ]-VcTN1:}edlZ[x+҄~bJ{ǠsE .6bqc_ǧ3LH"F^7\ӅԲ/D@/K\ғIDC_5Ҝ/ ~W4H\ ݒ\D ⼜ /Zi2>k`ܦʃ/7%HFb5F}@q8H.ku+T{.{G/iS}+x$g>zƠWt:][Ah,lEc2OaUcOjLxenBY&r#^-:# m\ (y*#dYAVH?ai?´* Xr13Qi)kK_ͽz1l^wHqjťݠ[8C1 g.J_2-#P0^ҟF;Sf(Ԇ[,6zsS[bg] Ŏ|W1`v-O`Ǵ-cǯ) AwԂa:jv?e2 gi#xGh|ōu-/'p G=,!:T.kex#5ā?4\,V+@,J)|Z uܴ y9i_"/9_S`+7>KtYE?k Z*3¦y]Kj4Z`*p+Y\@<lK5{/|+ǽ}g+.{&BZ]ڻp_z$d9C%)X<la .Z iJhS)5lPC;mt0;Jim=*ʢP|W/)mPfL0cM$RG^0Se+;%38ED,sزMoH{S lyQrҝZՑoŖ<zU6Tu]hvbG@P-^|9;4MK_ lj =oɫk*Q1ԇzǞ 5-ˣ>TPMkT{^Aq^4q=:٤7M#iGݷvJxx{ߣbح?o;_Gm[m3y*=4-Fyjv׼Druk/`xKõ 7!g0Z1"܀/Ot]Lڗ8pX)bLJ<8igT%Eæ_+fҍx]}h,AE̎ͅʭp!SڤarH)% }i@sHTe0uw9MTi pHP:1U\3_uhOhbs(̜+j+nM殓\جC!çk\#GЕT g[ SE*G_T*=ؘ?i�iO>~lgSu "M[' kg^9 �Å% S7:2.edz_Z"XX(, rx ,5S\YS5Ujz$C1O_mV'1fp TXeKc )i`֫JQF[7%=&KFِvŁ٦"^TZΦfT`N5eUi%"~2^JͳTAO,Iz6-B9RF-xxTB�%@i֣{= %fáL]u_>mv]<;i}DDu[WXnF:qYis םgcCg.M%/xT_Ƥ a3]O]6(ŨRW("ކ A*o&Q53O(Ja'xҊN^<$ k9yT0)jß.R>?E"s|iE2?/dXq7.ğzj*v2Ay%X!Tilˠv: 9esSTד^ e 1$rx[| Iت?prғ^@֓S|v\Jx<2 0yʷY[SZr>!tn5k_qԞ5HhZE? U71 #L8$/Ϡk-u{@]h1c._^<R-αɾ۷6ip&e"*I>_~Qw/M^Zcƈ߾bԭG˛/G5O|;v֓KaI> frdKm*{SͿn=+wAQ yմ}UF <R֛rB}k3,]kջx+-sP[T*”>B*6E5Y*d k *M4YIW�Zy_>ur[Pcsk`IvR.$r^k_ ׃*on1g'UZT,-qRwĤ~$hPQɍHX |§I?8-U<L ӱ^Z]^q̋U0jяS ,o e߷ ,x�x Ѵ1HI/Xe#mdTeCHA ص#o׶0 B"Q7Z{!?y#hnhs:HA@G^1!p Qđ^L &fa=n t3Y:j^$ZY.?{1�b-޼ek "W8)j>lŭ$Ny[0(Sw\yiy<}}Gh>{p{~&ۑFI:VƓxs,Fm ro#|;ms.ҡϖzWpp|ט0hqHYVw. 3؁za!Ez^+)Z}*뺓KRS[,GP8EZ*^((vv-+3'&8P6#<&�\Oƭ5M-APϾ'Ca|\jC[>GXe W{s@ M uEO Nl'<\yޛ/=>$ K>}YTbwatü->1‡';w7Q~棹wMYS.DTueu1nfKEyuMТZM;E ӝ oN{G1OJx?jgV`xn=΢yYL Ř UQ'v5;uxh!)�D&V I7L(g\a,u^x+B.G8;Na/S󔝥s8yCĭvlߑ{p<7+uoԔώcz46%C aCqx"fxpw 넡யnz\|{kA@cu#.!J|fx_-Ma8^5//4`aԙ7-;mXV6z.RYbsXݦo.1xJN0=pɔ/&I݉T75*? R\3zNlxηO֒ 9<Yo{h,*"oI~K:r"`ٮ'^q"Ud*Oyfe~ͫBzPW%Rm2 Bj2.:qL?kI/B�B<6C4bZZKZeŐ18U~)4W_ZQddArpz:ў v0EvY'zlP=Q`96Xœ$-J[*XA[>]qmu`:+"V%{#AHn($cT]ǔo7BZ|Y1P<;Iyz=7fĉ.oڨKN;Sq7Z|갸k"v~z3=62ebLD k&oJ>SeudA\fԬ%]e;1rr 'HÛ` R:KZ?Y-71 "[_nSptݕŠbI\y)znnuH J{S+9O?HḄp%e}sY;9CgP9[Ccnu\It՗_FPub݇>Ο4yP@GcUᛜ͌c.N /Yvyxitش<4N-/b*:49)ěiD{E -UIHCxSM۔LJ&Z:�RԋWO;[$%L_5eE �NLt*Rd)gZ! Mc2Ɛ=9&.>Fӭ|D3l0{ }Db[,'$Rglb"dyOZ窑 ;X"|/'ŮvJ:oتzG MoUlr-u캷(Y;Ԙ9W/]I3 #(H,x3seJBNay>,RdjOvwM oKAP7} R6 2)jSZ*t'G6fƌVPʔ NVO8(5`ʎ=_\VtFzRj.v�<Z7q$yZcV'=er7"gFF WUS=[~J. x`|Ov(h nyU ܊J<o\OILƚU񤻧h]I8jŕRo#wrvX|耬ۯ�9aו endstream endobj 805 0 obj << /Length1 1647 /Length2 10281 /Length3 0 /Length 11129 /Filter /FlateDecode >> stream xڭteXے5ݥq .ݡ%wKnCΙ;w}g~]jU^TIA(io Pٚ:*3�-\e\m�<%do'nh�@S�++ ftШh {3@wڹSU@%`>)i(JhR@;{J&6 S<h ;l>�L@Zsf|q0)�t9;@� 'c;;pLm\n7 'wwL xϪ$.w..r;a럖iQc3' `rv1|N Wg?+pZ;�i޹?l<j�8mYXs�3;s{� v3W`n@.оalfog 03)ڻTfo"E{Ԓ66ƶ/c;,c'2BmA6Szk?9;ŻB ,AΒ `nl~ỳN6 ;{3`j Sk?jp wIJE\LAض9+O4JT``b~ϑ/"]@�]fFff?~< ٟ9Ru13{2M]kw_��¯.ٛXge O|u(kT+. OSe%iseOnۆ7Зm~?ɠ )Xق'A34t'm�[a�&ŭiZCVjz]1U- =88J>c#dO#FWG7.Ww$oW@;t{zo4eWzi΍M^gזbpL.@:XӰsԽf”MzYn7ƕT$I&K|Mc-vV>5u,[QW|Ăe/ r%v OЅc[ҥ> #jSlh6!^ yd'N*LG̥UV/,U0{0 0 T\0ݵ\ƭ] O'|s^[ K𖨛,}f9k4jiY+_IhFog4ځ ݾ�A6o_<]⏭ۊž=E$" WHPkg,x¯s;IBTnmyﴕn&ށ+Tb,Dl~NNCo`?$ʢmGćk`}% </J=ܑx!h+? M ͠7<kkE'R =rK(e/lc Hmkz=H(z x`?uV0}!]�Nu POg yl.ߵtSuÁCpq[8qD!<O˦oê@VdGXy.˰|T뽑+ծ@MnY͏׶y2+T}}m"AϫUU!]iEWq5˜Ͽ0̄6fH)iOġ_Ϊ Ĭ.}k|ߜ1!PS\ٿ`0}w1(%eboe[.id&UF>rʎ`) !NF9 9dc4?N'f'-? P^'p{}<W|L`s4п8zӣz]cED > a5f eX7Ln34(OѤP"I2PĥF0:r"y-)Hꅲ C.Ţ#{|"ey%|&d[P?;jwģ Q jE;"h|D=y/'H-롚{ Don*O4ZF穸׃LjRa]imB_ 0 $9R<N9̀U&9nan?V)O4*U>,.YOmM82DQ=z:-UcEqse~u^i|6[@Mݣ;!41IWBu&`a"I44Hwhת5DIΥA N%:Э(G_9((ӫo�Qj;#0G*2HYuy WJD+81M@>E$OiP<5-GJ^D#qu\g)=ހƎ)<xT9g;=^yab-k;2DmnyP_Etwr)ZLŃw|BtwB@K<^'h=4$[r~ S"~epgH]iW % ^`'l:G$ʄ QDQco#T,u& %yTՊZ.v/}GN?C,̖'2A<,<�U߼R_%{kj,D}m մ/a:mVVggnC8A$ᐜmKX&b/> ,'3oCG,.]YB ̦ {aO_Q5:ǻ=ŽA)΃k$W&E&?oB-nPZ~ͮLK ;Dž&R̩tꭜϛ#@jŅ:LF"v0:p:><gtW/N(US /߬SLq奋OfэldA/5]1%j \YUěӂO\C9J<dEIvs?YNϱvƒZK~ϖ~- "N"D R (irI1L@(6Iq^ G7C=)ό]3?g -Hp h񦳌4YqW̽sR,O='4^^,G7Ub)j~sQfe;O;KM#*d+z v E[=3p eɧ+<'pRfPaꥰ$B?Gp9hiEG}NjY31У2ie�i)H�v: R?<mudz M[3z:E"xFm;pGT1D:{ 0t)^Q5 Wh�<Zfv,'Ұ<y}vӜS3|S7|Liՙ.'ƺ8{c=uTFtasv({ [6w0$GL}CJ"NbC$ѫ8`S% `J/e>ʞy7<~g{ ,B0C_7Ճ2¾[F%Qy&܊^mm8n'G(CNuOAEi <R3yX^mqoڲ\KҜQ5o_, =qP>P(!Xt|i8K%bL`Rp}<j`|ԪcUنUzk)&ԯ*tFjf 0A6a2R$l$l3vDq;%$5~e<e@nN/Sj=v=qUzY;%5+3g*I "Q@@ym+~:^$avlҘy"&&.^3/yuFX bѾ0!L;ԏ藊~ⵔ&A,cGM)ȧš'buoL6<15؊jj5*[S]i>WiV%ZEGbR 1&aufdbvD+34=% džCn*pݽ섘8 *N0ڣpv)~eggU]5xutH얍*+!#˜vܼ,&�NZDZW6cDž2'TeĂfas\ |5(hHж$|LUd(jтC3w1_Hn೸}B[p5W\ZinH@fhC[!+&)#k3CɞiUm^%f]|@ !oXpկ<:9ӕ1dh;T@Bevit\U�Y4TQD)K VmC hn| jT:[s|hh >>V2^ͯsƒC$e&+fșW`P- Jϸzn%;Rc.+|#d] XPc/ߛ{p#5w(wM`BCc=~٤eRe[lӭ7T �yFV -]/*ZXA}/Qf*',m:dұ}CJ2ke$d]+z67'H eS/>̲A UUr-K *s&k'kBGv׻$W WpVȅ7:Tς](dxyuĀRe'ܱ6cI hozGDh2֢=LR\Ќi^DGm:rVDa?3}_Sj۫ lGl{kiE1:a'o1~\xK996^p>Êc r?)^tXZ8H�_y5ClL6,1Hm9i\21JkOhM<Ca4qs Dk~X$aoza w7{!9&bHK~aZfu5}cT5S>Nn):d ׌Wjms fyIJsUPp;w~,^lGih.h&>%+tt{cqZMSvطHxX* $jE+~e)Դa/oְ]£YgFb'{RR,DI+<yk8 oE;Rq[$++-}"L62otL+XIºŅ,op|[Wƽ @l]Ffߔf~{-0S<;pT~[N 43$GG[Tpq|ZF1R[!#DBC}νK]O(l?W}f>}ӲXޮM` w A75sXH!�UD-}g"(<N~$$^^a\v4J& ||$}sҪ.`<UW/1r ޓm7y:+2bm{'#(J_u3'#3! yxJõY>@$g;G?]Q睥ZtJ~;͍#⇚C"5 ~"x/݊7w)vI41rIg?#XVk7tjg#%0<x'i Q(b("_ EF 6CJ?X݂,j-H| ?rE�Nqr}Zɵ Eihy~z[X=7Y{Vޓ֐FrUaũ[[f;잔k ؞nPz!ϓiHmj<"+D6'NH8sBS8)xo콀P_PVb=B Pb5tSC Z4AH Xט7>07N#ˤy2dWӂ6@v 'g*k+X\G (N೵`izd!ڇsh{\0sEOha??w "WsՄ$>j<LX\ M,kHwW*;"Z߆p:ʝw('xqZfL-;|QpWa0?* e]E~s+]1 qCV:N7oyd �h[,wyB.yI1<}Gv߼Yt+fJXlr==8K˿%i[C/&Tر\'\JDn?:r0/jήE޸i=;0If0a9 o'+b ?Y1fr=զh\CJ(ώ7JgRn]o3?N~U.'͗% {56[ti)$en5cG$i4A); }L6|3K˸J5p @l^R*)&*$ŤrL65hX?0CM}| b u0= eLzDR k&' (҂Ud? `M;:h4l/ڸ" Eȗ }2y7R,Ջ^ƒM)4~ ",ǷmZb' {evc5.$zZhlqD(*k`Yh*Ft;w#ulhn QG zZ>X q~uhAKuMk/4SL-nM9W+cZK~6gK(87_,RyojfГʮWA<uS1 VDܰ"u `QӦy`P3?KwM �)B$i{e *߾$q3ū ؓ%=8b?u� 4~-=g ؇UNEV "fJvv SUGq!D~Ⱥ!n7~_ q]N׏ػIYTzHѓ@PO*K)Uw嵤#Kg'[eܽyȾƓxP&;?n>.)h$L-U*uB;t$ hټ |Yߒ>F$1fOV[ۥ:vDl!cDMxrKHe{@V;VxQ棧FCB{,UYU§o8`|ӗcEPة<ۭslrPޗD3u:E ]/ro>I�NuE$_* &flY>Nfx(sY_K3%CIap7 qw͈:FKa=a_ͯZf`ZN0M$7 U;sɗO[[=Y ~|5BBm)~i+='~癐T4<+#aUdsѥqYt bd~.ιԛ:  iunp|PYkwDdZp ~ݕބ1b[Wig0%΂X0\M1Y|QOE45-6ݔ0G:쌠L0H=(]l8I=} B<-ĕOP[mfF:ד<r{S yW* t P~`^m:D%ea(@3xPEɺRM#Qb9 $CfwPipho"a(yz:Ƃn6l˅iҚM%NIG>`i ZbQփ oǼF)xݽn>g<י-9.JEŪo ̤LI9gc^!|ߓ/~ j6�ZI9I.x'ʹͳ! +P*_Ñ"q3Wy_:nN􊛰贈=.9,$L~[[el2˘l!,='CnVv!("eϕkYg2k)fhe ہ9us[D1hSt8yA ߲o&HKQ}O(ZМGgqKg"Ix$,FftDQ(0rAztC]X}'6j0"!t%~RHfDr&qULCɼpJ1F~C4jAr]2ue[Mo?|gk׽#|3D3 G.#~k*Qf^ax\-&,Ka{,dv8ՉO!<'zW8?JB$̾0HU>Ss~,ag*%{h&yZC!vgStO( spuٶOR [=D_w ǘ~WSݵ' ^X7K}a§-Ǎ4b{SA !9UsKv [R.VN0-'&Km! ی[/�tӅLs^#_mܯ)O^{AQ;oaeW yiηzW QFɹEYHxbw8V ` vg #M|=1BU©O&dn*nzNʚ*7_Y㱅  . (1 @~_L|]S3Ҭ4FԞ,KR}R5~\Z}[P[C  !y&/C09=ҢuG6X*1S9( 7WU܈}_SBgRsS*x1}0(`;n~F+&jbޭ*ҝpm[X<;ǚna|\gئ̣2#<2zZ_%!k. :E|"JY}֖d;$|9pvkiYp~Ě.-4xK*{$\24;r}u!9FeǿY1<=?dRDWnpj%Dag#Q܇d}oo@/?f9Eqn<BHe!&;a\(3DRFj(Aw7Lo2aG"cruf/ɇ.&.2ߩE3(Qa-ѩ) E;Na<轡:)Gu^`% Y<Rpȓm$tif߅S_7:dyShY0j;F#U:w<A gc Dn%զm(�>|$Y$N[øJl#A ޚQ u¼_ހ_qyѢ?%Jcբ`8 C9OaoKĦJGNβwmlN+܆{eBQ8MRMCڵZ`2E9O^#Ye˟kᘢXBA>䎢sboLnwѴsZmX~тk v- N]Zy9f\ˋtOzqn \U5n@vpWSG 4rR9ZJm\jӷil�{w07pЯ/ O Ę$DX(C6zvvќI8CzP\}"W r ^5S^Q9Ч �^;~T!DX!f)f+A\fc}UO:J0Flk;F12o4~FA 9H5;)a[ F eO`qs2 <ѵ�Jz}CH+Qr U+?p7F8IwwxNw6~`V8ư;OE9l1i5=XD%8,NMz!К˂UW٩co5~f !e0b*2_M b(MK[xZY gT7z) :J{5VUb4؀4 X�ZD>tj&6,WG$[-.<|-ŹSEu'raeZ@Sxg %#=AJR1?5G Š^V^dY,`e* pF e&1(ȼ~t9XT[}b2X$ƃkS�،.0z)2#B.e> J!Xp'j) SZIg>}U6Ct$'Nn'9UB+jZ RqEക1?_<'nӓzd`s%d"ۖ׺uv-.}Ѵű<g!֣Y4JUf)"HJT&>h#Qʖ3;LȪM55EG\k ^W2Y@( B։jb-@9LO샵/1TtA(8C0S?5Y�6qzSfE^\YWod' hvhs±&nL"c2ϱhK}>ɇ2$`Le4nqP곒lf؅UÀCTkOڟlūhH# ;w"_H,K"Ŵ0+WwGO-, endstream endobj 807 0 obj << /Length 696 /Filter /FlateDecode >> stream xmTMo0Wx$ ! 8l[jWHL7IPV=M̼ su;Uٛ=w]yil;<[[j<=?׾+v`&ߴț<^*;~&Q>MS >_P{=s@dkx;`VY`s4JaQܡn.Uu9\Y6><ٴ.Z.4>Dӗ}~r:-d0VWk,8yLһʮӮђ[*mLr?q 5F8@=�@)&� 8�Rx uD\j2�H�V0CzL] bctI g$`htы0\F0s jd< I�6zg W qȐ+#k .bsrbmXK7ǵH7Gnb>&jؐu1VljOu$՟qWS/%1{\xB!K(hHTЖ枃Jρϯv=k2UKς_:~$/ ~E+7ˢ/ l(/} -+ZXukoԝE?ZKq endstream endobj 808 0 obj << /Length 739 /Filter /FlateDecode >> stream xmUMo0WxvHUdCmU^!1H#x�?gx]OTm$|͜s_Iss :L;<Sz==׾f`*_`ɫڟk3'iѴ}=M;7rfnj-eSӵOL<rmh;)^tl״uö.#]a`4êuA雝< SL_Moٙx`<X.Ymv96y4L UUWqS~~ |Ҳ\Khv7RKs|*Z -1 b[d08A  i$C#.CZ\wF|TT<\`Gc)y ,<$g v1a粳[ RHדL1>g~8 )ok A8 $`I\3`Af<Z]! xNky"7 _㓧q H`nḱRONH=CpB:# =%888QA~!*zƜАT?!~> tw8y*sύ }nFE>7*QύR>7G];~<6OIyktg>O:yұϓN|I/|yIg>O:y҅ϓ.}2 L<e띹_m;z}s=״#V{ǿ ^/P endstream endobj 809 0 obj << /Length 900 /Filter /FlateDecode >> stream xmUMo:W�5?$R. d9M eCkmCp;;w~>|3E_?O]5߶w]Occ]=~?}Oyh9%?۹׬B|Ɯ>);vw%g43>\ 6 EJ78 1{~`W(-;]%=xe_,b+-O;q\L}UI--=BKE1p[! Mߊyu>.N5K)Wb٬8i[_uʕMzQ)V(T�xޢjy!�Z�2�P="Zd0\ÃGR\).2*Шa!U,H`+j�.�5�Nα@VK-x%3%AYӀzΚ>kP#5m0Woþj.ZT$X�/)n)#Wo(oRZ $Kp4Z-b\1ܰJ P"GXQi/8k^Zq:Zs9dB )sL-7xJ`aɽ)f$1 dъcCZC<73JgznHȰYɚTa,_-O87}KԴܗLloK+gJ.GZyVc48Wt]:P~`rZq.n1] S/Pu7Ue:?&?!d&1yHn5)yғBx#1ޞ]Go׏M?X endstream endobj 810 0 obj << /Length 833 /Filter /FlateDecode >> stream xmUMo0Wx8T·~h[ ۍT~3<f}<M? 6w7W(k!O>r#_)9۞c$_{t]P܂~ݣP_(&w(R|vp#P)->g_B?q8SG AC۽[ia߿{2ZE_cf/1/{/4G+)bUUwkuTO4[@ 0@`%! #P� .w)ú�p%K�cJ�e Rͤ�(*1�:bDDR@ ȓ2UR*N)�KIΡԀ0CS,km:5Bͦ&[Y{Ł@꒩)NMvSpJs}irphS ᐙ2L9ΙV}yXi8'z Ԛxq1GyלNZ1fXt:s0>wpVR.խr)>1qҾKvHX1iS5rM yR6FBlH>]6b 5&5&0a'evb_dfQTtQ]zK/WБ^Zz&孯ӷrW.&_rUOz䢓n�9)C]!􁠧r7dE?_;~T?m endstream endobj 811 0 obj << /Length 700 /Filter /FlateDecode >> stream xmTn0+Jb'$8B 8l[jWHL$Q;o.Z ̼7/o~<GYm(PQs77EW=>:W{xPCWQb6;J^ǩv'-[~Gݾߣ#i6ڿRV_n84]֚̽e[sYͮi P[ L:?=v8|`4nh7u{QE sU5Y7{C]_?{B^QSu; 3jV՞d;&xD\20-0b# !ڇ\)&�q)% 1ON"ۂ%480`r�H%Dd#C �K .%�"l %RQ NLHI($ux-LJ@J!^H :ggM597F7FN|[{}&Ff*pdk_ΜN0VG9ʱwDK4X=CaCɁg2)4X(rb0/s4lƵ.b]ʌ[r<s!?f*{.z.I=mZoJ+9R Ϩx?Wr\io|M.T?n2 7rX endstream endobj 812 0 obj << /Length 700 /Filter /FlateDecode >> stream xmTn0CƆ@LE"jD;oƤjgy_xN{qV'wC&]\]]u>t\qxں7ŦmN7isƬ'k~G]?ߓ` 4;RV_n86]{̭֚u[sfߴ L:?v>4|`0nhWu}QE KU=5Yw߇l?N6jwwv Z/բ,ko{&PaffIq XMJ0Lfhr�dĥ�P<F:ASl PJ҈tƀ # Gs =2+ (@s5.W PL�KF1 LHI($ux-JBJ!^I :ggM597F7FN}Y{}&Ff.pdk_ ΜN0VG9ʱwDK4X=CaCɁg2)4X(rb0/s4lƵǮb]ˌ[r<s!?f*{.z.I=mZoJ+9R Ϩx?Wr\yo|M.T?nC_er endstream endobj 813 0 obj << /Length 701 /Filter /FlateDecode >> stream xmTn@Cx ^"#&W R ە7iSFyo.{a;M[ݱ;w}puUtjWowa読;|SltCɛz;nʽ4%<i$>57JN.n86]{̭֚u[ҏӫ(hߴ5g( L:?yv>ixgm7~д/"$(,v{F~{Tk#zv~Wa׾`R-r睉y?&xYF\20/0b# !ڇ\)&�q)% 1ϹN"ۂ%481`r�H%Dd#C �k Ю%�"l %RQ F'b=:S:,Rx( y]eѱԁ_[WS3+!Z af<T&ÈO ֳOkchAo MƱf)$P cusVCWY3h{Æ?,dRhP@`N+^i4،kY]  '\xB~f*{.z.I=mZoJ+9R Ϩx?Wz0Uw}\S}ף|(VecWt endstream endobj 814 0 obj << /Length 995 /Filter /FlateDecode >> stream xmVnH+Ap 6 bcW;lJ>S]WX`U쮮~pF7|XaW y;nn?=! oy?Sr4D= / $>i 5|4Pr %O~_RhPqYD$qEI]T'؟oٿN x o~&_4/͏y8$⃇ "Qdϑ/}'}x<B{JM~înz RwɶVaL yz^|5|u?v �%@ !P� vh#/�&%`�Pm(0YJp(s�9��HKV$ @Z1āBHEiᦓ4("ܲV�T飇.@E-]ݖpUtI>E�jypxr �z m#)u�:+@,B:6f{b\qeǂuN\슶̏R(ӞƐd7t-3>Y9ۈOI+ȕ״%>Fl)qԍtSTX8n9Ē+p9\/ڭ p)gdEKhe]NJXX.5 Z2XhX;^1G8%jI,sYg]Ò<idOT&v GWb2'm_fQԴ4Q1]".yosG% yUZlrW=/NNgi?. =u#{=bKF-Q-S^ݫcקAv@5ϹԣzR﵃6=+y39ګU*o}Xt<s>2⨫ybAOWOKN+QM?.<^+W.<\u>n(~t?\C endstream endobj 815 0 obj << /Length 699 /Filter /FlateDecode >> stream xmTn0CƆ@LE"j.RC~8iZ)Ayo7?nkNy$냛G׎ծU[7|SlfM[kwʽ5g x=i6;RV׵_n85]֚̽u[OsE͡i P{ LՑ @4=tb/yVvL MnݞArjwf4P׏ީFT]Nrî}sBZ2pmmR?\rs<, X#.KIɌCH'hjmJIQ09�da"2rG~\5hגQv]`n @v)(A'b}qHI($ux-JBJ!^I :ggM597F7FN}Y{}&Ff.pdk_ ΜN0VG9ʱwDK4X=CaCɁg2)4X(rb0/s4lƵǮb]ˌ[r<s!?f*{.z.I=mZoJ+9R Ϩx?Wr^yo|M뮗T?n2 %rg endstream endobj 816 0 obj << /Length 699 /Filter /FlateDecode >> stream xmTn0CƆ@LE"h.RC~8iZ)Ayo7?^$ŝPIs77EW]}==硫nTشxGɛz?{k۝=` 4vN߷u8NM>(s&`ywS0jzQshz+&TuS~Hxqq`P<+ OC톦}SWUn}@`T;P3qtj}w*5UWSܰo\ze \[3. 9ff ؤdF@!i @F\ ` H sn4ȶ` $(Ng �2R0zd9#Cb.k(@.0[Czr� aà8SuX$Q:\CAfpGR~m%^!N%$h&՚R #ƿp'XϾ>AI }3Nh25gNE'bkkؿs %|V !3?fc91ӊ9|u 6ZcWCab d1׮eF-9Ag깐3Z=I= 6-7p?)pegT<?}pq\< tS ķ�uKzToSr endstream endobj 817 0 obj << /Length 700 /Filter /FlateDecode >> stream xmTn0CƆ@LE"j.RC~8M])A̼7W?^$PIsWWEW]}~{SCWmݨMi7mv9I+ڴg{ҏÄ~F )P ǦkZn;@1zz5= 7m=x Fgu P}?i]X<;k C톦}UYoO} A`TS7~wpjmS!詺]]ꂅK(ew&97\=̒5⒁yAa>:M1ȈK,x΍t,@F*&" C,zdWXPv-hakH/]�d"btv"gg?|�2JB^G5kdwt,uVT Jb9;kBX!00a0bw3W M";\88̿9Earʱs ށ?c>+q p~PrL  hi˜c>:q-+01~k2#Ϡ3\OLqRυ>¹M \)s9O \Y!O>\\/Au*[�ӺkzT%C0t endstream endobj 818 0 obj << /Length 700 /Filter /FlateDecode >> stream xmTn0CƆ@LE"j.RC~8M])A̼7W?^$PIsWWEW]}~{SCWmݨMi7mv9I+ڴg{ҏÄ~F )P ǦkZn;@1zz5= 7m=x Fgu P}?i]X<;k C톦}UYoO} A`TS7~wpjmS!詺]]ꂅK(ew&97\=̒5⒁yAa>:M1ȈK,x΍t,@F*&" C,zdWXPv-hakH/]�d"btv"gg?|�2JB^G5kdwt,uVT Jb9;kBX!00a0bw3W M";\88̿9Earʱs ށ?c>+q p~PrL  hi˜c>:q-+01~k2#Ϡ3\OLqRυ>¹M \)s9O \Y!O>\\/Au*[�ӺkzT%C2t endstream endobj 568 0 obj << /Type /ObjStm /N 100 /First 943 /Length 6274 /Filter /FlateDecode >> stream x\koF_6~$QlqmZ$:Tfy!g8(vwECs3C؂0Z8}, `hV<<& ~P+'ƙBhQbZ &vP k efeP}D1EcBX p? H*<<+l (51z'c`9i $Ɂwic!\I&I<<IKO<p ē6U({K)Jȍ+IO ETRs\J e-Rޠ wʹ/(k"I!ZNZ̩%5)ͩ5~xm0 9eQ降rA3&ơBEFDġ5<`CxFQg"x2 RRYC:k(DPg&A#YRgO1 Gwh2+;BBg"(&q${k<q4%~#jN u܃IPHpf.heLb h_4$.?-ٕ`Fѓ٢B)6 cDpEA|IldK*Ht,hL,!,4K^Kʌ%L%,U*aS +H6hJD JX$Z�m-DJԦRz(<} E'5abYQAMk:]*NaLDvs_}U/6U]MzfxIdUNVK}š[NL~wg׌]oIIY޽[n7Ο*p3˳rQ5P6 ƅVcq9\\X IGVFVu5C9bt0 Ѕ-y:98up#m. Reqems*gcGD: ~$HmCF/j'[tqbmcA6Lm5Vj(%i02Z,`j) "]�]U[lNg֙,:EZH|i}w1]ߋw}wy&Qػ< {EaX(lȢaLe10dTBd6-qgc̙ wL"C OiHX(놾~i\awqnyL f|&N1%ڛqjb^2#Gw<4Gޓ9oVz%IT+(oGc9 K4]Ek{[v[o۱=A9Fzsׄ~>)\.I<4t<.Ǹ6:O(s,ߘ7u=}އfrv=8C"C ٥h,.:\2).da 5S6\h1 ~M{E~#F8p0޴W:lj+ȁӋ "d4Ec:LDVtͣ1 iUQY\QtI¤V!,#>!L\@ l$H `|[DNl`Z"uFi:Xg`uF:XG[댊-%;gΘe3txa;gΘNlϤ}1hҶ4iW )F0iOoҖQߤ12IbOF <Iw{#T9M({A&$3i 'eth, r2i , r+2i!U9L>@Nkrim9!`,3h&`OjDW"v tiRZĦ Fq#agRs7$)Kp(q/{'$ˑƶߝq9ٹ;9 `FO`F#m-=EyF{ hwsm{M\ <7qF?~;R`(.9YxցJNo@tlҏ90GJNh"-<Uh&X eY8qteuLE-\uP2AQ|Emw&H/XEmBRmL/a.  ҙ鰬ò ˦3 (EeALsòIyemr찬M8.ڄi˕ :`kEvi6G SLduj u�$:PM@(&kP {ԁrmPdU6C(g)%ғ -;0lU6V Xމމ(wbNމ;1-&?&?&?&?&?؇Âma¶e@v'S.TLJ`|-B>a7FaT͟#VxQkZN/:_ÕɆ#Wwxy:3Mtzߛh7cs[H woc=g+GA{DuǺD:ꛝR+-Yz޲Ke^VܫWn~CuEq DwϚQc~0FwMltxA$ACM8{3p IxD%$jZ[,iAFmYwɒG־ Fު)*g b 08ק1Qot";c8ۆAI $*kA)`P ޷fcr{Y}ܭ7)@{tzǜ^6]-o r[MfG8ovt ٲi;xZ]Ln_-QIc;JI if,wՂFmϣzYl{ֻU8/'?}K<Ğbg寷ϒK󟾩*tO�ӧkxSbZl6Ge|z>}z+SM^dRf)qǐ9C?ϧ|~{=_<9.J@l8R>ӓ9G$=WJKs5)EyQ]yݓܑ_r_.Q`g{-3yGQE!,`}Y.ʷ`wY/W/Uy]ހMo_? =$GB?#Sjnᠦkn2͗bsyQy<Nis;?^_/vM{ś^~\*|~ON./WT*ޤ]<MC*;?誽� A֖OʧW?aߋ]0Ky K(m|W[ovg�w7% eߏfys|kBT9喤hmySnWv6e}]ޖ7bYZn}]+>'] 9&x[ԕPJ󞷙;Y_UӁ-;פrܮµvo2n,wAsWW@돟r}ut`cz/7XU^6׉ϛ AWXz!tfD(uMeca׫ֶWdKtWOg?f?؈ pؽ/g#ImXS&4}6aͽԦ KmJF\j15NQ.[l |p$cx%26gg~8)vg?JbF[moL=JѸH ><WiA7a`p(GF B}G3*s.4*m8Tkמ0ml!M5Y(DutQ5o>g0bmv|*L^]Z]WoK2P{41{M*Sqg><BH?~t@Pν#`_" GP.w'rHRft7c *'ߟ؃;!Ělj'nnH;q ߕ )s!|Fj(%/vlS'ϱ=5ˬTEW Ejew!ܟϡ!A+Eqg#*;I{$#X_n-׷UOP0uSV@t}kܛϑ{Ιoo M+xEaټ/Ds^p>d T}-j[ôs5_ޮڲkM;?jM86ο[JpII!y+櫟>]o[S/Z'K/"W;ڔO"/ofNCőg?-yx'~G6ӘPT#5HF#ǏDy`iErb&elFjT1Oe6)EB%Pfz?Œu_qN\fD:AӨ1jT2Gɵ4IJeӨVITd4# \jD2X8#RIXlȥjz>ik,#nV^F?žH@ZȚ'Ysux\c$jΒKH cS4Fl7ɏ!:E'gvt󐝾&lvȽny}t\V!"!Q'g?Z祛ϥh)zWY3!&ҳ`sjM+W-c o:MN+[д&~gV^͸:ofF fhmOVsTܶ{m+Yϸ~D3uZ3jigh,;JQ'rV̡/|xL?ѕUIjj隉i m) 62M Tp2\ I5w`^גA1!{ԏe|Z;>ԎU|$yᴞ΀Al5t3nSl])1sQk5VJZA.c|6Vy-u|lel827GBTsuZXU$**2WEWټxXV=%7aN)jLrhUTuܓJ5GW k2fi`+[l&H/<#0s위'HMj[ V 8.k(bTEZ%v1n{ԏc1^) 'L;8L; 4b1γV_vT̕eJ[{ؽs|2(ZQ)U9fXDڼY0OQyࠕ/Zo,:^{PmNde:#3I8)@ebrnPp"ɜlͦL-Z7]7!z>GJsgbG>#@٬O.L]sG$T 9M,DLr )3o)|le FJRN8=ʸs94—ry{Y9?#d1>` 3":Uuo+Zr̖EglKrŅas.c|ѣ9ָPAL/kᇰg"Ou|^9P!T+ogdBJ *vX�g{e#M\??L i @@|q~Iy)235[:ۣiѮ7%sZS#54z}(<=Ҫr]wGܫ 9' 󘭛 5\鲏^t*s*.!4yZoA&&=Daכs%= 0p "!j,(u0%a/sAXgz>'SE޲<qaZ"<J$mS%v} 8WVҔzHjNE!zRpv>g"D0> 9rXI뇕XH7t:$Yu8u0GAĜ̩6 Ɋd㚷o3vȠݰ1P ( 3{!՘p>W>of!h"hM(hSjLVe}ZczPQntQJ(6Qfc G7Qh?bKqHr endstream endobj 857 0 obj << /Producer (pdfTeX-1.40.25) /Author(\376\377\000S\000e\000b\000a\000s\000t\000i\000a\000n\000\040\000G\000u\000t\000s\000c\000h\000e\000\040\000;\000\040\000M\000a\000x\000\040\000H\000o\000r\000n)/Title(\376\377\000A\000u\000t\000o\000D\000o\000c)/Subject()/Creator(\376\377\000L\000a\000T\000e\000X\000\040\000w\000i\000t\000h\000\040\000h\000y\000p\000e\000r\000r\000e\000f\000\040\000p\000a\000c\000k\000a\000g\000e\000\040\000/\000\040\000G\000A\000P\000D\000o\000c)/Keywords() /CreationDate (D:19700101000000Z) /ModDate (D:19700101000000Z) /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Debian) kpathsea version 6.3.5) >> endobj 845 0 obj << /Type /ObjStm /N 12 /First 100 /Length 506 /Filter /FlateDecode >> stream xڕUn0 +t\%h(4e]7l0`m@{ߏC0#e5x�` d"se( "gs c_P!7G(7>/w}s?nX73`e<<;32L=o}n#3Qz٦O. @@! ERJU',f6Hܙb(7v@i YH 2HLݲ$0gN ) jW!?"5F4l=0gܦd9SNqըJ`拻u[Ksf<@:QuL-ɶ鞹=WzU7y2*FUo_~׃)aio.͟}cʋzǢ;9nP_^v'+N+ $G\wKn3̳. endstream endobj 858 0 obj << /Type /XRef /Index [0 859] /Size 859 /W [1 3 1] /Root 856 0 R /Info 857 0 R /ID [<E10B782967262C9303EB338BD3EEA8FF> <E10B782967262C9303EB338BD3EEA8FF>] /Length 2246 /Filter /FlateDecode >> stream x%ytU@B@001L SJk-Z]] VjUgQ (" -Z(u>y=>{ϾI$9'.!akOxXIm&[)H1 A 3 jfA6aԦ2l 9j3l6aHm ;AgM7I @.rjAWjM` 򩍠6aRIatVOmbAX%ГZ#1 {A)F3 }-6a_(S-dQeSHm$PNZ `0 0 *]t H:V 6*&a5|jgҟ-(ҙ-{pl XˬdbAYa4A3̆90Ƹ$o.X,,a a,%Ka.. XEg8,Ҽy"{ 0o8Ń9KLgt!fmV#1%Ђn&:v!18mnGXc!و+dۥ =lHrb,|v.Roav`E")#`KVcm+mQ>ıdh%['8d(Nd.D9HdG"i)H"is!RHE"T$qK~k"Hp@"AmV\PYُAK|hv�,Ȇ=*%w#:]ֿ<UZW�}%[>cmq+[J^`WpR`(sj;�AU0%d.Caة*aTdoRCU /a e6RR0 \rN0&$ S`*̀0%G63a4\Xy<X�6%KJhuv nfpKN-]aι<9}@6!@Cs].IS "@ ~~ |e싊z~D 0h|XjƏ싅l *lyӁN:tӡhw a:@C49MFB tp`\QΊ-Ǔvs(M>kE_jD%bODQT"_,*~$s\#8UQsfE ڧ8S:v{b;b&1bHQF/bR|S=Ō1AtmY4ss& (&[2CKвD+`9']X3X^oTXטקoLsn+6,.zT|琸XO|q wQ?̷VĥNp5k_Hq]5Ozzqa O M-[7NwOww"ilp?߽Mb3J<NlH<xx?̃}q艄4?SRȄ6=>LG<+'SoEi v;po݄YzsŞ qb /4o?a=G7/Gy/"^onw#q4S!]c kop7$o}&ḮN|S%Nn&q&>` N1X>_|B>+>ϟ!O3t0B6_Jbvd@ٟW}<{ y̧64H+3z}=N ێ9堧?{c8 ̽T.}WNi W_LdW'JJS)*9L-X_~f>/O3bx[13WvUYPw2Z~i1S}5Oj'�7=K1YY|:uO%fhi3=ߠF֔om_c3t\syo}l[ݜfwRҟqm:+Ͷ?l[ݝж?ympWVK]~=]j&R;ozG+Hjfq@]HT@RtoZRGԛ_M ~aef]a e Z? @ m1qi}R< !2 dA6uscZIv endstream endobj startxref 263134 %%EOF ��������������������������������������������������������������������������������������������AutoDoc-2025.10.16/doc/_AutoDocMainFile.xml���������������������������������������������������������0000644�0001751�0001751�00000000267�15074117054�017456� 0����������������������������������������������������������������������������������������������������ustar �runner��������������������������runner�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!-- This is an automatically generated file. --> <#Include SYSTEM "_Chapter_AutoDoc_worksheets.xml"> <#Include SYSTEM "_Chapter_AutoDoc.xml"> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������AutoDoc-2025.10.16/doc/chapInd.html�����������������������������������������������������������������0000644�0001751�0001751�00000016550�15074117054�016070� 0����������������������������������������������������������������������������������������������������ustar �runner��������������������������runner�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>GAP (AutoDoc) - Index
Goto Chapter: Top 1 2 3 4 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter] 

Index

@Arguments args 2.1-3
@BeginChunk name 2.2-14
@BeginCode name 2.2-15
@BeginExample 2.2-9
@BeginExampleSession 2.2-10
@BeginGroup 2.2-4
@BeginLatexOnly 2.2-16
@BeginLog 2.2-11
@BeginLogSession 2.2-12
@BeginNotLatex 2.2-17
@Chapter 2.2-1
@ChapterInfo 2.1-8
@ChapterLabel 2.2-1
@ChapterTitle 2.2-1
@Description descr 2.1-1
@DoNotReadRestOfFile 2.2-13
@EndChunk 2.2-14
@InsertChunk name 2.2-14
@EndCode 2.2-15
@EndExample 2.2-9
@EndExampleSession 2.2-10
@EndGroup 2.2-5
@EndLatexOnly 2.2-16
@EndLog 2.2-11
@EndLogSession 2.2-12
@EndNotLatex 2.2-17
@Group grpname 2.1-4
@GroupTitle 2.2-6
@InsertCode name 2.2-15
@Label label 2.1-5
@LatexOnly text 2.2-16
@Level 2.2-7
@NotLatex text 2.2-17
@ResetLevel 2.2-8
@Returns ret_val 2.1-2
@Section 2.2-2
@SectionLabel 2.2-2
@SectionTitle 2.2-2
@Subsection 2.2-3
@SubsectionLabel 2.2-3
@SubsectionTitle 2.2-3
1.3-3 1.3-3
AProperty, for IsObject 2.1-7
    testlabel 2.1-6
AutoDoc 4.1-1
AutoDocWorksheet 3.1-1
1.3-3 1.3-3 1.3-3
FirstOperation, for IsInt 2.5-1
InfoAutoDoc 4.1-2
1.3-3
makedoc.g 1.1
1.3-3
SecondOperation, for IsInt, IsGroup 2.5-1
ThirdOperation, for IsGroup, IsInt 2.5-1

 [Top of Book]  [Contents]   [Previous Chapter] 
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/manual.js0000644000175100017510000001011315074117054015434 0ustar runnerrunner/* manual.js Frank Lübeck */ /* This file contains a few javascript functions which allow to switch between display styles for GAPDoc HTML manuals. If javascript is switched off in a browser or this file in not available in a manual directory, this is no problem. Users just cannot switch between several styles and don't see the corresponding button. A style with name mystyle can be added by providing two files (or only one of them). mystyle.js: Additional javascript code for the style, it is read in the HTML pages after this current file. The additional code may adjust the preprocessing function jscontent() with is called onload of a file. This is done by appending functions to jscontentfuncs (jscontentfuncs.push(newfunc);). Make sure, that your style is still usable without javascript. mystyle.css: CSS configuration, read after manual.css (so it can just reconfigure a few details, or overwrite everything). Then adjust chooser.html such that users can switch on and off mystyle. A user can change the preferred style permanently by using the [Style] link and choosing one. Or one can append '?GAPDocStyle=mystyle' to the URL when loading any file of the manual (so the style can be configured in the GAP user preferences). */ /* generic helper function */ function deleteCookie(nam) { document.cookie = nam+"=;Path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT"; } /* read a value from a "nam1=val1;nam2=val2;..." string (e.g., the search part of an URL or a cookie */ function valueString(str,nam) { var cs = str.split(";"); for (var i=0; i < cs.length; i++) { var pos = cs[i].search(nam+"="); if (pos > -1) { pos = cs[i].indexOf("="); return cs[i].slice(pos+1); } } return 0; } /* when a non-default style is chosen via URL or a cookie, then the cookie is reset and the styles .js and .css files are read */ function overwriteStyle() { /* style in URL? */ var style = valueString(window.location.search, "GAPDocStyle"); /* otherwise check cookie */ if (style == 0) style = valueString(document.cookie, "GAPDocStyle"); if (style == 0) return; if (style == "default") deleteCookie("GAPDocStyle"); else { /* ok, we set the cookie for path "/" */ var path = "/"; /* or better like this ??? var here = window.location.pathname.split("/"); for (var i=0; i+3 < here.length; i++) path = path+"/"+here[i]; */ document.cookie = "GAPDocStyle="+style+";Path="+path; /* split into names of style files */ var stlist = style.split(","); /* read style's css and js files */ for (var i=0; i < stlist.length; i++) { document.writeln(''); document.writeln(''); } } } /* this adds a "[Style]" link next to the MathJax switcher */ function addStyleLink() { var line = document.getElementById("mathjaxlink"); var el = document.createElement("a"); var oncl = document.createAttribute("href"); var back = window.location.protocol+"//" if (window.location.protocol == "http:" || window.location.protocol == "https:") { back = back+window.location.host; if (window.location.port != "") { back = back+":"+window.location.port; } } back = back+window.location.pathname; oncl.nodeValue = "chooser.html?BACK="+back; el.setAttributeNode(oncl); var cont = document.createTextNode(" [Style]"); el.appendChild(cont); line.appendChild(el); } var jscontentfuncs = new Array(); jscontentfuncs.push(addStyleLink); /* the default jscontent() only adds the [Style] link to the page */ function jscontent () { for (var i=0; i < jscontentfuncs.length; i++) jscontentfuncs[i](); } AutoDoc-2025.10.16/doc/manual.css0000644000175100017510000001575415074117054015630 0ustar runnerrunner/* manual.css Frank Lübeck */ /* This is the default CSS style sheet for GAPDoc HTML manuals. */ /* basic settings, fonts, sizes, colors, ... */ body { position: relative; background: #ffffff; color: #000000; width: 70%; margin: 0pt; padding: 15pt; font-family: Helvetica,Verdana,Arial,sans-serif; text-align: justify; } /* no side toc on title page, bib and index */ body.chap0 { width: 95%; } body.chapBib { width: 95%; } body.chapInd { width: 95%; } h1 { font-size: 200%; } h2 { font-size: 160%; } h3 { font-size: 160%; } h4 { font-size: 130%; } h5 { font-size: 100%; } p.foot { font-size: 60%; font-style: normal; } a:link { color: #00008e; text-decoration: none; } a:visited { color: #00008e; text-decoration: none; } a:active { color: #000000; text-decoration: none; } a:hover { background: #eeeeee; } pre { font-family: "Courier New",Courier,monospace; font-size: 100%; color:#111111; } tt,code { font-family: "Courier New",Courier,monospace; font-size: 110%; color: #000000; } var { } /* general alignment classes */ .pcenter { text-align: center; } .pleft { text-align: left; } .pright { text-align: right; } /* layout for the definitions of functions, variables, ... */ div.func { background: #e0e0e0; margin: 0pt 0pt; } /* general and special table settings */ table { border-collapse: collapse; margin-left: auto; margin-right: auto; } td, th { border-style: none; } table.func { padding: 0pt 1ex; margin-left: 1ex; margin-right: 1ex; background: transparent; /* line-height: 1.1; */ width: 100%; } table.func td.tdright { padding-right: 2ex; } /* Example elements (for old converted manuals, now in div+pre */ table.example { background: #efefef; border-style: none; border-width: 0pt; padding: 0px; width: 100% } table.example td { border-style: none; border-width: 0pt; padding: 0ex 1ex; } /* becomes ... */ div.example { background: #efefef; padding: 0ex 1ex; /* overflow-x: auto; */ overflow: auto; } /* Links to chapters in all files at top and bottom. */ /* If there are too many chapters then use 'display: none' here. */ div.chlinktop { background: #dddddd; border-style: solid; border-width: thin; margin: 2px; text-align: center; } div.chlinktop a { margin: 3px; } div.chlinktop a:hover { background: #ffffff; } div.chlinkbot { background: #dddddd; border-style: solid; border-width: thin; margin: 2px; text-align: center; /* width: 100%; */ } div.chlinkbot a { margin: 3px; } span.chlink1 { } /* and this is for the "Top", "Prev", "Next" links */ div.chlinkprevnexttop { background: #dddddd; border-style: solid; border-width: thin; text-align: center; margin: 2px; } div.chlinkprevnexttop a:hover { background: #ffffff; } div.chlinkprevnextbot { background: #dddddd; border-style: solid; border-width: thin; text-align: center; margin: 2px; } div.chlinkprevnextbot a:hover { background: #ffffff; } /* table of contents, initially don't display subsections */ div.ContSSBlock { display: none; } div.ContSSBlock br { display: none; } /* format in separate lines */ span.tocline { display: block; width: 100%; } div.ContSSBlock a { display: block; } /* this is for the main table of contents */ div.ContChap { } div.ContChap div.ContSect:hover div.ContSSBlock { display: block; position: absolute; background: #eeeeee; border-style: solid; border-width: 1px 4px 4px 1px; border-color: #666666; padding-left: 0.5ex; color: #000000; left: 20%; width: 40%; z-index: 10000; } div.ContSSBlock a:hover { background: #ffffff; } /* and here for the side menu of contents in the chapter files */ div.ChapSects { } div.ChapSects a:hover { background: #eeeeee; } div.ChapSects a:hover { display: block; width: 100%; background: #eeeeee; color: #000000; } div.ChapSects div.ContSect:hover div.ContSSBlock { display: block; position: fixed; background: #eeeeee; border-style: solid; border-width: 1px 2px 2px 1px; border-color: #666666; padding-left: 0ex; padding-right: 0.5ex; color: #000000; left: 54%; width: 25%; z-index: 10000; } div.ChapSects div.ContSect:hover div.ContSSBlock a { display: block; margin-left: 3px; } div.ChapSects div.ContSect:hover div.ContSSBlock a:hover { display: block; background: #ffffff; } div.ContSect { text-align: left; margin-left: 1em; } div.ChapSects { position: fixed; left: 75%; font-size: 90%; overflow: auto; top: 10px; bottom: 0px; } /* Table elements */ table.GAPDocTable { border-collapse: collapse; border-style: none; border-color: black; } table.GAPDocTable td, table.GAPDocTable th { padding: 3pt; border-width: thin; border-style: solid; border-color: #555555; } caption.GAPDocTable { caption-side: bottom; width: 70%; margin-top: 1em; margin-left: auto; margin-right: auto; } td.tdleft { text-align: left; } table.GAPDocTablenoborder { border-collapse: collapse; border-style: none; border-color: black; } table.GAPDocTablenoborder td, table.GAPDocTable th { padding: 3pt; border-width: 0pt; border-style: solid; border-color: #555555; } caption.GAPDocTablenoborder { caption-side: bottom; width: 70%; margin-top: 1em; margin-left: auto; margin-right: auto; } td.tdleft { text-align: left; } td.tdright { text-align: right; } td.tdcenter { text-align: center; } /* Colors and fonts can be overwritten for some types of elements. */ /* Verb elements */ pre.normal { color: #000000; } /* Func-like elements and Ref to Func-like */ code.func { color: #000000; } /* K elements */ code.keyw { color: #770000; } /* F elements */ code.file { color: #8e4510; } /* C elements */ code.code { } /* Item elements */ code.i { } /* Button elements */ strong.button { } /* Headings */ span.Heading { } /* Arg elements */ var.Arg { color: #006600; } /* Example elements, is in tables, see above */ div.Example { } /* Package elements */ strong.pkg { } /* URL-like elements */ span.URL { } /* Mark elements */ strong.Mark { } /* Ref elements */ b.Ref { } span.Ref { } /* this contains the contents page */ div.contents { } /* this contains the index page */ div.index { } /* ignore some text for non-css layout */ span.nocss { display: none; } /* colors for ColorPrompt like examples */ span.GAPprompt { color: #000097; font-weight: normal; } span.GAPbrkprompt { color: #970000; font-weight: normal; } span.GAPinput { color: #970000; } /* Bib entries */ p.BibEntry { } span.BibKey { color: #005522; } span.BibKeyLink { } b.BibAuthor { } i.BibTitle { } i.BibBookTitle { } span.BibEditor { } span.BibJournal { } span.BibType { } span.BibPublisher { } span.BibSchool { } span.BibEdition { } span.BibVolume { } span.BibSeries { } span.BibNumber { } span.BibPages { } span.BibOrganization { } span.BibAddress { } span.BibYear { } span.BibPublisher { } span.BibNote { } span.BibHowpublished { } AutoDoc-2025.10.16/doc/chap2.txt0000644000175100017510000007153615074117054015377 0ustar runnerrunner 2 AutoDoc documentation comments You can document declarations of global functions and variables, operations, attributes etc. by inserting AutoDoc comments into your sources before these declaration. An AutoDoc comment always starts with #!. This is also the smallest possible AutoDoc command. If you want your declaration documented, just write #! at the line before the documentation. For example:  #! DeclareOperation( "AnOperation",  [ IsList ] );  This will produce a manual entry for the operation AnOperation. Inside of AutoDoc comments, AutoDoc commands starting with @ can be used to control the output AutoDoc produces. 2.1 Documenting declarations In the bare form above, the manual entry for AnOperation will not contain much more than the name of the operation. In order to change this, there are several commands you can put into the AutoDoc comment before the declaration. Currently, the following commands are provided: 2.1-1 @Description descr Adds the text in the following lines of the AutoDoc to the description of the declaration in the manual. Lines are until the next AutoDoc command or until the declaration is reached. 2.1-2 @Returns ret_val The string ret_val is added to the documentation, with the text Returns:  put in front of it. This should usually give a brief hint about the type or meaning of the value returned by the documented function. 2.1-3 @Arguments args The string args contains a description of the arguments the function expects, including optional parts, which are denoted by square brackets. The argument names can be separated by whitespace, commas or square brackets for the optional arguments, like grp[, elm] or xx[y[z] ]. If GAP options are used, this can be followed by a colon : and one or more assignments, like n[, r]: tries := 100. 2.1-4 @Group grpname Adds the following method to a group with the given name. See section 2.5 for more information about groups. 2.1-5 @Label label Adds label to the function as label. If this is not specified, then for declarations that involve a list of input filters (as is the case for DeclareOperation, DeclareAttribute, etc.), a default label is generated from this filter list.  #! @Label testlabel DeclareProperty( "AProperty",  IsObject );  leads to this: 2.1-6 AProperty AProperty( arg )  property Returns: true or false while  #! DeclareProperty( "AProperty",  IsObject );  leads to this: 2.1-7 AProperty AProperty( arg )  property Returns: true or false 2.1-8 @ChapterInfo chapter, section Adds the entry to the given chapter and section. Here, chapter and section are the respective titles. As an example, a full AutoDoc comment with all options could look like this:  #! @Description #! Computes the list of lists of degrees of ordinary characters #! associated to the $p$-blocks of the group $G$ #! with $p$-modular character table modtbl #! and underlying ordinary character table `ordtbl`. #! @Returns a list #! @Arguments modtbl #! @Group CharacterDegreesOfBlocks #! @Label chardegblocks #! @ChapterInfo Blocks, Attributes DeclareAttribute( "CharacterDegreesOfBlocks",  IsBrauerTable );  2.2 Other documentation comments There are also some commands which can be used in AutoDoc comments that are not associated to any declaration. This is useful for additional text in your documentation, examples, mathematical chapters, etc.. 2.2-1 @Chapter name Sets the active chapter, all subsequent functions which do not have an explicit chapter declared in their AutoDoc comment via @ChapterInfo will be added to this chapter. Also all text comments, i.e. lines that begin with #! without a command, and which do not follow after @Description, will be added to the chapter as regular text. Additionally, the chapters label will be set to Chapter_name. Example:  #! @Chapter My chapter #! This is my chapter. #! I document my stuff in it.  The @ChapterLabel label command can be used to set the label of the chapter to Chapter_label instead of Chapter_name. Additionally, the chapter will be stored as _Chapter_label.xml. The @ChapterTitle title command can be used to set a heading for the chapter that is different from name. Note that the title does not affect the label. If you use all three commands, i.e.,  #! @Chapter name #! @ChapterLabel label #! @ChapterTitle title  title is used for the headline, label for cross-referencing, and name for setting the same chapter as active chapter again. 2.2-2 @Section name Sets an active section like @Chapter sets an active chapter. The section automatically ends with the next @Section or @Chapter command.  #! @Section My first manual section #! In this section I am going to document my first method.  The @SectionLabel label command can be used to set the label of the section to Section_label instead of Chapter_chaptername_Section_name. The @SectionTitle title command can be used to set a heading for the section that is different from name. 2.2-3 @Subsection name Sets an active subsection like @Section sets an active section. The subsection automatically ends with the next @Subsection, @Section or @Chapter command. It also ends with the next documented function. Indeed, internally each function manpage is treated like a subsection.  #! @Subsection My first manual subsection #! In this subsection I am going to document my first example.  The @SubsectionLabel label command can be used to set the label of the subsection to Subsection_label instead of Chapter_chaptername_Section_sectionname_Subsection_name. The @SubsectionTitle title command can be used to set a heading for the subsection that is different from name. 2.2-4 @BeginGroup [grpname] Starts a group. All following documented declarations without an explicit @Group command are grouped together in the same group with the given name. If no name is given, then a new nameless group is generated. The effect of this command is ended when an @EndGroup command is reached. See section 2.5 for more information about groups. 2.2-5 @EndGroup Ends the current group.  #! @BeginGroup MyGroup #! DeclareAttribute( "GroupedAttribute",  IsList );  DeclareOperation( "NonGroupedOperation",  [ IsObject ] );  #! DeclareOperation( "GroupedOperation",  [ IsList, IsRubbish ] ); #! @EndGroup  2.2-6 @GroupTitle title Sets the subsection heading for the current group to title. In the absence of any @GroupTitle command, the heading will be the name of the first entry in the group. See 2.5 for more information. 2.2-7 @Level lvl Sets the current level of the documentation. All items created after this, chapters, sections, and items, are given the level lvl, until the @ResetLevel command resets the level to 0 or another level is set. See section 2.6 for more information about levels. 2.2-8 @ResetLevel Resets the current level to 0. 2.2-9 @BeginExample and @EndExample @BeginExample marks the start of an example to be put into the manual. It differs from GAPDoc's  (see 'GAPDoc: Log'), in that it expects actual code (not in a comment) interspersed with comments, to allow for examples files that can be both executed by GAP, and parsed by AutoDoc. To achieve this, GAP commands are not preceded by a comment, while output has to be preceded by an AutoDoc comment. The gap> prompt for the display in the manual is added by AutoDoc. @EndExample ends the example block. To illustrate this command, consider this input:  #! @BeginExample S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) Order(S5); #! 120 #! @EndExample  This results in the following output:  Example  gap> S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Order(S5); 120  The AutoDoc command @Example is an alias of @BeginExample. 2.2-10 @BeginExampleSession and @EndExampleSession @BeginExampleSession marks the start of an example to be put into the manual, while @EndExampleSession ends the example block. It is the direct analog of GAPDoc's  (see 'GAPDoc: Log'). To illustrate this command, consider this input:  #! @BeginExampleSession #! gap> S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) #! gap> Order(S5); #! 120 #! @EndExampleSession  This results in the following output:  Example  gap> S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Order(S5); 120  It inserts an example into the manual just as @Example would do, but all lines are commented and therefore not executed when the file is read. All lines that should be part of the example displayed in the manual have to start with an AutoDoc comment (#!). The comment will be removed, and, if the following character is a space, this space will also be removed. There is never more than one space removed. To ensure examples are correctly colored in the manual, there should be exactly one space between #! and the gap> prompt. The AutoDoc command @ExampleSession is an alias of @BeginExampleSession. 2.2-11 @BeginLog and @EndLog Works just like the @BeginExample command, but the example will not be tested. See the GAPDoc manual for more information. The AutoDoc command @Log is an alias of @BeginLog. 2.2-12 @BeginLogSession and @EndLogSession Works just like the @BeginExampleSession command, but the example will not be tested if manual examples are run. It is the direct analog of GAPDoc's  (see 'GAPDoc: Log'). The AutoDoc command @LogSession is an alias of @BeginLogSession. 2.2-13 @DoNotReadRestOfFile Prevents the rest of the file from being read by the parser. Useful for unfinished or temporary files.  #! This will appear in the manual  #! @DoNotReadRestOfFile  #! This will not appear in the manual.  2.2-14 @BeginChunk name, @EndChunk, and @InsertChunk name Text inside a @BeginChunk / @EndChunk part will not be inserted into the final documentation directly. Instead, the text is stored in an internal buffer. That chunk of text can then later on be inserted in any other place by using the @InsertChunk name command. If you do not provide an @EndChunk, the chunk ends at the end of the file.  #! @BeginChunk MyChunk #! Hello, world. #! @EndChunk  #! @InsertChunk MyChunk ## The text "Hello, world." is inserted right before this.  You can use this to define an example like this in one file:  #! @BeginChunk Example_Symmetric_Group #! @BeginExample S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) Order(S5); #! 120 #! @EndExample #! @EndChunk  And then later, insert the example in a different file, like this:  #! @InsertChunk Example_Symmetric_Group  2.2-15 @BeginCode name, @EndCode, and @InsertCode name Inserts the text between @BeginCode and @EndCode verbatim at the point where @InsertCode is called. This is useful to insert code excerpts directly into the manual.  #! @BeginCode Increment i := i + 1; #! @EndCode  #! @InsertCode Increment ## Code is inserted here.  2.2-16 @LatexOnly text, @BeginLatexOnly, and @EndLatexOnly Code inserted between @BeginLatexOnly and @EndLatexOnly or after @LatexOnly is only inserted in the PDF version of the manual or worksheet. It can hold arbitrary LaTeX-commands.  #! @BeginLatexOnly #! \include{picture.tex} #! @EndLatexOnly  #! @LatexOnly \include{picture.tex}  2.2-17 @NotLatex text, @BeginNotLatex, and @EndNotLatex Code inserted between @BeginNotLatex and @EndNotLatex or after @NotLatex is inserted in the HTML and text versions of the manual or worksheet, but not in the PDF version.  #! @BeginNotLatex #! For further information see the PDF version of this manual. #! @EndNotLatex  #! @NotLatex For further information see the PDF version of this manual.  2.3 Title page commands The following commands can be used to add the corresponding parts to the title page of the document which generated by AutoDoc if scaffolding is enabled.  @Title  @Subtitle  @Version  @TitleComment  @Author  @Date  @Address  @Abstract  @Copyright  @Acknowledgements  @Colophon Those add the following lines at the corresponding point of the title page. Please note that many of those things can be (better) extracted from the PackageInfo.g. In case you set some of those, the extracted or in scaffold defined items will be overwritten. While this is not very useful for documenting packages, they are necessary for worksheets created with AutoDocWorksheet (3.1-1), since worksheets do not have a PackageInfo.g file from which this information could be extracted. 2.4 Plain text files Files that have the suffix .autodoc and are listed in the autodoc.files option of AutoDoc (4.1-1), resp. are contained in one of the directories listed in autodoc.scan_dirs, are treated as AutoDoc plain text files. These work exactly like AutoDoc comments, except that lines do not need to (and in fact, should not) start with #!. 2.5 Grouping In GAPDoc, it is possible to make groups of manual items, i.e., when documenting a function, operation, etc., it is possible to group them into suitable chunks. This can be particularly useful if there are several definitions of an operation with several different argument types, all doing more or less the same to the arguments. Then their manual items can be grouped, sharing the same description and return type information. You can give a heading to the group in the manual with the @GroupTitle command; if that is not supplied, then the heading of the first manual item in the group will be used as the heading. Note that group names are globally unique throughout the whole manual. That is, groups with the same name are in fact merged into a single group, even if they were declared in different source files. Thus you can have multiple @BeginGroup / @EndGroup pairs using the same group name, in different places, and these all will refer to the same group. Moreover, this means that you can add items to a group via the @Group command in the AutoDoc comment of an arbitrary declaration, at any time. The following code  #! @BeginGroup Group1 #! @GroupTitle A family of operations  #! @Description #! First sentence. DeclareOperation( "FirstOperation", [ IsInt ] );  #! @Description #! Second sentence. DeclareOperation( "SecondOperation", [ IsInt, IsGroup ] );  #! @EndGroup  ## .. Stuff ..  #! @Description #! Third sentence. #! @Group Group1 KeyDependentOperation( "ThirdOperation", IsGroup, IsInt, "prime );  produces the following: 2.5-1 A family of operations FirstOperation( arg )  operation SecondOperation( arg1, arg2 )  operation ThirdOperation( arg1, arg2 )  operation First sentence. Second sentence. Third sentence. 2.6 Level Levels can be set to not write certain parts in the manual by default. Every entry has by default the level 0. The command @Level can be used to set the level of the following part to a higher level, for example 1, and prevent it from being printed to the manual by default. However, if one sets the level to a higher value in the autodoc option of AutoDoc, the parts will be included in the manual at the specific place.  #! This text will be printed to the manual. #! @Level 1 #! This text will be printed to the manual if created with level 1 or higher. #! @Level 2 #! This text will be printed to the manual if created with level 2 or higher. #! @ResetLevel #! This text will be printed to the manual.  2.7 Markdown-like formatting of text in AutoDoc AutoDoc has some convenient ways to insert special format into text, like math formulas and lists. The syntax for them are inspired by Markdown and LaTeX, but do not follow them strictly. Neither are all features of the Markdown language supported. The following subsections describe what is possible. 2.7-1 Lists One can create lists of items by beginning a new line with *, +, -, followed by one space. The first item starts the list. When items are longer than one line, the following lines have to be indented by at least two spaces. The list ends when a line which does not start a new item is not indented by two spaces. Of course lists can be nested. Here is an example:  #! The list starts in the next line #! * item 1 #! * item 2 #! which is a bit longer #! * and also contains a nested list #! * with two items #! * item 3 of the outer list #! This does not belong to the list anymore.  This is the output: The list starts in the next line  item 1  item 2 which is a bit longer  and also contains a nested list  with two items  item 3 of the outer list This does not belong to the list anymore. The *, -, and + are fully interchangeable and can even be used mixed, but this is not recommended. 2.7-2 Math modes One can start an inline formula with a $, and also end it with $, just like in LaTeX. This will translate into GAPDocs inline math environment. For display mode one can use $$, also like LaTeX.  #! This is an inline formula: $1+1 = 2$. #! This is a display formula: #! $$ \sum_{i=1}^n i. $$  produces the following output: This is an inline formula: 1+1 = 2. This is a display formula: \sum_{i=1}^n i.  2.7-3 Emphasize One can emphasize text by using two asterisks (**) or two underscores (__) at the beginning and the end of the text which should be emphasized. Example:  #! **This** is very important. #! This is __also important__. #! **Naturally, more than one line #! can be important.**  This produces the following output: This is very important. This is also important. Naturally, more than one line can be important. 2.7-4 Inline code One can mark inline code snippets by using backticks (`) at the beginning and the end of the text which should be marked as code. Example:  #! Call function `foobar()` at the start.  This produces the following output: Call function foobar() at the start. 2.8 Deprecated commands The following commands used to be supported, but are not anymore. @EndSection You can simply remove any use of this, AutoDoc ends sections automatically at the start of any new section or chapter. @EndSubsection You can simply remove any use of this, AutoDoc ends subsections automatically at the start of any new subsection, section or chapter. @BeginAutoDoc and @EndAutoDoc It suffices to prepend each declaration that is meant to be appear in the manual with a minimal AutoDoc comment #!. @BeginSystem name, @EndSystem, and @InsertSystem name Please use the chunk commands from subsection 2.2-14 instead. @AutoDocPlainText and @EndAutoDocPlainText Use .autodoc files or AutoDoc comments instead. AutoDoc-2025.10.16/doc/chap1.html0000644000175100017510000010261315074117054015512 0ustar runnerrunner GAP (AutoDoc) - Chapter 1: Getting started using AutoDoc
Goto Chapter: Top 1 2 3 4 Bib Ind

1 Getting started using AutoDoc

AutoDoc is a GAP package which is meant to aid GAP package authors in creating and maintaining the documentation of their packages. In this capacity it builds upon the GAPDoc package (see https://www.gap-system.org/Packages/gapdoc.html). As such, it is not a replacement for GAPDoc, but rather complements it.

In this chapter we describe how to get started using AutoDoc for your package. First, we explain in Section 1.1 how to write a new package manual from scratch.

Then we show in Section 1.3 how you might benefit from AutoDoc even if you already have a complete manual written using GAPDoc.

In Section 1.4, we explain how you may use AutoDoc to generate a title page and the main XML file for your manual.

Finally, Section 1.5, explains what AutoDoc worksheets are and how to use them.

1.1 Creating a package manual from scratch

Suppose your package is already up and running, but so far has no manual. Then you can rapidly generate a scaffold for a package manual using the AutoDoc (4.1-1) command like this, while running GAP from within your package's directory (the one containing the PackageInfo.g file):

LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := true ) );

This first reads the PackageInfo.g file from the current directory. It extracts information about the package from it (such as its name and version, see Section 1.4-1). It then creates two XML files doc/NAME_OF_YOUR_PACKAGE.xml and doc/title.xml inside the package directory. Finally, it runs GAPDoc on them to produce a nice initial PDF and HTML version of your fresh manual.

To ensure that the GAP help system picks up your package manual, you should also add something like the following to your PackageInfo.g:

PackageDoc := rec(
  BookName  := ~.PackageName,
  ArchiveURLSubset := ["doc"],
  HTMLStart := "doc/chap0.html",
  PDFFile   := "doc/manual.pdf",
  SixFile   := "doc/manual.six",
  LongTitle := ~.Subtitle,
),

Congratulations, your package now has a minimal working manual. Of course it will be mostly empty for now, but it already should contain some useful information, based on the data in your PackageInfo.g. This includes your package's name, version and description as well as information about its authors. And if you ever change the package data, (e.g. because your email address changed), just re-run the above command to regenerate the two main XML files with the latest information.

Next of course you need to provide actual content (unfortunately, we were not yet able to automate that for you, more research on artificial intelligence is required). To add more content, you have several options: You could add further GAPDoc XML files containing extra chapters, sections and so on. Or you could use classic GAPDoc source comments. For details on either, please refer to GAPDoc: Distributing a Document into Several Files, as well as Section 1.3 of this manual on how to teach the AutoDoc (4.1-1) command to include this extra documentation. Or you could use the special documentation facilities AutoDoc provides (see Section 1.2).

You will probably want to re-run the AutoDoc (4.1-1) command frequently, e.g. whenever you modified your documentation or your PackageInfo.g. To make this more convenient and reproducible, we recommend putting its invocation into a file makedoc.g in your package directory, with content based on the following example:

LoadPackage( "AutoDoc" );
AutoDoc( rec( autodoc := true ) );
QUIT;

Then you can regenerate the package manual from the command line with the following command, executed from within in the package directory:

gap makedoc.g

1.2 Documenting code with AutoDoc

To get one of your global functions, operations, attributes etc. to appear in the package manual, simply insert an AutoDoc comment of the form #! directly in front of it. For example:

#!
DeclareOperation( "ToricVariety", [ IsConvexObject ] );

This tiny change is already sufficient to ensure that the operation appears in the manual. In general, you will want to add further information about the operation, such as in the following example:

#! @Arguments conv
#! @Returns a toric variety
#! @Description
#!  Creates a toric variety out
#!  of the convex object <A>conv</A>.
DeclareOperation( "ToricVariety", [ IsConvexObject ] );

For a thorough description of what you can do with AutoDoc documentation comments, please refer to chapter 2.

Suppose you have not been using GAPDoc before but instead used the process described in section 1.1 to create your manual. Then the following GAP command will regenerate the manual and automatically include all newly documented functions, operations etc.:

LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := true,
              autodoc := true ) );

If you are not using the scaffolding feature, e.g. because you already have an existing GAPDoc based manual, then you can still use AutoDoc documentation comments. Just make sure to first edit the main XML file of your documentation, and insert the line

<#Include SYSTEM "_AutoDocMainFile.xml">

in a suitable place. This means that you can mix AutoDoc documentation comment freely with your existing documentation; you can even still make use of any existing GAPDoc documentation comments in your code. The following command should be useful for you in this case; it still scans the package code for AutoDoc documentation comments and the runs GAPDoc to produce HTML and PDF output, but does not touch your documentation XML files otherwise.

LoadPackage( "AutoDoc" );
AutoDoc( rec( autodoc := true ) );

1.3 Using AutoDoc in an existing GAPDoc manual

Even if you already have an existing GAPDoc manual, it might be interesting for you to use AutoDoc for two purposes:

First off, with AutoDoc it is very convenient to regenerate your documentation.

Secondly, the scaffolding feature which generates a title page with all the metadata of your package in a uniform way is very handy. The somewhat tedious process of keeping your title page in sync with your PackageInfo.g is fully automated this way (including the correct version, release data, author information and so on).

There are various examples of packages using AutoDoc for this purpose only, e.g. io and orb.

1.3-1 Using AutoDoc on a complete GAPDoc manual

Suppose you already have a complete XML manual, with some main and title XML files and some documentation for operations distributed over all your .g, .gd, and .gi files. Suppose the main XML file is named PACKAGENAME.xml and is in the /doc subdirectory of your package. Then you can rebuild your manual by executing the following two GAP commands from a GAP session started in the root directory of your package:

LoadPackage( "AutoDoc" );
AutoDoc( );

In contrast, the RingsForHomalg package currently uses essentially the following code in its makedoc.g file to achieve the same result:

LoadPackage( "GAPDoc" );
SetGapDocLaTeXOptions( "utf8" );
bib := ParseBibFiles( "doc/RingsForHomalg.bib" );
WriteBibXMLextFile( "doc/RingsForHomalgBib.xml", bib );
list := [
         "../gap/RingsForHomalg.gd",
         "../gap/RingsForHomalg.gi",
         "../gap/Singular.gi",
         "../gap/SingularBasic.gi",
         "../examples/RingConstructionsExternalGAP.g",
         "../examples/RingConstructionsSingular.g",
         "../examples/RingConstructionsMAGMA.g",
         "../examples/RingConstructionsMacaulay2.g",
         "../examples/RingConstructionsSage.g",
         "../examples/RingConstructionsMaple.g",
         ];
MakeGAPDocDoc( "doc", "RingsForHomalg", list, "RingsForHomalg" );
GAPDocManualLab( "RingsForHomalg" );

Note that in particular, you do not have to worry about keeping a list of your implementation files up-to-date.

But there is more. AutoDoc can create .tst files from the examples in your manual to test your package. This can be achieved via

LoadPackage( "AutoDoc" );
AutoDoc( rec( extract_examples := true ) );

Now files PACKAGENAME01.tst, PACKAGENAME02.tst and so appear in the tst/ subdirectory of your package, and can be tested as usual using Test (Reference: Test) respectively TestDirectory (Reference: TestDirectory).

1.3-2 Setting different GAPDoc options

Sometimes, the default values for the GAPDoc command used by AutoDoc may not be suitable for your manual.

Suppose your main XML file is not named PACKAGENAME.xml, but rather something else, e.g. main.xml. Then you can tell AutoDoc to use this file as the main XML file via

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( main := "main" ) ) );

As explained above, by default AutoDoc scans all .g, .gd and .gi files it can find inside of your package root directory, and in the subdirectories gap, lib, examples and examples/doc as well. If you keep source files with documentation in other directories, you can adjust the list of directories AutoDoc scans via the scan_dirs option. The following example illustrates this by instructing AutoDoc to only search in the subdirectory package_sources of the packages root directory.

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( scan_dirs := [ "package_sources" ] ) ) );

You can also specify an explicit list of files containing documentation, which will be searched in addition to any files located within the scan directories:

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( files := [ "path/to/some/hidden/file.gds" ] ) ) );

Giving such a file does not prevent the standard scan_dirs from being scanned for other files.

Next, GAPDoc supports the documentation to be built with relative paths. This means, links to manuals of other packages or the GAP library will not be absolute, but relative from your documentation. This can be particularly useful if you want to build a release tarball or move your GAP installation around later. Suppose you are starting GAP in the root path of your package as always, and the standard call of AutoDoc (4.1-1) will then build the documentation in the doc subdirectory of your package. From this directory, the gap root directory has the relative path ../../... Then you can enable the relative paths by

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( gap_root_relative_path := "../../.." ) ) );

or, since ../../.. is the standard option for gap_root_relative_path, by

LoadPackage( "AutoDoc" );
AutoDoc( rec( gapdoc := rec( gap_root_relative_path := true ) ) );

1.3-3 Checklist for converting an existing GAPDoc manual to use AutoDoc

Here is a checklist for authors of a package PackageName, which already has a GAPDoc based manual, who wish to use AutoDoc to build the manual from now on. We assume that the manual is currently built by reading a file makedoc.g and that the main .xml file is named manual.xml.

The files PackageInfo.g, makedoc.g, doc/title.xml and doc/PackageName.xml (if it exists) will be altered by this procedure, so it may be wise to keep backup copies.

You should have copies of the AutoDoc files PackageInfo.g and makedoc.g to hand when reading these instructions.

  • Copy AutoDoc/makedoc.g to PackageName/makedoc.g.

  • Edit PackageName/makedoc.g as follows.

    • Change the header comment to match other files in your package.

    • After LoadPackage("AutoDoc"); add LoadPackage("PackageName");.

    • In the AutoDoc record delete autodoc := true;.

    • In the scaffold record change the includes list to be the list of your .xml files that are contained in manual.xml.

    • If you do not have a bibliography you may delete the bib := "bib.xml", field in the scaffold. Otherwise, edit the file name if you have a different file. If you only have a .bib file (manual.bib or bib.xml.bib say) you should rename this file PackageName.bib.

    • In the LaTeXOptions record, which is in the gapdoc record, enter any LaTeX newcommands previously in manual.xml. (If there are none you may safely delete this record.) To illustrate this option, the AutoDoc file makedoc.g defines the command \bbZ by \newcommand{\bbZ}{\mathbb{Z}}, which may be used to produce the LaTeX formula f : bbZ^2 -> bbZ. However, note that this only works in the PDF version of the file.

  • Now edit PackageName/PackageInfo.g as follows.

    • Delete any PKGVERSIONDATA chunk that may be there. One reason for converting your manual to use AutoDoc is to stop using entities such as PACKAGENAMEVERSION.

    • Copy the AutoDoc record from AutoDoc/PackageInfo.g to the end of your file (just before the final "));".

    • Replace the Copyright, Abstract and Acknowledgements fields of the TitlePage record with the corresponding material from your manual.xml. (If you do not have an abstract, then delete the Abstract field, etc.)

    • In the entities record enter any entities previously stored in your manual.xml. (Again, if you have none, you may safely delete this record.) To illustrate this option the AutoDoc file PackageInfo.g defines entities for the names of packages io and PackageName.

  • If you are using a GitHub repository, as well as running "git add" on files makedoc.g, PackageInfo.g and doc/PackageName.bib, you should run "git rm -f" on files doc/manual.xml, and doc/title.xml.

You should now be ready to run GAP and Read("makedoc.g"); in your package root directory.

1.4 Scaffolds

1.4-1 Generating a title page

For most (if not all) GAP packages, the title page of the package manual lists information such as the release date, version, names and contact details of the authors, and so on. All this data is also contained in your PackageInfo.g, and whenever you make a change to that file, there is a risk that you forget to update your manual to match. And even if you don't forget it, you of course have to spend some time to adjust the manual. GAPDoc can help to a degree with this via entities. Thus, you will sometimes see code like this in PackageInfo.g files:

Version        := "1.2.3",
Date           := "20/01/2015",
##  <#GAPDoc Label="PKGVERSIONDATA">
##  <!ENTITY VERSION "1.2.3">
##  <!ENTITY RELEASEDATE "20 January 2015">
##  <!ENTITY RELEASEYEAR "2015">
##  <#/GAPDoc>

However, it is still easy to forget both of these versions. And it doesn't solve the problem of updating package authors addresses. Neither of these is a big issue, of course, but there have been plenty examples in the past where people forget either of these two things, and it can be slightly embarrassing. It may even require you to make a new release just to fix the issue, which in our opinion is a sad waste of your valuable time.

So instead of worrying about manually synchronising these things, you can instruct AutoDoc to generate a title page for your manual based on the information in your PackageInfo.g. The following commands do just that (in addition to building your manual), by generating a file called doc/title.xml.

LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := rec( MainPage := false ) ) );

Note that this only outputs doc/title.xml but does not touch any other files of your documentation. In particular, you need to explicitly include doc/title.xml from your main XML file.

However, you can also tell AutoDoc to maintain the main XML file for you, in which case this is automatic. In fact, this is the default if you enable scaffolding; the above example command explicitly told AutoDoc not to generate a main page.

1.4-2 Generating the main XML file

The following generates a main XML file for your documentation in addition to the title page. The main XML file includes the title page by default, as well as any documentation generated from AutoDoc documentation comments.

LoadPackage( "AutoDoc" );
AutoDoc( rec( scaffold := true ) );

You can instruct AutoDoc to include additional XML files by giving it a list of filenames, as in the following example:

LoadPackage( "AutoDoc" );
AutoDoc(rec(
    scaffold := rec(
        includes := [ "somefile.xml", "anotherfile.xml" ]
    )
));

For more information, please consult the documentation of the AutoDoc (4.1-1) function.

1.4-3 What data is used from PackageInfo.g?

AutoDoc can use data from PackageInfo.g in order to generate a title page. Specifically, the following components of the package info record are taken into account:

PackageName

This is used to set the <Title> element of the title page.

Subtitle

This is used to set the <Subtitle> element of the title page.

Version

This is used to set the <Version> element of the title page, with the string Version prepended.

Date

This is used to set the <Date> element of the title page.

Persons

This is used to generate <Author> elements in the generated title page.

PackageDoc

This is a record (or a list of records) which is used to tell the GAP help system about the package manual. Currently AutoDoc extracts the value of the PackageDoc.BookName component and then passes that on to GAPDoc when creating the HTML, PDF and text versions of the manual.

AutoDoc

This is a record which can be used to control the scaffolding performed by AutoDoc, specifically to provide extra information for the title page. For example, you can set AutoDoc.TitlePage.Copyright to a string which will then be inserted on the generated title page. Using this method you can customize the following title page elements: TitleComment, Abstract, Copyright, Acknowledgements and Colophon.

Note that AutoDoc.TitlePage behaves exactly the same as the scaffold.TitlePage parameter of the AutoDoc (4.1-1) function.

1.5 AutoDoc worksheets

AutoDoc worksheets can be used to create HTML and PDF documents using AutoDoc syntax and possibly including GAP examples and implementations without having them associated to a package. A file for a worksheet could look like this:

#! @Title My first worksheet
#! @Author Charlie Brown

#! @Chapter Some groups

#! @BeginExample
S3 := SymmetricGroup( 3 );;
S4 := SymmetricGroup( 4 );;
#! @EndExample

Now, one can create a PDF and HTML document, like a package documentation out of it. Suppose the document above is saved as worksheet.g. Then, when GAP is started in the directory of this file, the command

AutoDocWorksheet( "worksheet.g" );

will create a subdirectory called doc of the current directory in which it will create the documentation. There are several options to configure the output of the worksheet command, which are identical to the options of the AutoDoc (4.1-1) command. It is even possible to test the examples in the worksheet using the extract_examples option of the AutoDoc (4.1-1) command.

Since the worksheets do not have a PackageInfo.g to extract information, all possible tags that GAPDoc supports for the title page can be set into the document. A fully typed title page can look like this:

#! @Title My first worksheet
#! @Subtitle Some small examples
#! @Author Charlie Brown

#! @Version 0.1
#! @TitleComment Some worksheet
#! @Date 01/01/2016
#! @Address TU Kaiserslautern
#! @Abstract
#!  A worksheet showing some small examples about groups.
#! @Copyright 2016 Charlie Brown
#! @Acknowledgements Woodstock
#! @Colophon Some colophon

#! @Chapter Some groups

#! @BeginExample
S3 := SymmetricGroup( 3 );;
S4 := SymmetricGroup( 4 );;
#! @EndExample
Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chapBib_mj.html0000644000175100017510000000522215074117054016532 0ustar runnerrunner GAP (AutoDoc) - References
Goto Chapter: Top 1 2 3 4 Bib Ind

References

[LN12] Lübeck, F. and Neunhöffer, M., GAPDoc (Version 1.5.1), RWTH Aachen (2012)
( GAP package, http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html ).

Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chap3_mj.html0000644000175100017510000000733415074117054016206 0ustar runnerrunner GAP (AutoDoc) - Chapter 3: AutoDoc worksheets
Goto Chapter: Top 1 2 3 4 Bib Ind

3 AutoDoc worksheets

3.1 Worksheets

3.1-1 AutoDocWorksheet
‣ AutoDocWorksheet( list_of_filenames: options )( function )

The intention of these function is to create stand-alone pdf and html files using AutoDoc without having them associated to a package. It uses the same optional records as the AutoDoc command itself, but instead of a package name there should be a filename or a list of filenames containing AutoDoc text from which the documents are created. Please see the AutoDoc command for more information about this and have a look at 1.5 for a simple worksheet example.

Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chap4.html0000644000175100017510000005313115074117054015515 0ustar runnerrunner GAP (AutoDoc) - Chapter 4: AutoDoc
Goto Chapter: Top 1 2 3 4 Bib Ind

4 AutoDoc

4.1 The AutoDoc() function

4.1-1 AutoDoc
‣ AutoDoc( [packageOrDirectory][,] [optrec] )( function )

Returns: nothing

This is the main function of the AutoDoc package. It can perform any combination of the following tasks:

  1. It can (re)generate a scaffold for your package manual. That is, it can produce two XML files in GAPDoc format to be used as part of your manual: First, a file named doc/PACKAGENAME.xml (with your package's name substituted) which is used as main XML file for the package manual, i.e. this file sets the XML doctype and defines various XML entities, includes other XML files (both those generated by AutoDoc as well as additional files created by other means), tells GAPDoc to generate a table of contents and an index, and more. Secondly, it creates a file doc/title.xml containing a title page for your documentation, with information about your package (name, description, version), its authors and more, based on the data in your PackageInfo.g.

  2. It can scan your package for AutoDoc based documentation (by using AutoDoc tags and the Autodoc command. This will produce further XML files to be used as part of the package manual.

  3. It can use GAPDoc to generate PDF, text and HTML (with MathJaX enabled) documentation from the GAPDoc XML files it generated as well as additional such files provided by you. For this, it invokes MakeGAPDocDoc (GAPDoc: MakeGAPDocDoc) to convert the XML sources, and it also instructs GAPDoc to copy supplementary files (such as CSS style files) into your doc directory (see CopyHTMLStyleFiles (GAPDoc: CopyHTMLStyleFiles)).

For more information and some examples, please refer to Chapter 1.

The parameters have the following meanings:

packageOrDirectory

The purpose of this parameter is twofold: to determine the package directory in which AutoDoc will operate, and to find the metadata concerning the package being documented. The parameter is either a string, an IsDirectory object, or omitted. If it is a string, AutoDoc interprets it as the name of a package, uses the metadata of the first package known to GAP with that name, and uses the InstallationPath specified in that metadata as the package directory. If packageOrDirectory is an IsDirectory object, this is used as package directory; if the argument is omitted, then the current directory is used. In the last two cases, the specified directory must contain a PackageInfo.g file, and AutoDoc extracts all needed metadata from that. The IsDirectory form is for example useful if you have multiple versions of the package around and want to make sure the documentation of the correct version is built.

Note that when using AutoDocWorksheet (see 3.1), there is no parameter corresponding to packageOrDirectory and so the package directory is always the current directory, and there is no metadata.

optrec

optrec can be a record with some additional options. The following are currently supported:

dir

This should either be a string, in which case it must be a path relative to the specified package directory, or a Directory() object. (Thus, the only way to designate an absolute directory is with a Directory() object.) This option specifies where the package documentation (e.g. the GAPDoc XML or the manual PDF, etc.) files are stored and/or will be generated.
Default value: "doc/".

scaffold

This controls whether and how to generate scaffold XML files for the package documentation.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.scaffold is missing but the package's info record in PackageInfo.g has an AutoDoc entry. In all other cases (in particular if opt.scaffold is false), scaffolding is disabled.

If scaffolding is enabled, and PackageInfo.AutoDoc exists, then it is assumed to be a record, and its contents are used as default values for the scaffold settings.

If opt.scaffold is a record, it may contain the following entries.

includes

A list of XML files to be included in the body of the main XML file. If you specify this list and also are using AutoDoc to document your operations with AutoDoc comments, you can add _AutoDocMainFile.xml to this list to control at which point the documentation produced by AutoDoc is inserted. If you do not do this, it will be added after the last of your own XML files.

index

By default, the scaffold creates an index. If you do not want an index, set this to false.

appendix

This entry is similar to opt.scaffold.includes but is used to specify files to include after the main body of the manual, i.e. typically appendices.

bib

The name of a bibliography file, in BibTeX or XML format. If this key is not set, but there is a file doc/PACKAGENAME.bib then it is assumed that you want to use this as your bibliography.

entities

A record whose keys are taken as entity names, set to the corresponding (string) values. For example, if you pass the record SomePackage,

             rec( SomePackage := "<Package>SomePackage</Package>",
                  RELEASEYEAR := "2015" )

then the following entity definitions are added to the XML preamble:

<!ENTITY SomePackage '<Package>SomePackage</Package>'>
             <!ENTITY RELEASEYEAR '2015'>

This allows you to write &SomePackage; and &RELEASEYEAR; in your documentation, which will be replaced by respective values specified in the entities definition.

TitlePage

A record whose entries are used to embellish the generated title page for the package manual with extra information, such as a copyright statement or acknowledgments. To this end, the names of the record components are used as XML element names, and the values of the components are outputted as content of these XML elements. For example, you could pass the following record to set a custom acknowledgements text:

             rec( Acknowledgements := "Many thanks to ..." )

For a list of valid entries in the title page, please refer to the GAPDoc manual, specifically section GAPDoc: TitlePage.

MainPage

If scaffolding is enabled, by default a main XML file is generated (this is the file which contains the XML doctype and more). If you do not want this (e.g. because you have a handwritten main XML file), but still want AutoDoc to generate a title page for you, you can set this option to false

document_class

Sets the document class of the resulting PDF. The value can either be a string which has to be the name of the new document class, a list containing this string, or a list of two strings. Then the first one has to be the document class name, the second one the option string ( contained in [ ] ) in LaTeX.

latex_header_file

Replaces the standard header from GAPDoc completely with the header in this LaTeX file. Please be careful here, and look at GAPDoc's latexheader.tex file for an example.

autodoc

This controls whether and how to generate additional XML documentation files by scanning for AutoDoc documentation comments.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.autodoc is missing but the package depends (directly) on the AutoDoc package. In all other cases (in particular if opt.autodoc is false), this feature is disabled.

If opt.autodoc is a record, it may contain the following entries.

files

A list of files (given by paths relative to the package directory) to be scanned for AutoDoc documentation comments. Usually it is more convenient to use autodoc.scan_dirs, see below.

scan_dirs

A list of subdirectories of the package directory (given as relative paths) which AutoDoc then scans for .gi, .gd, .g, and .autodoc files; all of these files are then scanned for AutoDoc documentation comments.
Default value: [ ".", "gap", "lib", "examples", "examples/doc" ].

level

This defines the level of the created documentation. The default value is 0. When parts of the manual are declared with a higher value they will not be printed into the manual.

gapdoc

This controls whether and how to invoke GAPDoc to create HTML, PDF and text files from your various XML files.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.gapdoc is missing. In all other cases (in particular if opt.gapdoc is false), this feature is disabled.

If opt.gapdoc is a record, it may contain the following entries.

main

The name of the main XML file of the package manual. This exists primarily to support packages with existing manual which use a filename here which differs from the default. In particular, specifying this is unnecessary when using scaffolding.
Default value: PACKAGENAME.xml.

files

A list of files (given by paths relative to the package directory) to be scanned for GAPDoc documentation comments. Usually it is more convenient to use gapdoc.scan_dirs, see below.

scan_dirs

A list of subdirectories of the package directory (given as relative paths) which AutoDoc then scans for .gi, .gd and .g files; all of these files are then scanned for GAPDoc documentation comments.
Default value: [ ".", "gap", "lib", "examples", "examples/doc" ].

LaTeXOptions

Must be a record with entries which can be understood by SetGapDocLaTeXOptions (GAPDoc: SetGapDocLaTeXOptions). Each entry can be a string, which will be given to GAPDoc directly, or a list containing of two entries: The first one must be the string "file", the second one a filename. This file will be read and then its content is passed to GAPDoc as option with the name of the entry.

gap_root_relative_path

Either a boolean, or a string containing a relative path. By default (if this option is not set, or is set to false), references in the generated documentation referring to external documentation (such as the GAP manual) are encoded using absolute paths. This is fine as long as the documentation stays on only a single computer, but is problematic when preparing documentation that should be used on multiple computers, e.g., when creating a distribution archive of a GAP package.
Thus, if a relative path is provided via this option (or if it is set to true, in which case the relative path ../../.. is used), then AutoDoc and GAPDoc attempt to replace all absolute paths in references to GAP manuals by paths based on this relative path.

On a technical level, AutoDoc passes the relative path to the gaproot parameter of MakeGAPDocDoc (GAPDoc: MakeGAPDocDoc)

extract_examples

Either true or a record. If set to true, then all manual examples are extracted and placed into files tst/PACKAGENAME01.tst, tst/PACKAGENAME02.tst, ... and so on, with one file for each chapter. For chapters with no examples, no file is created.

As a record, the entry can have the following entries itself, to specify some options.

units

This controls how examples are grouped into files. Recognized values are "Chapter" (default), "Section", "Subsection" or "Single". Depending on the value, one file is created for each chapter, each section, each subsection or each example. For all other values only a single file is created.

On a technical level, AutoDoc passes the value to the units parameter of ExtractExamples (GAPDoc: ExtractExamples).

skip_empty_in_numbering

If set to true (the default), the generated files use filenames with strictly sequential numbering; that means that if chapter 1 (or whatever units are being used) contains no examples but chapter 2 does, then the examples for chapter 2 are put into the file tst/PACKAGENAME01.tst. If this option is set to false, then the chapter numbers are used to generate the filenames; so the examples for chapter 2 would be put into the file tst/PACKAGENAME02.tst.

4.1-2 InfoAutoDoc
‣ InfoAutoDoc( info class )

Info class for the AutoDoc package. Set this to 0 to suppress info messages, 1 to allow most messages, and 2 to allow all messages including those that contain file paths.

This can be set by calling, for example, SetInfoLevel(InfoPackageManager, 0). Default value 1.

4.2 Examples

Some basic examples for using AutoDoc were already shown in Chapter 1.

Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chap3.txt0000644000175100017510000000145115074117054015365 0ustar runnerrunner 3 AutoDoc worksheets 3.1 Worksheets 3.1-1 AutoDocWorksheet AutoDocWorksheet( list_of_filenames: options )  function The intention of these function is to create stand-alone pdf and html files using AutoDoc without having them associated to a package. It uses the same optional records as the AutoDoc command itself, but instead of a package name there should be a filename or a list of filenames containing AutoDoc text from which the documents are created. Please see the AutoDoc command for more information about this and have a look at 1.5 for a simple worksheet example. AutoDoc-2025.10.16/doc/bib.xml0000644000175100017510000000101215074117054015075 0ustar runnerrunner FrankLübeck MaxNeunhöffer <C>GAPDoc (Version 1.5.1)</C> RWTH Aachen 2012 GAP package, http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc/index.html AutoDoc-2025.10.16/doc/toggless.js0000644000175100017510000000420515074117054016013 0ustar runnerrunner/* toggless.js Frank Lübeck */ /* this file contains two functions: mergeSideTOCHooks: this changes div.ContSect elements to the class ContSectClosed and includes a hook to toggle between ContSectClosed and ContSectOpen. openclosetoc: this function does the toggling, the rest is done by CSS */ closedTOCMarker = "▶ "; openTOCMarker = "▼ "; noTOCMarker = " "; /* merge hooks into side toc for opening/closing subsections with openclosetoc */ function mergeSideTOCHooks() { var hlist = document.getElementsByTagName("div"); for (var i = 0; i < hlist.length; i++) { if (hlist[i].className == "ContSect") { var chlds = hlist[i].childNodes; var el = document.createElement("span"); var oncl = document.createAttribute("class"); oncl.nodeValue = "toctoggle"; el.setAttributeNode(oncl); var cont; if (chlds.length > 2) { var oncl = document.createAttribute("onclick"); oncl.nodeValue = "openclosetoc(event)"; el.setAttributeNode(oncl); cont = document.createTextNode(closedTOCMarker); } else { cont = document.createTextNode(noTOCMarker); } el.appendChild(cont); hlist[i].firstChild.insertBefore(el, hlist[i].firstChild.firstChild); hlist[i].className = "ContSectClosed"; } } } function openclosetoc (event) { /* first two steps to make it work in most browsers */ var evt=window.event || event; if (!evt.target) evt.target=evt.srcElement; var markClosed = document.createTextNode(closedTOCMarker); var markOpen = document.createTextNode(openTOCMarker); var par = evt.target.parentNode.parentNode; if (par.className == "ContSectOpen") { par.className = "ContSectClosed"; evt.target.replaceChild(markClosed, evt.target.firstChild); } else if (par.className == "ContSectClosed") { par.className = "ContSectOpen"; evt.target.replaceChild(markOpen, evt.target.firstChild); } } /* adjust jscontent which is called onload */ jscontentfuncs.push(mergeSideTOCHooks); AutoDoc-2025.10.16/doc/manual.six0000644000175100017510000004611515074117054015636 0ustar runnerrunner#SIXFORMAT GapDocGAP HELPBOOKINFOSIXTMP := rec( encoding := "UTF-8", bookname := "AutoDoc", entries := [ [ "Title page", "0.0", [ 0, 0, 0 ], 1, 1, "title page", "X7D2C85EC87DD46E5" ], [ "Abstract", "0.0-1", [ 0, 0, 1 ], 43, 2, "abstract", "X7AA6C5737B711C89" ] , [ "Copyright", "0.0-2", [ 0, 0, 2 ], 49, 2, "copyright", "X81488B807F2A1CF1" ], [ "Acknowledgements", "0.0-3", [ 0, 0, 3 ], 57, 2, "acknowledgements", "X82A988D47DFAFCFA" ], [ "Table of Contents", "0.0-4", [ 0, 0, 4 ], 62, 3, "table of contents", "X8537FEB07AF2BEC8" ], [ "\033[1X\033[33X\033[0;-2YGetting started using \033[5XAutoDoc\033[105X\\ 033[101X\027\033[1X\027\033[133X\033[101X", "1", [ 1, 0, 0 ], 1, 4, "getting started using autodoc", "X7A0D7AA484F466E1" ], [ "\033[1X\033[33X\033[0;-2YCreating a package manual from scratch\033[133X\\ 033[101X", "1.1", [ 1, 1, 0 ], 23, 4, "creating a package manual from scratch" , "X7BFBC6907B26AA95" ], [ "\033[1X\033[33X\033[0;-2YDocumenting code with \033[5XAutoDoc\033[105X\\ 033[101X\027\033[1X\027\033[133X\033[101X", "1.2", [ 1, 2, 0 ], 94, 5, "documenting code with autodoc", "X87A00EED866E22E8" ], [ "\033[1X\033[33X\033[0;-2YUsing \033[5XAutoDoc\033[105X\033[101X\027\033[1X\ \027 in an existing \033[5XGAPDoc\033[105X\033[101X\027\033[1X\027 manual\033[\ 133X\033[101X", "1.3", [ 1, 3, 0 ], 154, 6, "using autodoc in an existing gapdoc manual", "X7FA614637B807F4D" ], [ "\033[1X\033[33X\033[0;-2YUsing \033[5XAutoDoc\033[105X\033[101X\027\033[1X\ \027 on a complete \033[5XGAPDoc\033[105X\033[101X\027\033[1X\027 manual\033[1\ 33X\033[101X", "1.3-1", [ 1, 3, 1 ], 172, 6, "using autodoc on a complete gapdoc manual", "X7F3CEB097AF47C1E" ], [ "\033[1X\033[33X\033[0;-2YSetting different \033[5XGAPDoc\033[105X\033[101X\ \027\033[1X\027 options\033[133X\033[101X", "1.3-2", [ 1, 3, 2 ], 226, 7, "setting different gapdoc options", "X7D0DDF2284F2D24A" ], [ "\033[1X\033[33X\033[0;-2YChecklist for converting an existing \033[5XGAPDo\ c\033[105X\033[101X\027\033[1X\027 manual to use \033[5XAutoDoc\033[105X\033[1\ 01X\027\033[1X\027\033[133X\033[101X", "1.3-3", [ 1, 3, 3 ], 288, 8, "checklist for converting an existing gapdoc manual to use autodoc", "X83448D91868D7994" ], [ "\033[1X\033[33X\033[0;-2YScaffolds\033[133X\033[101X", "1.4", [ 1, 4, 0 ], 357, 9, "scaffolds", "X8524193D824CDE0D" ], [ "\033[1X\033[33X\033[0;-2YGenerating a title page\033[133X\033[101X", "1.4-1", [ 1, 4, 1 ], 360, 9, "generating a title page", "X7CF22DE28478316F" ], [ "\033[1X\033[33X\033[0;-2YGenerating the main XML file\033[133X\033[101X", "1.4-2", [ 1, 4, 2 ], 409, 10, "generating the main xml file", "X7CD72CC780874FD5" ], [ "\033[1X\033[33X\033[0;-2YWhat data is used from \033[11XPackageInfo.g\033[\ 111X\033[101X\027\033[1X\027?\033[133X\033[101X", "1.4-3", [ 1, 4, 3 ], 436, 10, "what data is used from packageinfo.g?", "X799956EA85D3FC15" ], [ "\033[1X\033[33X\033[0;-2YAutoDoc worksheets\033[133X\033[101X", "1.5", [ 1, 5, 0 ], 477, 11, "autodoc worksheets", "X80ED3C2A78146AD1" ], [ "\033[1X\033[33X\033[0;-2Y\033[5XAutoDoc\033[105X\033[101X\027\033[1X\027 d\ ocumentation comments\033[133X\033[101X", "2", [ 2, 0, 0 ], 1, 13, "autodoc documentation comments", "X87668C487B1A2094" ], [ "\033[1X\033[33X\033[0;-2YDocumenting declarations\033[133X\033[101X", "2.1", [ 2, 1, 0 ], 21, 13, "documenting declarations", "X871482CE838C68F6" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@Description \033[3Xdescr\033[103X\033[10\ 1X\027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[10\ 1X", "2.1-1", [ 2, 1, 1 ], 29, 13, "description descr", "X7F1D85188262A827" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@Returns \033[3Xret_val\033[103X\033[101\ X\027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101\ X", "2.1-2", [ 2, 1, 2 ], 36, 13, "returns ret_val", "X7DCAB2F87E8FAE90" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@Arguments \033[3Xargs\033[103X\033[101X\\ 027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101X" , "2.1-3", [ 2, 1, 3 ], 43, 13, "arguments args", "X81DAA454857F7971" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@Group \033[3Xgrpname\033[103X\033[101X\\ 027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101X" , "2.1-4", [ 2, 1, 4 ], 53, 14, "group grpname", "X8677FE8F80C00B14" ] , [ "\033[1X\033[33X\033[0;-2Y\033[10X@Label \033[3Xlabel\033[103X\033[101X\\ 027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101X" , "2.1-5", [ 2, 1, 5 ], 59, 14, "label label", "X7B0E20A27D64DF6F" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@ChapterInfo \033[3Xchapter\033[103X\033\ [101X\027\033[1X\027\033[10X\027, \033[3Xsection\033[103X\033[101X\027\033[1X\ \027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101X", "2.1-8", [ 2, 1, 8 ], 95, 14, "chapterinfo chapter section", "X78938EE37A532FFA" ], [ "\033[1X\033[33X\033[0;-2YOther documentation comments\033[133X\033[101X", "2.2", [ 2, 2, 0 ], 118, 15, "other documentation comments", "X8152FEF9844B1ACD" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@Chapter \033[3Xname\033[103X\033[101X\\ 027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101X" , "2.2-1", [ 2, 2, 1 ], 125, 15, "chapter name", "X823E613385D09F6F" ] , [ "\033[1X\033[33X\033[0;-2Y\033[10X@Section \033[3Xname\033[103X\033[101X\\ 027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101X" , "2.2-2", [ 2, 2, 2 ], 156, 15, "section name", "X78AA98BA7E0635D0" ] , [ "\033[1X\033[33X\033[0;-2Y\033[10X@Subsection \033[3Xname\033[103X\033[101X\ \027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101X\ ", "2.2-3", [ 2, 2, 3 ], 172, 16, "subsection name", "X7FD77434802A3580" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@BeginGroup \033[3X[grpname]\033[103X\\ 033[101X\027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\ \033[101X", "2.2-4", [ 2, 2, 4 ], 191, 16, "begingroup [grpname]", "X7D3060C17EDBCED1" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@EndGroup\033[110X\033[101X\027\033[1X\\ 027\033[133X\033[101X", "2.2-5", [ 2, 2, 5 ], 201, 16, "endgroup", "X7C17EB007FD42C87" ], [ "\033[1X\033[33X\033[0;-2Y@GroupTitle \033[3Xtitle\033[103X\033[101X\027\\ 033[1X\027\033[133X\033[101X", "2.2-6", [ 2, 2, 6 ], 221, 16, "grouptitle title", "X82FB96F37FAE8167" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@Level \033[3Xlvl\033[103X\033[101X\027\\ 033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[133X\033[101X", "2.2-7", [ 2, 2, 7 ], 228, 16, "level lvl", "X7BF81EAF80D1A4B5" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@ResetLevel\033[110X\033[101X\027\033[1X\\ 027\033[133X\033[101X", "2.2-8", [ 2, 2, 8 ], 237, 17, "resetlevel", "X7C6723D57F424215" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@BeginExample\033[110X\033[101X\027\033[1\ X\027 and \033[10X@EndExample\033[110X\033[101X\027\033[1X\027\033[133X\033[10\ 1X", "2.2-9", [ 2, 2, 9 ], 242, 17, "beginexample and endexample", "X83D6DA3B83D3436C" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@BeginExampleSession\033[110X\033[101X\\ 027\033[1X\027 and \033[10X@EndExampleSession\033[110X\033[101X\027\033[1X\027\ \033[133X\033[101X", "2.2-10", [ 2, 2, 10 ], 275, 17, "beginexamplesession and endexamplesession", "X861E2E778510CAF7" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@BeginLog\033[110X\033[101X\027\033[1X\\ 027 and \033[10X@EndLog\033[110X\033[101X\027\033[1X\027\033[133X\033[101X", "2.2-11", [ 2, 2, 11 ], 312, 18, "beginlog and endlog", "X81A2D44D834C0A17" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@BeginLogSession\033[110X\033[101X\027\\ 033[1X\027 and \033[10X@EndLogSession\033[110X\033[101X\027\033[1X\027\033[133\ X\033[101X", "2.2-12", [ 2, 2, 12 ], 319, 18, "beginlogsession and endlogsession", "X7BADE876794FF309" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@DoNotReadRestOfFile\033[110X\033[101X\\ 027\033[1X\027\033[133X\033[101X", "2.2-13", [ 2, 2, 13 ], 327, 18, "donotreadrestoffile", "X78DC644E8519280C" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@BeginChunk \033[3Xname\033[103X\033[101X\ \027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027, \033[10X@EndChun\ k\033[110X\033[101X\027\033[1X\027, and \033[10X@InsertChunk \033[3Xname\033[1\ 03X\033[101X\027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027\033[1\ 33X\033[101X", "2.2-14", [ 2, 2, 14 ], 341, 18, "beginchunk name endchunk and insertchunk name", "X83C01F9B7FA1C973" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@BeginCode \033[3Xname\033[103X\033[101X\ \027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027, @EndCode, and \ \033[10X@InsertCode \033[3Xname\033[103X\033[101X\027\033[1X\027\033[10X\027\ \033[110X\033[101X\027\033[1X\027\033[133X\033[101X", "2.2-15", [ 2, 2, 15 ], 378, 19, "begincode name endcode and insertcode name", "X7D3671AF86B995B9" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@LatexOnly \033[3Xtext\033[103X\033[101X\\ 027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027, \033[10X@BeginLat\ exOnly\033[110X\033[101X\027\033[1X\027, and \033[10X@EndLatexOnly\033[110X\ \033[101X\027\033[1X\027\033[133X\033[101X", "2.2-16", [ 2, 2, 16 ], 394, 19, "latexonly text beginlatexonly and endlatexonly", "X8033B34F80A12A10" ], [ "\033[1X\033[33X\033[0;-2Y\033[10X@NotLatex \033[3Xtext\033[103X\033[101X\ \027\033[1X\027\033[10X\027\033[110X\033[101X\027\033[1X\027, \033[10X@BeginNo\ tLatex\033[110X\033[101X\027\033[1X\027, and \033[10X@EndNotLatex\033[110X\033\ [101X\027\033[1X\027\033[133X\033[101X", "2.2-17", [ 2, 2, 17 ], 409, 19, "notlatex text beginnotlatex and endnotlatex", "X7EF303147F1BCC22" ], [ "\033[1X\033[33X\033[0;-2YTitle page commands\033[133X\033[101X", "2.3", [ 2, 3, 0 ], 424, 19, "title page commands", "X841E3AD584F5385C" ], [ "\033[1X\033[33X\033[0;-2YPlain text files\033[133X\033[101X", "2.4", [ 2, 4, 0 ], 461, 20, "plain text files", "X828AE38F80CB02E7" ], [ "\033[1X\033[33X\033[0;-2YGrouping\033[133X\033[101X", "2.5", [ 2, 5, 0 ], 470, 20, "grouping", "X7D7A38F87BC40C48" ], [ "\033[1X\033[33X\033[0;-2YA family of operations\033[133X\033[101X", "2.5-1", [ 2, 5, 1 ], 518, 21, "a family of operations", "X79BF060F8436C586" ], [ "\033[1X\033[33X\033[0;-2YLevel\033[133X\033[101X", "2.6", [ 2, 6, 0 ], 527, 21, "level", "X8209AFDE8209AFDE" ], [ "\033[1X\033[33X\033[0;-2YMarkdown-like formatting of text in \033[5XAutoDo\ c\033[105X\033[101X\027\033[1X\027\033[133X\033[101X", "2.7", [ 2, 7, 0 ], 547, 22, "markdown-like formatting of text in autodoc", "X79558A2F7FE187B4" ], [ "\033[1X\033[33X\033[0;-2YLists\033[133X\033[101X", "2.7-1", [ 2, 7, 1 ], 556, 22, "lists", "X7B256AE5780F140A" ], [ "\033[1X\033[33X\033[0;-2YMath modes\033[133X\033[101X", "2.7-2", [ 2, 7, 2 ], 593, 22, "math modes", "X871412737A0E12E2" ], [ "\033[1X\033[33X\033[0;-2YEmphasize\033[133X\033[101X", "2.7-3", [ 2, 7, 3 ], 614, 23, "emphasize", "X7ED0330479146EFC" ], [ "\033[1X\033[33X\033[0;-2YInline code\033[133X\033[101X", "2.7-4", [ 2, 7, 4 ], 632, 23, "inline code", "X838CCDEB7E0ECEE2" ], [ "\033[1X\033[33X\033[0;-2YDeprecated commands\033[133X\033[101X", "2.8", [ 2, 8, 0 ], 645, 23, "deprecated commands", "X78CA9E5C7F494C19" ], [ "\033[1X\033[33X\033[0;-2YAutoDoc worksheets\033[133X\033[101X", "3", [ 3, 0, 0 ], 1, 24, "autodoc worksheets", "X80ED3C2A78146AD1" ], [ "\033[1X\033[33X\033[0;-2YWorksheets\033[133X\033[101X", "3.1", [ 3, 1, 0 ], 4, 24, "worksheets", "X801D4A2F8292704C" ], [ "\033[1X\033[33X\033[0;-2YAutoDoc\033[133X\033[101X", "4", [ 4, 0, 0 ], 1, 25, "autodoc", "X7CBD8AAF7DCEF352" ], [ "\033[1X\033[33X\033[0;-2YThe AutoDoc() function\033[133X\033[101X", "4.1", [ 4, 1, 0 ], 4, 25, "the autodoc function", "X863584DB8497D8BA" ] , [ "\033[1X\033[33X\033[0;-2YExamples\033[133X\033[101X", "4.2", [ 4, 2, 0 ], 322, 29, "examples", "X7A489A5D79DA9E5C" ], [ "Bibliography", "bib", [ "Bib", 0, 0 ], 1, 30, "bibliography", "X7A6F98FD85F02BFE" ], [ "References", "bib", [ "Bib", 0, 0 ], 1, 30, "references", "X7A6F98FD85F02BFE" ], [ "Index", "ind", [ "Ind", 0, 0 ], 1, 31, "index", "X83A0356F839C696F" ], [ "\033[11Xmakedoc.g\033[111X", "1.1", [ 1, 1, 0 ], 23, 4, "makedoc.g", "X7BFBC6907B26AA95" ], [ "", "1.3-3", [ 1, 3, 3 ], 288, 8, "", "X83448D91868D7994" ], [ "", "1.3-3", [ 1, 3, 3 ], 288, 8, "", "X83448D91868D7994" ], [ "", "1.3-3", [ 1, 3, 3 ], 288, 8, "", "X83448D91868D7994" ], [ "", "1.3-3", [ 1, 3, 3 ], 288, 8, "", "X83448D91868D7994" ], [ "", "1.3-3", [ 1, 3, 3 ], 288, 8, "", "X83448D91868D7994" ], [ "", "1.3-3", [ 1, 3, 3 ], 288, 8, "", "X83448D91868D7994" ], [ "", "1.3-3", [ 1, 3, 3 ], 288, 8, "", "X83448D91868D7994" ], [ "\033[10X@Description \033[3Xdescr\033[103X\033[10X\027\033[110X", "2.1-1", [ 2, 1, 1 ], 29, 13, "description descr", "X7F1D85188262A827" ] , [ "\033[10X@Returns \033[3Xret_val\033[103X\033[10X\027\033[110X", "2.1-2", [ 2, 1, 2 ], 36, 13, "returns ret_val", "X7DCAB2F87E8FAE90" ], [ "\033[10X@Arguments \033[3Xargs\033[103X\033[10X\027\033[110X", "2.1-3", [ 2, 1, 3 ], 43, 13, "arguments args", "X81DAA454857F7971" ], [ "\033[10X@Group \033[3Xgrpname\033[103X\033[10X\027\033[110X", "2.1-4", [ 2, 1, 4 ], 53, 14, "group grpname", "X8677FE8F80C00B14" ], [ "\033[10X@Label \033[3Xlabel\033[103X\033[10X\027\033[110X", "2.1-5", [ 2, 1, 5 ], 59, 14, "label label", "X7B0E20A27D64DF6F" ], [ "\033[2XAProperty\033[102X testlabel", "2.1-6", [ 2, 1, 6 ], 75, 14, "aproperty testlabel", "X83B63B847B5199CF" ], [ "\033[2XAProperty\033[102X for IsObject", "2.1-7", [ 2, 1, 7 ], 90, 14, "aproperty for isobject", "X78A9022A7D5CB20E" ], [ "\033[10X@ChapterInfo\033[110X", "2.1-8", [ 2, 1, 8 ], 95, 14, "chapterinfo", "X78938EE37A532FFA" ], [ "\033[10X@Chapter\033[110X", "2.2-1", [ 2, 2, 1 ], 125, 15, "chapter", "X823E613385D09F6F" ], [ "\033[10X@ChapterLabel\033[110X", "2.2-1", [ 2, 2, 1 ], 125, 15, "chapterlabel", "X823E613385D09F6F" ], [ "\033[10X@ChapterTitle\033[110X", "2.2-1", [ 2, 2, 1 ], 125, 15, "chaptertitle", "X823E613385D09F6F" ], [ "\033[10X@Section\033[110X", "2.2-2", [ 2, 2, 2 ], 156, 15, "section", "X78AA98BA7E0635D0" ], [ "\033[10X@SectionLabel\033[110X", "2.2-2", [ 2, 2, 2 ], 156, 15, "sectionlabel", "X78AA98BA7E0635D0" ], [ "\033[10X@SectionTitle\033[110X", "2.2-2", [ 2, 2, 2 ], 156, 15, "sectiontitle", "X78AA98BA7E0635D0" ], [ "\033[10X@Subsection\033[110X", "2.2-3", [ 2, 2, 3 ], 172, 16, "subsection", "X7FD77434802A3580" ], [ "\033[10X@SubsectionLabel\033[110X", "2.2-3", [ 2, 2, 3 ], 172, 16, "subsectionlabel", "X7FD77434802A3580" ], [ "\033[10X@SubsectionTitle\033[110X", "2.2-3", [ 2, 2, 3 ], 172, 16, "subsectiontitle", "X7FD77434802A3580" ], [ "\033[10X@BeginGroup\033[110X", "2.2-4", [ 2, 2, 4 ], 191, 16, "begingroup", "X7D3060C17EDBCED1" ], [ "\033[10X@EndGroup\033[110X", "2.2-5", [ 2, 2, 5 ], 201, 16, "endgroup", "X7C17EB007FD42C87" ], [ "\033[10X@GroupTitle\033[110X", "2.2-6", [ 2, 2, 6 ], 221, 16, "grouptitle", "X82FB96F37FAE8167" ], [ "\033[10X@Level\033[110X", "2.2-7", [ 2, 2, 7 ], 228, 16, "level", "X7BF81EAF80D1A4B5" ], [ "\033[10X@ResetLevel\033[110X", "2.2-8", [ 2, 2, 8 ], 237, 17, "resetlevel", "X7C6723D57F424215" ], [ "\033[10X@BeginExample\033[110X", "2.2-9", [ 2, 2, 9 ], 242, 17, "beginexample", "X83D6DA3B83D3436C" ], [ "\033[10X@EndExample\033[110X", "2.2-9", [ 2, 2, 9 ], 242, 17, "endexample", "X83D6DA3B83D3436C" ], [ "\033[10X@BeginExampleSession\033[110X", "2.2-10", [ 2, 2, 10 ], 275, 17, "beginexamplesession", "X861E2E778510CAF7" ], [ "\033[10X@EndExampleSession\033[110X", "2.2-10", [ 2, 2, 10 ], 275, 17, "endexamplesession", "X861E2E778510CAF7" ], [ "\033[10X@BeginLog\033[110X", "2.2-11", [ 2, 2, 11 ], 312, 18, "beginlog", "X81A2D44D834C0A17" ], [ "\033[10X@EndLog\033[110X", "2.2-11", [ 2, 2, 11 ], 312, 18, "endlog", "X81A2D44D834C0A17" ], [ "\033[10X@BeginLogSession\033[110X", "2.2-12", [ 2, 2, 12 ], 319, 18, "beginlogsession", "X7BADE876794FF309" ], [ "\033[10X@EndLogSession\033[110X", "2.2-12", [ 2, 2, 12 ], 319, 18, "endlogsession", "X7BADE876794FF309" ], [ "\033[10X@DoNotReadRestOfFile\033[110X", "2.2-13", [ 2, 2, 13 ], 327, 18, "donotreadrestoffile", "X78DC644E8519280C" ], [ "\033[10X@BeginChunk \033[3Xname\033[103X\033[10X\027\033[110X", "2.2-14", [ 2, 2, 14 ], 341, 18, "beginchunk name", "X83C01F9B7FA1C973" ], [ "\033[10X@EndChunk\033[110X", "2.2-14", [ 2, 2, 14 ], 341, 18, "endchunk", "X83C01F9B7FA1C973" ], [ "\033[10X@InsertChunk \033[3Xname\033[103X\033[10X\027\033[110X", "2.2-14", [ 2, 2, 14 ], 341, 18, "insertchunk name", "X83C01F9B7FA1C973" ], [ "\033[10X@BeginCode \033[3Xname\033[103X\033[10X\027\033[110X", "2.2-15", [ 2, 2, 15 ], 378, 19, "begincode name", "X7D3671AF86B995B9" ], [ "\033[10X@EndCode\033[110X", "2.2-15", [ 2, 2, 15 ], 378, 19, "endcode", "X7D3671AF86B995B9" ], [ "\033[10X@InsertCode \033[3Xname\033[103X\033[10X\027\033[110X", "2.2-15", [ 2, 2, 15 ], 378, 19, "insertcode name", "X7D3671AF86B995B9" ], [ "\033[10X@LatexOnly \033[3Xtext\033[103X\033[10X\027\033[110X", "2.2-16", [ 2, 2, 16 ], 394, 19, "latexonly text", "X8033B34F80A12A10" ] , [ "\033[10X@BeginLatexOnly\033[110X", "2.2-16", [ 2, 2, 16 ], 394, 19, "beginlatexonly", "X8033B34F80A12A10" ], [ "\033[10X@EndLatexOnly\033[110X", "2.2-16", [ 2, 2, 16 ], 394, 19, "endlatexonly", "X8033B34F80A12A10" ], [ "\033[10X@NotLatex \033[3Xtext\033[103X\033[10X\027\033[110X", "2.2-17", [ 2, 2, 17 ], 409, 19, "notlatex text", "X7EF303147F1BCC22" ], [ "\033[10X@BeginNotLatex\033[110X", "2.2-17", [ 2, 2, 17 ], 409, 19, "beginnotlatex", "X7EF303147F1BCC22" ], [ "\033[10X@EndNotLatex\033[110X", "2.2-17", [ 2, 2, 17 ], 409, 19, "endnotlatex", "X7EF303147F1BCC22" ], [ "\033[2XFirstOperation\033[102X for IsInt", "2.5-1", [ 2, 5, 1 ], 518, 21, "firstoperation for isint", "X79BF060F8436C586" ], [ "\033[2XSecondOperation\033[102X for IsInt, IsGroup", "2.5-1", [ 2, 5, 1 ], 518, 21, "secondoperation for isint isgroup", "X79BF060F8436C586" ], [ "\033[2XThirdOperation\033[102X for IsGroup, IsInt", "2.5-1", [ 2, 5, 1 ], 518, 21, "thirdoperation for isgroup isint", "X79BF060F8436C586" ], [ "\033[2XAutoDocWorksheet\033[102X", "3.1-1", [ 3, 1, 1 ], 7, 24, "autodocworksheet", "X809FE4137C08B28D" ], [ "\033[2XAutoDoc\033[102X", "4.1-1", [ 4, 1, 1 ], 7, 25, "autodoc", "X7CBD8AAF7DCEF352" ], [ "\033[2XInfoAutoDoc\033[102X", "4.1-2", [ 4, 1, 2 ], 311, 29, "infoautodoc", "X81F946A785BA3D6E" ] ] ); AutoDoc-2025.10.16/doc/title.xml0000644000175100017510000000266615074117054015502 0ustar runnerrunner AutoDoc Generate documentation from &GAP; source code 2025.10.16 Sebastian Gutsche
Department Mathematik
Universität Siegen
Walter-Flex-Straße 3
57072 Siegen
Germany
gutsche@mathematik.uni-siegen.de https://algebra.mathematik.uni-siegen.de/gutsche/
Max Horn
Fachbereich Mathematik
RPTU Kaiserslautern-Landau
Gottlieb-Daimler-Straße 48
67663 Kaiserslautern
Germany
mhorn@rptu.de https://www.quendi.de/math
16 October 2025 &AutoDoc; is a &GAP; package whose purpose is to aid &GAP; package authors in creating and maintaining the documentation of their packages. ©right; 2012-2022 by Sebastian Gutsche and Max Horn

This package may be distributed under the terms and conditions of the GNU Public License Version 2 or (at your option) any later version. This documentation was prepared using the &GAPDoc; package .

AutoDoc-2025.10.16/doc/chap2.html0000644000175100017510000012357415074117054015524 0ustar runnerrunner GAP (AutoDoc) - Chapter 2: AutoDoc documentation comments

Goto Chapter: Top 1 2 3 4 Bib Ind

2 AutoDoc documentation comments

You can document declarations of global functions and variables, operations, attributes etc. by inserting AutoDoc comments into your sources before these declaration. An AutoDoc comment always starts with #!. This is also the smallest possible AutoDoc command. If you want your declaration documented, just write #! at the line before the documentation. For example:

#!
DeclareOperation( "AnOperation",
                  [ IsList ] );

This will produce a manual entry for the operation AnOperation.

Inside of AutoDoc comments, AutoDoc commands starting with @ can be used to control the output AutoDoc produces.

2.1 Documenting declarations

In the bare form above, the manual entry for AnOperation will not contain much more than the name of the operation. In order to change this, there are several commands you can put into the AutoDoc comment before the declaration. Currently, the following commands are provided:

2.1-1 @Description descr

Adds the text in the following lines of the AutoDoc to the description of the declaration in the manual. Lines are until the next AutoDoc command or until the declaration is reached.

2.1-2 @Returns ret_val

The string ret_val is added to the documentation, with the text Returns: put in front of it. This should usually give a brief hint about the type or meaning of the value returned by the documented function.

2.1-3 @Arguments args

The string args contains a description of the arguments the function expects, including optional parts, which are denoted by square brackets. The argument names can be separated by whitespace, commas or square brackets for the optional arguments, like grp[, elm] or xx[y[z] ]. If GAP options are used, this can be followed by a colon : and one or more assignments, like n[, r]: tries := 100.

2.1-4 @Group grpname

Adds the following method to a group with the given name. See section 2.5 for more information about groups.

2.1-5 @Label label

Adds label to the function as label. If this is not specified, then for declarations that involve a list of input filters (as is the case for DeclareOperation, DeclareAttribute, etc.), a default label is generated from this filter list.

#! @Label testlabel
DeclareProperty( "AProperty",
                 IsObject );

leads to this:

2.1-6 AProperty
‣ AProperty( arg )( property )

Returns: true or false

while

#!
DeclareProperty( "AProperty",
                 IsObject );

leads to this:

2.1-7 AProperty
‣ AProperty( arg )( property )

Returns: true or false

2.1-8 @ChapterInfo chapter, section

Adds the entry to the given chapter and section. Here, chapter and section are the respective titles.

As an example, a full AutoDoc comment with all options could look like this:

#! @Description
#! Computes the list of lists of degrees of ordinary characters
#! associated to the $p$-blocks of the group $G$
#! with $p$-modular character table <A>modtbl</A>
#! and underlying ordinary character table `ordtbl`.
#! @Returns a list
#! @Arguments modtbl
#! @Group CharacterDegreesOfBlocks
#! @Label chardegblocks
#! @ChapterInfo Blocks, Attributes
DeclareAttribute( "CharacterDegreesOfBlocks",
        IsBrauerTable );

2.2 Other documentation comments

There are also some commands which can be used in AutoDoc comments that are not associated to any declaration. This is useful for additional text in your documentation, examples, mathematical chapters, etc..

2.2-1 @Chapter name

Sets the active chapter, all subsequent functions which do not have an explicit chapter declared in their AutoDoc comment via @ChapterInfo will be added to this chapter. Also all text comments, i.e. lines that begin with #! without a command, and which do not follow after @Description, will be added to the chapter as regular text. Additionally, the chapters label will be set to Chapter_name. Example:

#! @Chapter My chapter
#!  This is my chapter.
#!  I document my stuff in it.

The @ChapterLabel label command can be used to set the label of the chapter to Chapter_label instead of Chapter_name. Additionally, the chapter will be stored as _Chapter_label.xml. The @ChapterTitle title command can be used to set a heading for the chapter that is different from name. Note that the title does not affect the label. If you use all three commands, i.e.,

#! @Chapter name
#! @ChapterLabel label
#! @ChapterTitle title

title is used for the headline, label for cross-referencing, and name for setting the same chapter as active chapter again.

2.2-2 @Section name

Sets an active section like @Chapter sets an active chapter. The section automatically ends with the next @Section or @Chapter command.

#! @Section My first manual section
#!  In this section I am going to document my first method.

The @SectionLabel label command can be used to set the label of the section to Section_label instead of Chapter_chaptername_Section_name. The @SectionTitle title command can be used to set a heading for the section that is different from name.

2.2-3 @Subsection name

Sets an active subsection like @Section sets an active section. The subsection automatically ends with the next @Subsection, @Section or @Chapter command. It also ends with the next documented function. Indeed, internally each function manpage is treated like a subsection.

#! @Subsection My first manual subsection
#!  In this subsection I am going to document my first example.

The @SubsectionLabel label command can be used to set the label of the subsection to Subsection_label instead of Chapter_chaptername_Section_sectionname_Subsection_name. The @SubsectionTitle title command can be used to set a heading for the subsection that is different from name.

2.2-4 @BeginGroup [grpname]

Starts a group. All following documented declarations without an explicit @Group command are grouped together in the same group with the given name. If no name is given, then a new nameless group is generated. The effect of this command is ended when an @EndGroup command is reached.

See section 2.5 for more information about groups.

2.2-5 @EndGroup

Ends the current group.

#! @BeginGroup MyGroup
#!
DeclareAttribute( "GroupedAttribute",
                  IsList );

DeclareOperation( "NonGroupedOperation",
                  [ IsObject ] );

#!
DeclareOperation( "GroupedOperation",
                  [ IsList, IsRubbish ] );
#! @EndGroup

2.2-6 @GroupTitle title

Sets the subsection heading for the current group to title. In the absence of any @GroupTitle command, the heading will be the name of the first entry in the group. See 2.5 for more information.

2.2-7 @Level lvl

Sets the current level of the documentation. All items created after this, chapters, sections, and items, are given the level lvl, until the @ResetLevel command resets the level to 0 or another level is set.

See section 2.6 for more information about levels.

2.2-8 @ResetLevel

Resets the current level to 0.

2.2-9 @BeginExample and @EndExample

@BeginExample marks the start of an example to be put into the manual. It differs from GAPDoc's <Example> (see GAPDoc: Log), in that it expects actual code (not in a comment) interspersed with comments, to allow for examples files that can be both executed by GAP, and parsed by AutoDoc. To achieve this, GAP commands are not preceded by a comment, while output has to be preceded by an AutoDoc comment. The gap> prompt for the display in the manual is added by AutoDoc. @EndExample ends the example block.

To illustrate this command, consider this input:

#! @BeginExample
S5 := SymmetricGroup(5);
#! Sym( [ 1 .. 5 ] )
Order(S5);
#! 120
#! @EndExample

This results in the following output:

gap> S5 := SymmetricGroup(5);
Sym( [ 1 .. 5 ] )
gap> Order(S5);
120

The AutoDoc command @Example is an alias of @BeginExample.

2.2-10 @BeginExampleSession and @EndExampleSession

@BeginExampleSession marks the start of an example to be put into the manual, while @EndExampleSession ends the example block. It is the direct analog of GAPDoc's <Example> (see GAPDoc: Log).

To illustrate this command, consider this input:

#! @BeginExampleSession
#! gap> S5 := SymmetricGroup(5);
#! Sym( [ 1 .. 5 ] )
#! gap> Order(S5);
#! 120
#! @EndExampleSession

This results in the following output:

gap> S5 := SymmetricGroup(5);
Sym( [ 1 .. 5 ] )
gap> Order(S5);
120

It inserts an example into the manual just as @Example would do, but all lines are commented and therefore not executed when the file is read. All lines that should be part of the example displayed in the manual have to start with an AutoDoc comment (#!). The comment will be removed, and, if the following character is a space, this space will also be removed. There is never more than one space removed. To ensure examples are correctly colored in the manual, there should be exactly one space between #! and the gap> prompt. The AutoDoc command @ExampleSession is an alias of @BeginExampleSession.

2.2-11 @BeginLog and @EndLog

Works just like the @BeginExample command, but the example will not be tested. See the GAPDoc manual for more information. The AutoDoc command @Log is an alias of @BeginLog.

2.2-12 @BeginLogSession and @EndLogSession

Works just like the @BeginExampleSession command, but the example will not be tested if manual examples are run. It is the direct analog of GAPDoc's <Log> (see GAPDoc: Log). The AutoDoc command @LogSession is an alias of @BeginLogSession.

2.2-13 @DoNotReadRestOfFile

Prevents the rest of the file from being read by the parser. Useful for unfinished or temporary files.

#! This will appear in the manual

#! @DoNotReadRestOfFile

#! This will not appear in the manual.

2.2-14 @BeginChunk name, @EndChunk, and @InsertChunk name

Text inside a @BeginChunk / @EndChunk part will not be inserted into the final documentation directly. Instead, the text is stored in an internal buffer. That chunk of text can then later on be inserted in any other place by using the @InsertChunk name command. If you do not provide an @EndChunk, the chunk ends at the end of the file.

#! @BeginChunk MyChunk
#! Hello, world.
#! @EndChunk

#! @InsertChunk MyChunk
## The text "Hello, world." is inserted right before this.

You can use this to define an example like this in one file:

#! @BeginChunk Example_Symmetric_Group
#! @BeginExample
S5 := SymmetricGroup(5);
#! Sym( [ 1 .. 5 ] )
Order(S5);
#! 120
#! @EndExample
#! @EndChunk

And then later, insert the example in a different file, like this:

#! @InsertChunk Example_Symmetric_Group

2.2-15 @BeginCode name, @EndCode, and @InsertCode name

Inserts the text between @BeginCode and @EndCode verbatim at the point where @InsertCode is called. This is useful to insert code excerpts directly into the manual.

#! @BeginCode Increment
i := i + 1;
#! @EndCode

#! @InsertCode Increment
## Code is inserted here.

2.2-16 @LatexOnly text, @BeginLatexOnly, and @EndLatexOnly

Code inserted between @BeginLatexOnly and @EndLatexOnly or after @LatexOnly is only inserted in the PDF version of the manual or worksheet. It can hold arbitrary LaTeX-commands.

#! @BeginLatexOnly
#! \include{picture.tex}
#! @EndLatexOnly

#! @LatexOnly \include{picture.tex}

2.2-17 @NotLatex text, @BeginNotLatex, and @EndNotLatex

Code inserted between @BeginNotLatex and @EndNotLatex or after @NotLatex is inserted in the HTML and text versions of the manual or worksheet, but not in the PDF version.

#! @BeginNotLatex
#! For further information see the PDF version of this manual.
#! @EndNotLatex

#! @NotLatex For further information see the PDF version of this manual.

2.3 Title page commands

The following commands can be used to add the corresponding parts to the title page of the document which generated by AutoDoc if scaffolding is enabled.

  • @Title

  • @Subtitle

  • @Version

  • @TitleComment

  • @Author

  • @Date

  • @Address

  • @Abstract

  • @Copyright

  • @Acknowledgements

  • @Colophon

Those add the following lines at the corresponding point of the title page. Please note that many of those things can be (better) extracted from the PackageInfo.g. In case you set some of those, the extracted or in scaffold defined items will be overwritten. While this is not very useful for documenting packages, they are necessary for worksheets created with AutoDocWorksheet (3.1-1), since worksheets do not have a PackageInfo.g file from which this information could be extracted.

2.4 Plain text files

Files that have the suffix .autodoc and are listed in the autodoc.files option of AutoDoc (4.1-1), resp. are contained in one of the directories listed in autodoc.scan_dirs, are treated as AutoDoc plain text files. These work exactly like AutoDoc comments, except that lines do not need to (and in fact, should not) start with #!.

2.5 Grouping

In GAPDoc, it is possible to make groups of manual items, i.e., when documenting a function, operation, etc., it is possible to group them into suitable chunks. This can be particularly useful if there are several definitions of an operation with several different argument types, all doing more or less the same to the arguments. Then their manual items can be grouped, sharing the same description and return type information. You can give a heading to the group in the manual with the @GroupTitle command; if that is not supplied, then the heading of the first manual item in the group will be used as the heading.

Note that group names are globally unique throughout the whole manual. That is, groups with the same name are in fact merged into a single group, even if they were declared in different source files. Thus you can have multiple @BeginGroup / @EndGroup pairs using the same group name, in different places, and these all will refer to the same group.

Moreover, this means that you can add items to a group via the @Group command in the AutoDoc comment of an arbitrary declaration, at any time.

The following code

#! @BeginGroup Group1
#! @GroupTitle A family of operations

#! @Description
#!  First sentence.
DeclareOperation( "FirstOperation", [ IsInt ] );

#! @Description
#!  Second sentence.
DeclareOperation( "SecondOperation", [ IsInt, IsGroup ] );

#! @EndGroup

## .. Stuff ..

#! @Description
#!  Third sentence.
#! @Group Group1
KeyDependentOperation( "ThirdOperation", IsGroup, IsInt, "prime );

produces the following:

2.5-1 A family of operations
‣ FirstOperation( arg )( operation )
‣ SecondOperation( arg1, arg2 )( operation )
‣ ThirdOperation( arg1, arg2 )( operation )

First sentence. Second sentence. Third sentence.

2.6 Level

Levels can be set to not write certain parts in the manual by default. Every entry has by default the level 0. The command @Level can be used to set the level of the following part to a higher level, for example 1, and prevent it from being printed to the manual by default. However, if one sets the level to a higher value in the autodoc option of AutoDoc, the parts will be included in the manual at the specific place.

#! This text will be printed to the manual.
#! @Level 1
#! This text will be printed to the manual if created with level 1 or higher.
#! @Level 2
#! This text will be printed to the manual if created with level 2 or higher.
#! @ResetLevel
#! This text will be printed to the manual.

2.7 Markdown-like formatting of text in AutoDoc

AutoDoc has some convenient ways to insert special format into text, like math formulas and lists. The syntax for them are inspired by Markdown and LaTeX, but do not follow them strictly. Neither are all features of the Markdown language supported. The following subsections describe what is possible.

2.7-1 Lists

One can create lists of items by beginning a new line with *, +, -, followed by one space. The first item starts the list. When items are longer than one line, the following lines have to be indented by at least two spaces. The list ends when a line which does not start a new item is not indented by two spaces. Of course lists can be nested. Here is an example:

#! The list starts in the next line
#! * item 1
#! * item 2
#!   which is a bit longer
#!   * and also contains a nested list
#!   * with two items
#! * item 3 of the outer list
#! This does not belong to the list anymore.

This is the output:
The list starts in the next line

  • item 1

  • item 2 which is a bit longer

    • and also contains a nested list

    • with two items

  • item 3 of the outer list

This does not belong to the list anymore.
The *, -, and + are fully interchangeable and can even be used mixed, but this is not recommended.

2.7-2 Math modes

One can start an inline formula with a $, and also end it with $, just like in LaTeX. This will translate into GAPDocs inline math environment. For display mode one can use $$, also like LaTeX.

#! This is an inline formula: $1+1 = 2$.
#! This is a display formula:
#! $$ \sum_{i=1}^n i. $$

produces the following output:
This is an inline formula: 1+1 = 2. This is a display formula:

\sum_{i=1}^n i.

2.7-3 Emphasize

One can emphasize text by using two asterisks (**) or two underscores (__) at the beginning and the end of the text which should be emphasized. Example:

#! **This** is very important.
#! This is __also important__.
#! **Naturally, more than one line
#! can be important.**

This produces the following output:
This is very important. This is also important. Naturally, more than one line can be important.

2.7-4 Inline code

One can mark inline code snippets by using backticks (`) at the beginning and the end of the text which should be marked as code. Example:

#! Call function `foobar()` at the start.

This produces the following output:
Call function foobar() at the start.

2.8 Deprecated commands

The following commands used to be supported, but are not anymore.

@EndSection

You can simply remove any use of this, AutoDoc ends sections automatically at the start of any new section or chapter.

@EndSubsection

You can simply remove any use of this, AutoDoc ends subsections automatically at the start of any new subsection, section or chapter.

@BeginAutoDoc and @EndAutoDoc

It suffices to prepend each declaration that is meant to be appear in the manual with a minimal AutoDoc comment #!.

@BeginSystem name, @EndSystem, and @InsertSystem name

Please use the chunk commands from subsection 2.2-14 instead.

@AutoDocPlainText and @EndAutoDocPlainText

Use .autodoc files or AutoDoc comments instead.

Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/_entities.xml0000644000175100017510000000030615074117054016331 0ustar runnerrunnerPackageName'> AutoDoc'> io'> AutoDoc-2025.10.16/doc/toggless.css0000644000175100017510000000167215074117054016174 0ustar runnerrunner/* toggless.css Frank Lübeck */ /* Using javascript we change all div.ContSect to div.ContSectOpen or div.ContSectClosed. This way the config for div.ContSect in manual.css is no longer relevant. Here we add the CSS for the new elements. */ /* This layout is based on an idea by Burkhard Höfling. */ div.ContSectClosed { text-align: left; margin-left: 1em; } div.ContSectOpen { text-align: left; margin-left: 1em; } div.ContSectOpen div.ContSSBlock { display: block; text-align: left; margin-left: 1em; } div.ContSectOpen div.ContSSBlock a { display: block; width: 100%; margin-left: 1em; } span.tocline a:hover { display: inline; background: #eeeeee; } span.ContSS a:hover { display: inline; background: #eeeeee; } span.toctoggle { font-size: 80%; display: inline-block; width: 1.2em; } span.toctoggle:hover { background-color: #aaaaaa; } AutoDoc-2025.10.16/doc/chap4_mj.html0000644000175100017510000005350415074117054016207 0ustar runnerrunner GAP (AutoDoc) - Chapter 4: AutoDoc
Goto Chapter: Top 1 2 3 4 Bib Ind

4 AutoDoc

4.1 The AutoDoc() function

4.1-1 AutoDoc
‣ AutoDoc( [packageOrDirectory][,] [optrec] )( function )

Returns: nothing

This is the main function of the AutoDoc package. It can perform any combination of the following tasks:

  1. It can (re)generate a scaffold for your package manual. That is, it can produce two XML files in GAPDoc format to be used as part of your manual: First, a file named doc/PACKAGENAME.xml (with your package's name substituted) which is used as main XML file for the package manual, i.e. this file sets the XML doctype and defines various XML entities, includes other XML files (both those generated by AutoDoc as well as additional files created by other means), tells GAPDoc to generate a table of contents and an index, and more. Secondly, it creates a file doc/title.xml containing a title page for your documentation, with information about your package (name, description, version), its authors and more, based on the data in your PackageInfo.g.

  2. It can scan your package for AutoDoc based documentation (by using AutoDoc tags and the Autodoc command. This will produce further XML files to be used as part of the package manual.

  3. It can use GAPDoc to generate PDF, text and HTML (with MathJaX enabled) documentation from the GAPDoc XML files it generated as well as additional such files provided by you. For this, it invokes MakeGAPDocDoc (GAPDoc: MakeGAPDocDoc) to convert the XML sources, and it also instructs GAPDoc to copy supplementary files (such as CSS style files) into your doc directory (see CopyHTMLStyleFiles (GAPDoc: CopyHTMLStyleFiles)).

For more information and some examples, please refer to Chapter 1.

The parameters have the following meanings:

packageOrDirectory

The purpose of this parameter is twofold: to determine the package directory in which AutoDoc will operate, and to find the metadata concerning the package being documented. The parameter is either a string, an IsDirectory object, or omitted. If it is a string, AutoDoc interprets it as the name of a package, uses the metadata of the first package known to GAP with that name, and uses the InstallationPath specified in that metadata as the package directory. If packageOrDirectory is an IsDirectory object, this is used as package directory; if the argument is omitted, then the current directory is used. In the last two cases, the specified directory must contain a PackageInfo.g file, and AutoDoc extracts all needed metadata from that. The IsDirectory form is for example useful if you have multiple versions of the package around and want to make sure the documentation of the correct version is built.

Note that when using AutoDocWorksheet (see 3.1), there is no parameter corresponding to packageOrDirectory and so the package directory is always the current directory, and there is no metadata.

optrec

optrec can be a record with some additional options. The following are currently supported:

dir

This should either be a string, in which case it must be a path relative to the specified package directory, or a Directory() object. (Thus, the only way to designate an absolute directory is with a Directory() object.) This option specifies where the package documentation (e.g. the GAPDoc XML or the manual PDF, etc.) files are stored and/or will be generated.
Default value: "doc/".

scaffold

This controls whether and how to generate scaffold XML files for the package documentation.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.scaffold is missing but the package's info record in PackageInfo.g has an AutoDoc entry. In all other cases (in particular if opt.scaffold is false), scaffolding is disabled.

If scaffolding is enabled, and PackageInfo.AutoDoc exists, then it is assumed to be a record, and its contents are used as default values for the scaffold settings.

If opt.scaffold is a record, it may contain the following entries.

includes

A list of XML files to be included in the body of the main XML file. If you specify this list and also are using AutoDoc to document your operations with AutoDoc comments, you can add _AutoDocMainFile.xml to this list to control at which point the documentation produced by AutoDoc is inserted. If you do not do this, it will be added after the last of your own XML files.

index

By default, the scaffold creates an index. If you do not want an index, set this to false.

appendix

This entry is similar to opt.scaffold.includes but is used to specify files to include after the main body of the manual, i.e. typically appendices.

bib

The name of a bibliography file, in BibTeX or XML format. If this key is not set, but there is a file doc/PACKAGENAME.bib then it is assumed that you want to use this as your bibliography.

entities

A record whose keys are taken as entity names, set to the corresponding (string) values. For example, if you pass the record SomePackage,

             rec( SomePackage := "<Package>SomePackage</Package>",
                  RELEASEYEAR := "2015" )

then the following entity definitions are added to the XML preamble:

<!ENTITY SomePackage '<Package>SomePackage</Package>'>
             <!ENTITY RELEASEYEAR '2015'>

This allows you to write &SomePackage; and &RELEASEYEAR; in your documentation, which will be replaced by respective values specified in the entities definition.

TitlePage

A record whose entries are used to embellish the generated title page for the package manual with extra information, such as a copyright statement or acknowledgments. To this end, the names of the record components are used as XML element names, and the values of the components are outputted as content of these XML elements. For example, you could pass the following record to set a custom acknowledgements text:

             rec( Acknowledgements := "Many thanks to ..." )

For a list of valid entries in the title page, please refer to the GAPDoc manual, specifically section GAPDoc: TitlePage.

MainPage

If scaffolding is enabled, by default a main XML file is generated (this is the file which contains the XML doctype and more). If you do not want this (e.g. because you have a handwritten main XML file), but still want AutoDoc to generate a title page for you, you can set this option to false

document_class

Sets the document class of the resulting PDF. The value can either be a string which has to be the name of the new document class, a list containing this string, or a list of two strings. Then the first one has to be the document class name, the second one the option string ( contained in [ ] ) in LaTeX.

latex_header_file

Replaces the standard header from GAPDoc completely with the header in this LaTeX file. Please be careful here, and look at GAPDoc's latexheader.tex file for an example.

autodoc

This controls whether and how to generate additional XML documentation files by scanning for AutoDoc documentation comments.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.autodoc is missing but the package depends (directly) on the AutoDoc package. In all other cases (in particular if opt.autodoc is false), this feature is disabled.

If opt.autodoc is a record, it may contain the following entries.

files

A list of files (given by paths relative to the package directory) to be scanned for AutoDoc documentation comments. Usually it is more convenient to use autodoc.scan_dirs, see below.

scan_dirs

A list of subdirectories of the package directory (given as relative paths) which AutoDoc then scans for .gi, .gd, .g, and .autodoc files; all of these files are then scanned for AutoDoc documentation comments.
Default value: [ ".", "gap", "lib", "examples", "examples/doc" ].

level

This defines the level of the created documentation. The default value is 0. When parts of the manual are declared with a higher value they will not be printed into the manual.

gapdoc

This controls whether and how to invoke GAPDoc to create HTML, PDF and text files from your various XML files.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.gapdoc is missing. In all other cases (in particular if opt.gapdoc is false), this feature is disabled.

If opt.gapdoc is a record, it may contain the following entries.

main

The name of the main XML file of the package manual. This exists primarily to support packages with existing manual which use a filename here which differs from the default. In particular, specifying this is unnecessary when using scaffolding.
Default value: PACKAGENAME.xml.

files

A list of files (given by paths relative to the package directory) to be scanned for GAPDoc documentation comments. Usually it is more convenient to use gapdoc.scan_dirs, see below.

scan_dirs

A list of subdirectories of the package directory (given as relative paths) which AutoDoc then scans for .gi, .gd and .g files; all of these files are then scanned for GAPDoc documentation comments.
Default value: [ ".", "gap", "lib", "examples", "examples/doc" ].

LaTeXOptions

Must be a record with entries which can be understood by SetGapDocLaTeXOptions (GAPDoc: SetGapDocLaTeXOptions). Each entry can be a string, which will be given to GAPDoc directly, or a list containing of two entries: The first one must be the string "file", the second one a filename. This file will be read and then its content is passed to GAPDoc as option with the name of the entry.

gap_root_relative_path

Either a boolean, or a string containing a relative path. By default (if this option is not set, or is set to false), references in the generated documentation referring to external documentation (such as the GAP manual) are encoded using absolute paths. This is fine as long as the documentation stays on only a single computer, but is problematic when preparing documentation that should be used on multiple computers, e.g., when creating a distribution archive of a GAP package.
Thus, if a relative path is provided via this option (or if it is set to true, in which case the relative path ../../.. is used), then AutoDoc and GAPDoc attempt to replace all absolute paths in references to GAP manuals by paths based on this relative path.

On a technical level, AutoDoc passes the relative path to the gaproot parameter of MakeGAPDocDoc (GAPDoc: MakeGAPDocDoc)

extract_examples

Either true or a record. If set to true, then all manual examples are extracted and placed into files tst/PACKAGENAME01.tst, tst/PACKAGENAME02.tst, ... and so on, with one file for each chapter. For chapters with no examples, no file is created.

As a record, the entry can have the following entries itself, to specify some options.

units

This controls how examples are grouped into files. Recognized values are "Chapter" (default), "Section", "Subsection" or "Single". Depending on the value, one file is created for each chapter, each section, each subsection or each example. For all other values only a single file is created.

On a technical level, AutoDoc passes the value to the units parameter of ExtractExamples (GAPDoc: ExtractExamples).

skip_empty_in_numbering

If set to true (the default), the generated files use filenames with strictly sequential numbering; that means that if chapter 1 (or whatever units are being used) contains no examples but chapter 2 does, then the examples for chapter 2 are put into the file tst/PACKAGENAME01.tst. If this option is set to false, then the chapter numbers are used to generate the filenames; so the examples for chapter 2 would be put into the file tst/PACKAGENAME02.tst.

4.1-2 InfoAutoDoc
‣ InfoAutoDoc( info class )

Info class for the AutoDoc package. Set this to 0 to suppress info messages, 1 to allow most messages, and 2 to allow all messages including those that contain file paths.

This can be set by calling, for example, SetInfoLevel(InfoPackageManager, 0). Default value 1.

4.2 Examples

Some basic examples for using AutoDoc were already shown in Chapter 1.

Goto Chapter: Top 1 2 3 4 Bib Ind

generated by GAPDoc2HTML

AutoDoc-2025.10.16/doc/chapInd.txt0000644000175100017510000000405015074117054015733 0ustar runnerrunner Index @Arguments args 2.1-3 @BeginChunk name 2.2-14 @BeginCode name 2.2-15 @BeginExample 2.2-9 @BeginExampleSession 2.2-10 @BeginGroup 2.2-4 @BeginLatexOnly 2.2-16 @BeginLog 2.2-11 @BeginLogSession 2.2-12 @BeginNotLatex 2.2-17 @Chapter 2.2-1 @ChapterInfo 2.1-8 @ChapterLabel 2.2-1 @ChapterTitle 2.2-1 @Description descr 2.1-1 @DoNotReadRestOfFile 2.2-13 @EndChunk 2.2-14 @InsertChunk name 2.2-14 @EndCode 2.2-15 @EndExample 2.2-9 @EndExampleSession 2.2-10 @EndGroup 2.2-5 @EndLatexOnly 2.2-16 @EndLog 2.2-11 @EndLogSession 2.2-12 @EndNotLatex 2.2-17 @Group grpname 2.1-4 @GroupTitle 2.2-6 @InsertCode name 2.2-15 @Label label 2.1-5 @LatexOnly text 2.2-16 @Level 2.2-7 @NotLatex text 2.2-17 @ResetLevel 2.2-8 @Returns ret_val 2.1-2 @Section 2.2-2 @SectionLabel 2.2-2 @SectionTitle 2.2-2 @Subsection 2.2-3 @SubsectionLabel 2.2-3 @SubsectionTitle 2.2-3 1.3-3 1.3-3 AProperty, for IsObject 2.1-7 testlabel 2.1-6 AutoDoc 4.1-1 AutoDocWorksheet 3.1-1 1.3-3 1.3-3 1.3-3 FirstOperation, for IsInt 2.5-1 InfoAutoDoc 4.1-2 1.3-3 makedoc.g 1.1 1.3-3 SecondOperation, for IsInt, IsGroup 2.5-1 ThirdOperation, for IsGroup, IsInt 2.5-1 ------------------------------------------------------- AutoDoc-2025.10.16/read.g0000644000175100017510000000076315074117054014151 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later ReadPackage( "AutoDoc", "gap/ToolFunctions.gi" ); ReadPackage( "AutoDoc", "gap/DocumentationTree.gi" ); ReadPackage( "AutoDoc", "gap/Parser.gi" ); ReadPackage( "AutoDoc", "gap/AutoDocMainFunction.gi" ); ReadPackage( "AutoDoc", "gap/Magic.gi" ); ReadPackage( "AutoDoc", "gap/Markdown.gi" ); AutoDoc-2025.10.16/LICENSE0000644000175100017510000003646315074117054014101 0ustar runnerrunnerThe AutoDoc package is free software; you can redistribute and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The AutoDoc package 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. Version 2 of the GNU General Public License follows. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS AutoDoc-2025.10.16/makedoc.g0000644000175100017510000000107415074117054014635 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later LoadPackage("AutoDoc"); AutoDoc( rec( autodoc := true, gapdoc := rec( LaTeXOptions := rec( EarlyExtraPreamble := """ \usepackage{a4wide} \newcommand{\bbZ}{\mathbb{Z}} """ ) ), scaffold := rec( includes := [ "Tutorials.xml", "Comments.xml" ], bib := "bib.xml", ) )); AutoDoc-2025.10.16/TODO0000644000175100017510000000256215074117054013555 0ustar runnerrunner todo: Please create a (maybe random) test suite for invoking the AutoDoc command. We already have a nice testsuite for all comments possible, although Mohamed always seems to find a way to crash them into void. IDEAS: We need to collect all possible combinations to invoke the AutoDoc command. It should be no problem to design a loop in GAP, but checking the output for differences might be painful. Also, what to do with entities? The following is a list of possible valid inputs for the different option records, which might produce the desired output in all combinations. However, Murphys Law tells us that at least one of them will break anyway. So good luck. dir: * doc * nothing -> Both should produce the same output. scaffold: * includes * appendix * bib * TitlePage: + ... Stuff, see GAPDoc. * document_class * latex_header_file * gapdoc_latex_options Documenting C/C++/C# with AutoDoc: Use comments of C/C++/C# before AutoDoc hashes, i.e. // #!. You can also begin a whole comment section with /* and then end it with */. Please don't put a AutoDoc hash in the same line as /* and */. If using the @AutoDocPlainText command, you can get rid of the supersticious hashes. Please do *NOT* use the comment syntax with an asterisk at the beginning of every line, it will mess up the markdown extension! AutoDoc-2025.10.16/README.md0000644000175100017510000000252215074117054014340 0ustar runnerrunner[![CI](https://github.com/gap-packages/AutoDoc/actions/workflows/CI.yml/badge.svg)](https://github.com/gap-packages/AutoDoc/actions/workflows/CI.yml) [![Code Coverage](https://codecov.io/github/gap-packages/AutoDoc/coverage.svg?branch=master&token=)](https://codecov.io/gh/gap-packages/AutoDoc) # AutoDoc: A GAP package to help creating a GAPDoc documentation. AutoDoc is a package for the [GAP](https://www.gap-system.org) computer algebra system. It is meant to simplify the creation of reference manuals for GAP packages. It makes it possible to create documentation from source code comments, without writing XML files. It is not a substitute for GAPDoc, but rather builds on GAPDoc, by generating XML input for the latter. As such, you can combine an existing GAPDoc manual with AutoDoc. ## Using AutoDoc Please consult the AutoDoc manual for information on how to use it. It is accessible via the builtin help system of GAP. In addition you can find the manual for the latest AutoDoc version online at ## Support Bug reports and other feedback are welcome. The latest version of this package can be found at ## Copyright and licensing Please consult the LICENSE and COPYRIGHT file you should have received as part of this package for details. AutoDoc-2025.10.16/makefile0000644000175100017510000000024515074117054014561 0ustar runnerrunnerall: doc doc: doc/manual.six doc/manual.six: makedoc.g PackageInfo.g doc/*.xml gap/*.gd gap/*.gi gap makedoc.g clean: (cd doc ; ./clean) .PHONY: all doc clean AutoDoc-2025.10.16/tst/0000755000175100017510000000000015074117054013672 5ustar runnerrunnerAutoDoc-2025.10.16/tst/manual.expected/0000755000175100017510000000000015074117054016747 5ustar runnerrunnerAutoDoc-2025.10.16/tst/manual.expected/_Chapter_AutoDoc_worksheets.xml0000644000175100017510000000164315074117054025116 0ustar runnerrunner AutoDoc worksheets
Worksheets The intention of these function is to create stand-alone pdf and html files using AutoDoc without having them associated to a package. It uses the same optional records as the &AutoDoc; command itself, but instead of a package name there should be a filename or a list of filenames containing AutoDoc text from which the documents are created. Please see the &AutoDoc; command for more information about this and have a look at for a simple worksheet example.
AutoDoc-2025.10.16/tst/manual.expected/_Chapter_AutoDoc.xml0000644000175100017510000004212415074117054022637 0ustar runnerrunner AutoDoc
The AutoDoc() function nothing This is the main function of the &AutoDoc; package. It can perform any combination of the following tasks: It can (re)generate a scaffold for your package manual. That is, it can produce two XML files in &GAPDoc; format to be used as part of your manual: First, a file named doc/PACKAGENAME.xml (with your package's name substituted) which is used as main XML file for the package manual, i.e. this file sets the XML doctype and defines various XML entities, includes other XML files (both those generated by &AutoDoc; as well as additional files created by other means), tells &GAPDoc; to generate a table of contents and an index, and more. Secondly, it creates a file doc/title.xml containing a title page for your documentation, with information about your package (name, description, version), its authors and more, based on the data in your PackageInfo.g. It can scan your package for &AutoDoc; based documentation (by using &AutoDoc; tags and the Autodoc command. This will produce further XML files to be used as part of the package manual. It can use &GAPDoc; to generate PDF, text and HTML (with MathJaX enabled) documentation from the &GAPDoc; XML files it generated as well as additional such files provided by you. For this, it invokes to convert the XML sources, and it also instructs &GAPDoc; to copy supplementary files (such as CSS style files) into your doc directory (see ). For more information and some examples, please refer to Chapter .

The parameters have the following meanings: packageOrDirectory The purpose of this parameter is twofold: to determine the package directory in which &AutoDoc; will operate, and to find the metadata concerning the package being documented. The parameter is either a string, an IsDirectory object, or omitted. If it is a string, &AutoDoc; interprets it as the name of a package, uses the metadata of the first package known to &GAP; with that name, and uses the InstallationPath specified in that metadata as the package directory. If packageOrDirectory is an IsDirectory object, this is used as package directory; if the argument is omitted, then the current directory is used. In the last two cases, the specified directory must contain a PackageInfo.g file, and &AutoDoc; extracts all needed metadata from that. The IsDirectory form is for example useful if you have multiple versions of the package around and want to make sure the documentation of the correct version is built.

Note that when using AutoDocWorksheet (see ), there is no parameter corresponding to packageOrDirectory and so the package directory is always the current directory, and there is no metadata. optrec optrec can be a record with some additional options. The following are currently supported: dir This should either be a string, in which case it must be a path relative to the specified package directory, or a Directory() object. (Thus, the only way to designate an absolute directory is with a Directory() object.) This option specifies where the package documentation (e.g. the &GAPDoc; XML or the manual PDF, etc.) files are stored and/or will be generated.
Default value: "doc/".
scaffold This controls whether and how to generate scaffold XML files for the package documentation.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.scaffold is missing but the package's info record in PackageInfo.g has an AutoDoc entry. In all other cases (in particular if opt.scaffold is false), scaffolding is disabled.

If scaffolding is enabled, and PackageInfo.AutoDoc exists, then it is assumed to be a record, and its contents are used as default values for the scaffold settings.

If opt.scaffold is a record, it may contain the following entries.

includes A list of XML files to be included in the body of the main XML file. If you specify this list and also are using &AutoDoc; to document your operations with &AutoDoc; comments, you can add _AutoDocMainFile.xml to this list to control at which point the documentation produced by &AutoDoc; is inserted. If you do not do this, it will be added after the last of your own XML files. index By default, the scaffold creates an index. If you do not want an index, set this to false. appendix This entry is similar to opt.scaffold.includes but is used to specify files to include after the main body of the manual, i.e. typically appendices. bib The name of a bibliography file, in BibTeX or XML format. If this key is not set, but there is a file doc/PACKAGENAME.bib then it is assumed that you want to use this as your bibliography. entities A record whose keys are taken as entity names, set to the corresponding (string) values. For example, if you pass the record SomePackage,

SomePackage", RELEASEYEAR := "2015" )]]> then the following entity definitions are added to the XML preamble: SomePackage'> ]]> This allows you to write &SomePackage; and &RELEASEYEAR; in your documentation, which will be replaced by respective values specified in the entities definition. TitlePage A record whose entries are used to embellish the generated title page for the package manual with extra information, such as a copyright statement or acknowledgments. To this end, the names of the record components are used as XML element names, and the values of the components are outputted as content of these XML elements. For example, you could pass the following record to set a custom acknowledgements text: For a list of valid entries in the title page, please refer to the &GAPDoc; manual, specifically section . MainPage If scaffolding is enabled, by default a main XML file is generated (this is the file which contains the XML doctype and more). If you do not want this (e.g. because you have a handwritten main XML file), but still want &AutoDoc; to generate a title page for you, you can set this option to false document_class Sets the document class of the resulting PDF. The value can either be a string which has to be the name of the new document class, a list containing this string, or a list of two strings. Then the first one has to be the document class name, the second one the option string ( contained in [ ] ) in &LaTeX;. latex_header_file Replaces the standard header from &GAPDoc; completely with the header in this &LaTeX; file. Please be careful here, and look at &GAPDoc;'s latexheader.tex file for an example. autodoc This controls whether and how to generate additional XML documentation files by scanning for &AutoDoc; documentation comments.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.autodoc is missing but the package depends (directly) on the &AutoDoc; package. In all other cases (in particular if opt.autodoc is false), this feature is disabled.

If opt.autodoc is a record, it may contain the following entries.

files A list of files (given by paths relative to the package directory) to be scanned for &AutoDoc; documentation comments. Usually it is more convenient to use autodoc.scan_dirs, see below. scan_dirs A list of subdirectories of the package directory (given as relative paths) which &AutoDoc; then scans for .gi, .gd, .g, and .autodoc files; all of these files are then scanned for &AutoDoc; documentation comments.
Default value: [ ".", "gap", "lib", "examples", "examples/doc" ].
level This defines the level of the created documentation. The default value is 0. When parts of the manual are declared with a higher value they will not be printed into the manual.
gapdoc This controls whether and how to invoke &GAPDoc; to create HTML, PDF and text files from your various XML files.

The value should be either true, false or a record. If it is a record or true (the latter is equivalent to specifying an empty record), then this feature is enabled. It is also enabled if opt.gapdoc is missing. In all other cases (in particular if opt.gapdoc is false), this feature is disabled.

If opt.gapdoc is a record, it may contain the following entries.

main The name of the main XML file of the package manual. This exists primarily to support packages with existing manual which use a filename here which differs from the default. In particular, specifying this is unnecessary when using scaffolding.
Default value: PACKAGENAME.xml.
files A list of files (given by paths relative to the package directory) to be scanned for &GAPDoc; documentation comments. Usually it is more convenient to use gapdoc.scan_dirs, see below. scan_dirs A list of subdirectories of the package directory (given as relative paths) which &AutoDoc; then scans for .gi, .gd and .g files; all of these files are then scanned for &GAPDoc; documentation comments.
Default value: [ ".", "gap", "lib", "examples", "examples/doc" ].
LaTeXOptions Must be a record with entries which can be understood by . Each entry can be a string, which will be given to &GAPDoc; directly, or a list containing of two entries: The first one must be the string "file", the second one a filename. This file will be read and then its content is passed to &GAPDoc; as option with the name of the entry. gap_root_relative_path Either a boolean, or a string containing a relative path. By default (if this option is not set, or is set to false), references in the generated documentation referring to external documentation (such as the &GAP; manual) are encoded using absolute paths. This is fine as long as the documentation stays on only a single computer, but is problematic when preparing documentation that should be used on multiple computers, e.g., when creating a distribution archive of a &GAP; package.
Thus, if a relative path is provided via this option (or if it is set to true, in which case the relative path ../../.. is used), then &AutoDoc; and &GAPDoc; attempt to replace all absolute paths in references to &GAP; manuals by paths based on this relative path.

On a technical level, &AutoDoc; passes the relative path to the gaproot parameter of

extract_examples Either true or a record. If set to true, then all manual examples are extracted and placed into files tst/PACKAGENAME01.tst, tst/PACKAGENAME02.tst, ... and so on, with one file for each chapter. For chapters with no examples, no file is created.

As a record, the entry can have the following entries itself, to specify some options. units This controls how examples are grouped into files. Recognized values are "Chapter" (default), "Section", "Subsection" or "Single". Depending on the value, one file is created for each chapter, each section, each subsection or each example. For all other values only a single file is created.

On a technical level, &AutoDoc; passes the value to the units parameter of . skip_empty_in_numbering If set to true (the default), the generated files use filenames with strictly sequential numbering; that means that if chapter 1 (or whatever units are being used) contains no examples but chapter 2 does, then the examples for chapter 2 are put into the file tst/PACKAGENAME01.tst. If this option is set to false, then the chapter numbers are used to generate the filenames; so the examples for chapter 2 would be put into the file tst/PACKAGENAME02.tst.

Info class for the AutoDoc package. Set this to 0 to suppress info messages, 1 to allow most messages, and 2 to allow all messages including those that contain file paths.

This can be set by calling, for example, SetInfoLevel(InfoPackageManager, 0). Default value 1.

Examples

Some basic examples for using AutoDoc were already shown in Chapter .

AutoDoc-2025.10.16/tst/manual.expected/_Chunks.xml0000644000175100017510000000000015074117054021051 0ustar runnerrunnerAutoDoc-2025.10.16/tst/manual.expected/_AutoDocMainFile.xml0000644000175100017510000000026715074117054022600 0ustar runnerrunner <#Include SYSTEM "_Chapter_AutoDoc_worksheets.xml"> <#Include SYSTEM "_Chapter_AutoDoc.xml"> AutoDoc-2025.10.16/tst/testall.g0000644000175100017510000000027515074117054015516 0ustar runnerrunnerLoadPackage( "AutoDoc" ); SetInfoLevel(InfoAutoDoc, 1); SetInfoLevel(InfoGAPDoc, 0); TestDirectory( DirectoriesPackageLibrary("AutoDoc", "tst"), rec(exitGAP := true ) ); FORCE_QUIT_GAP(1); AutoDoc-2025.10.16/tst/worksheets/0000755000175100017510000000000015074117054016070 5ustar runnerrunnerAutoDoc-2025.10.16/tst/worksheets/general.expected/0000755000175100017510000000000015074117054021305 5ustar runnerrunnerAutoDoc-2025.10.16/tst/worksheets/general.expected/General_Test.xml0000644000175100017510000000046615074117054024411 0ustar runnerrunner ] > <#Include SYSTEM "title.xml"> <#Include SYSTEM "_AutoDocMainFile.xml"> AutoDoc-2025.10.16/tst/worksheets/general.expected/_Chapter_labelChapter.xml0000644000175100017510000000067715074117054026234 0ustar runnerrunner Label test chapter This is dummy text

Label test section This is dummy text

Label test subsection This is dummy text

AutoDoc-2025.10.16/tst/worksheets/general.expected/_Chunks.xml0000644000175100017510000000042315074117054023420 0ustar runnerrunner<#GAPDoc Label="MyChunk"> Hello, world. This line is indented! <#/GAPDoc> <#GAPDoc Label="MyCode"> 2"); fi; ]]> <#/GAPDoc> AutoDoc-2025.10.16/tst/worksheets/general.expected/_AutoDocMainFile.xml0000644000175100017510000000026515074117054025134 0ustar runnerrunner <#Include SYSTEM "_Chapter_SomeChapter.xml"> <#Include SYSTEM "_Chapter_labelChapter.xml"> AutoDoc-2025.10.16/tst/worksheets/general.expected/tst/0000755000175100017510000000000015074117054022117 5ustar runnerrunnerAutoDoc-2025.10.16/tst/worksheets/general.expected/tst/general_test01.tst0000644000175100017510000000141515074117054025471 0ustar runnerrunner# General Test, chapter 1 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("general_test01.tst"); # _Chapter_SomeChapter.xml:8-13 gap> S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Size(S5); 120 # _Chapter_SomeChapter.xml:17-25 gap> A5 := AlternatingGroup(5); Alt( [ 1 .. 5 ] ) gap> Size(A5); 60 gap> # Test whether ]]> can be used safely gap> [[2]]>[[1]]; true # gap> STOP_TEST("general_test01.tst", 1); AutoDoc-2025.10.16/tst/worksheets/general.expected/title.xml0000644000175100017510000000030015074117054023141 0ustar runnerrunner General Test 30 August 2018 AutoDoc-2025.10.16/tst/worksheets/general.expected/_entities.xml0000644000175100017510000000007115074117054024010 0ustar runnerrunnerGeneral_Test'> AutoDoc-2025.10.16/tst/worksheets/general.expected/_Chapter_SomeChapter.xml0000644000175100017510000001311115074117054026043 0ustar runnerrunner SomeChapter This is dummy text S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Size(S5); 120 ]]> Some text between two examples A5 := AlternatingGroup(5); Alt( [ 1 .. 5 ] ) gap> Size(A5); 60 gap> # Test whether ]]]]> can be used safely gap> [[2]]]]>[[1]]; true ]]> And we wrap up with some dummy text
Some categories Intro text true or false

true or false

true or false

Let's wrap up with something, though.

SomeSection Some test just inside a section. SomeSubsection This is a subsection! MarkDown support

We can use test some markdown features here: This is a list item. This is a subitem We can also use math mode here: a^2+b^2=c^2. This is emphasized text in a list item. This is also emphasized text in a list item. This is inline code in a list item.

All of this can also be used outside of a list.

Testing various kinds of documentation true or false A category true or false A collection category over the category we just created; A collection category over the category we just created; A collection category over the category we just created; A representation An attribute true or false A property An operation A cConstructor A global function A global variable A global name A filter An info class A key dependent operation
Testing the group commands A family of operations First sentence. Second sentence. Third sentence.
Testing chunks This test comes after the chunk is declared, but before it is inserted. <#Include Label="MyChunk"> The text "Hello, world." is inserted right before this.
Testing code chunks This test comes after the code chunk is declared, but before it is inserted. <#Include Label="MyCode"> The text "Hello, world." is inserted right before this.
AutoDoc-2025.10.16/tst/worksheets/general.sheet/0000755000175100017510000000000015074117054020614 5ustar runnerrunnerAutoDoc-2025.10.16/tst/worksheets/general.sheet/worksheet.g0000644000175100017510000001234715074117054023006 0ustar runnerrunner############################################################################# ## ## AutoDoc package ## ############################################################################# Print( "Pretend this is a code file.\n" ); Print( "(Even though we never use it that way.\n" ); #! @Title General Test #! @Date 30/08/2018 #! @Chapter SomeChapter #! This is dummy text #! @BeginExampleSession #! gap> S5 := SymmetricGroup(5); #! Sym( [ 1 .. 5 ] ) #! gap> Size(S5); #! 120 #! @EndExampleSession #! Some text between two examples #! @BeginExampleSession #! gap> A5 := AlternatingGroup(5); #! Alt( [ 1 .. 5 ] ) #! gap> Size(A5); #! 60 #! gap> # Test whether ]]> can be used safely #! gap> [[2]]>[[1]]; #! true #! @EndExampleSession #! And we wrap up with some dummy text ############################################################################# #! @Section Some categories #! Intro text DeclareCategory("MyThings", IsObject); DeclareCategoryCollections("MyThings"); DeclareCategoryCollections("MyThingsCollection"); # Now here is some text with a bunch of &!$%*!/ weird things in it. But that # should be OK, nothing should end up in a weird place. #! Let's wrap up with something, though. ############################################################################# #! @Section SomeSection #! Some test just inside a section. #! @Subsection SomeSubsection #! This is a subsection! #! @Subsection MarkDown support #! #! We can use test some markdown features here: #! * This is a list item. #! * This is a subitem #! * We can also use math mode here: $a^2+b^2=c^2$. #! * This is __emphasized__ text in a list item. #! * This is also **emphasized** text in a list item. #! * This is `inline code` in a list item. #! #! All of this can **also** be __used__ outside of a `list`. #! @LatexOnly This text will only appear in the \LaTeX version. #! @BeginLatexOnly #! This text will only appear in the \LaTeX version, too. #! @EndLatexOnly #! @NotLatex This text will only appear in the HTML version and the text version. #! @BeginNotLatex #! This text will only appear in the HTML version and the text version, too. #! @EndNotLatex ############################################################################# #! @Section Testing various kinds of documentation #! @Description #! A category DeclareCategory( "SomeCategory", IsObject ); #! @Description #! A collection category over the category we just created; # will appear as SomeCategoryCollection DeclareCategoryCollections( "SomeCategory" ); #! @Description #! A collection category over the category we just created; # will appear as SomeCategoryCollColl DeclareCategoryCollections( "SomeCategoryCollection" ); #! @Description #! A collection category over the category we just created; # will appear as SomeCategoryCollCollColl DeclareCategoryCollections( "SomeCategoryCollColl" ); #! @Description #! A representation DeclareRepresentation( "SomeRepresentation", IsAttributeStoringRep, [] ); #! @Description #! An attribute DeclareAttribute( "SomeAttribute", IsGroup ); #! @Description #! A property DeclareProperty( "SomeProperty", IsGroup ); #! @Description #! An operation DeclareOperation( "SomeOperation", [ IsInt, IsGroup ] ); #! @Description #! A cConstructor DeclareConstructor( "SomeConstructor", [ IsGroup, IsInt ] ); #! @Description #! A global function DeclareGlobalFunction( "SomeGlobalFunction" ); #! @Description #! A global variable DeclareGlobalVariable( "SomeGlobalVariable" ); #! @Description #! A global name DeclareGlobalName( "SomeGlobalName" ); #! @Description #! A filter DeclareFilter( "SomeFilter" ); #! @Description #! An info class DeclareInfoClass( "SomeInfoClass"); #! @Description #! A key dependent operation KeyDependentOperation( "SomeKeyDependentOperation", IsGroup, IsInt, "prime" ); ############################################################################# #! @Section Testing the group commands #! @BeginGroup Group1 #! @GroupTitle A family of operations #! @Description #! First sentence. DeclareOperation( "FirstOperation", [ IsInt ] ); #! @Description #! Second sentence. DeclareOperation( "SecondOperation", [ IsInt, IsGroup ] ); #! @EndGroup ## .. Stuff .. #! @Description #! Third sentence. #! @Group Group1 DeclareOperation( "ThirdOperation", [ IsGroup, IsInt ] ); ############################################################################# #! @Section Testing chunks #! @BeginChunk MyChunk #! Hello, world. #! This line is indented! #! @EndChunk #! This test comes after the chunk is declared, but before it is inserted. #! @InsertChunk MyChunk #! The text "Hello, world." is inserted right before this. ############################################################################# #! @Section Testing code chunks #! @BeginCode MyCode #! Hello, world. x := 1 + 1; if x = 2 then Print("1 + 1 = 2 holds, all is good\n"); else Error("1+1 <> 2"); fi; #! @EndCode #! This test comes after the code chunk is declared, but before it is inserted. #! @InsertCode MyCode #! The text "Hello, world." is inserted right before this. #! @Chapter Label test chapter #! @ChapterLabel labelChapter #! This is dummy text #! #! @Section Label test section #! @SectionLabel labelSection #! This is dummy text #! #! @Subsection Label test subsection #! @SubsectionLabel labelSubsection #! This is dummy text AutoDoc-2025.10.16/tst/worksheets/autoplain.sheet/0000755000175100017510000000000015074117054021173 5ustar runnerrunnerAutoDoc-2025.10.16/tst/worksheets/autoplain.sheet/plain.autodoc0000644000175100017510000000074015074117054023657 0ustar runnerrunner@Title Plain file.autodoc Test @Date 2018-08-30 @Chapter Test Does AutoDoc have a way to allow that header block not to appear in the documentation generated from a .autodoc file like this? @BeginExampleSession gap> S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Size(S5); 120 @EndExampleSession Some text between two examples @BeginExampleSession gap> A5 := AlternatingGroup(5); Alt( [ 1 .. 5 ] ) gap> Size(A5); 60 @EndExampleSession And we wrap up with some dummy text AutoDoc-2025.10.16/tst/worksheets/autoplain.expected/0000755000175100017510000000000015074117054021664 5ustar runnerrunnerAutoDoc-2025.10.16/tst/worksheets/autoplain.expected/_Chapter_Test.xml0000644000175100017510000000106515074117054025134 0ustar runnerrunner Test Does AutoDoc have a way to allow that header block not to appear in the documentation generated from a .autodoc file like this? S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Size(S5); 120 ]]> Some text between two examples A5 := AlternatingGroup(5); Alt( [ 1 .. 5 ] ) gap> Size(A5); 60 ]]> And we wrap up with some dummy text AutoDoc-2025.10.16/tst/worksheets/autoplain.expected/_Chunks.xml0000644000175100017510000000000015074117054023766 0ustar runnerrunnerAutoDoc-2025.10.16/tst/worksheets/autoplain.expected/_AutoDocMainFile.xml0000644000175100017510000000020015074117054025500 0ustar runnerrunner <#Include SYSTEM "_Chapter_Test.xml"> AutoDoc-2025.10.16/tst/worksheets/autoplain.expected/tst/0000755000175100017510000000000015074117054022476 5ustar runnerrunnerAutoDoc-2025.10.16/tst/worksheets/autoplain.expected/tst/plain_file.autodoc_test01.tst0000644000175100017510000000133615074117054030174 0ustar runnerrunner# Plain file.autodoc Test, chapter 1 # # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # gap> START_TEST("plain_file.autodoc_test01.tst"); # _Chapter_Test.xml:9-14 gap> S5 := SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> Size(S5); 120 # _Chapter_Test.xml:18-23 gap> A5 := AlternatingGroup(5); Alt( [ 1 .. 5 ] ) gap> Size(A5); 60 # gap> STOP_TEST("plain_file.autodoc_test01.tst", 1); AutoDoc-2025.10.16/tst/worksheets/autoplain.expected/title.xml0000644000175100017510000000031315074117054023524 0ustar runnerrunner Plain file.autodoc Test 30 August 2018 AutoDoc-2025.10.16/tst/worksheets/autoplain.expected/_entities.xml0000644000175100017510000000011715074117054024370 0ustar runnerrunnerPlain_file.autodoc_Test'> AutoDoc-2025.10.16/tst/worksheets/autoplain.expected/Plain_file.autodoc_Test.xml0000644000175100017510000000050115074117054027100 0ustar runnerrunner ] > <#Include SYSTEM "title.xml"> <#Include SYSTEM "_AutoDocMainFile.xml"> AutoDoc-2025.10.16/tst/worksheets/update.sh0000755000175100017510000000050415074117054017710 0ustar runnerrunner#!/bin/sh # This script copies actual files over to the expected files; # this is useful when adding new tests. for actual in *.actual ; do expected="$(basename $actual .actual).expected" rm -rf $expected mkdir $expected cp $actual/*.xml $expected/ mkdir $expected/tst cp $actual/tst/*.tst $expected/tst/ done AutoDoc-2025.10.16/tst/worksheets.tst0000644000175100017510000000074215074117054016627 0ustar runnerrunner# # test worksheets # gap> START_TEST( "worksheets.tst" ); # gap> AUTODOC_TestWorkSheet("general"); #I Extracting manual examples for General Test package ... #I 2 chapters detected #I Chapter 1... #I extracted 2 examples #I Chapter 2... #I no examples # gap> AUTODOC_TestWorkSheet("autoplain"); #I Extracting manual examples for Plain file.autodoc Test package ... #I 1 chapters detected #I Chapter 1... #I extracted 2 examples # # gap> STOP_TEST( "worksheets.tst" ); AutoDoc-2025.10.16/tst/misc.tst0000644000175100017510000000247015074117054015364 0ustar runnerrunner# # test miscellaneous stuff # gap> START_TEST( "misc.tst" ); # AUTODOC_SetIfMissing gap> r:=rec(); rec( ) gap> AUTODOC_SetIfMissing(r, "foo", 1); gap> r; rec( foo := 1 ) gap> AUTODOC_SetIfMissing(r, "foo", 2); gap> r; rec( foo := 1 ) # # AUTODOC_FormatDate # # gap> AUTODOC_FormatDate(2019); "2019" gap> AUTODOC_FormatDate(2019, 3); "March 2019" gap> AUTODOC_FormatDate(2019, 3, 1); "1 March 2019" gap> AUTODOC_FormatDate("2019", "3", "1"); "1 March 2019" gap> AUTODOC_FormatDate("2019-03-01"); "1 March 2019" gap> AUTODOC_FormatDate("01/03/2019"); "1 March 2019" gap> AUTODOC_FormatDate(rec(year:=2019)); "2019" gap> AUTODOC_FormatDate(rec(year:=2019, month:=3)); "March 2019" gap> AUTODOC_FormatDate(rec(year:=2019, month:=3, day:=1)); "1 March 2019" gap> AUTODOC_FormatDate(rec(year:="2019", month:="3", day:="1")); "1 March 2019" # error handling gap> AUTODOC_FormatDate(); Error, Invalid arguments gap> AUTODOC_FormatDate(2019, 3, 40); Error, must be an integer in the range [1..31], or a string representing\ such an integer gap> AUTODOC_FormatDate(2019, 13, 1); Error, must be an integer in the range [1..12], or a string representi\ ng such an integer gap> AUTODOC_FormatDate(fail, 3, 1); Error, must be an integer >= 2000, or a string representing such an int\ eger # gap> STOP_TEST( "misc.tst" ); AutoDoc-2025.10.16/tst/dogfood.tst0000644000175100017510000000351615074117054016054 0ustar runnerrunner############################################################################# ## ## AutoDoc package ## ## Test the behavior of AutoDoc by generating its own manual ## ## Copyright 2018 ## Contributed by Glen Whitney, studioinfinity.org ## ## Licensed under the GPL 2 or later. ## ############################################################################# gap> START_TEST( "dogfood.tst" ); # need IO package for ChangeDirectoryCurrent gap> LoadPackage("io", false); true # temporarily change info levels to suppress all GAPDoc output gap> oldGAPDocLevel := InfoLevel( InfoGAPDoc );; gap> oldWarningLevel := InfoLevel( InfoWarning );; gap> SetInfoLevel( InfoGAPDoc, 0 ); gap> SetInfoLevel( InfoWarning, 0 ); # change into the package directory gap> olddir := AUTODOC_CurrentDirectory();; gap> pkgdir := DirectoriesPackageLibrary( "AutoDoc", "");; gap> ChangeDirectoryCurrent(Filename(pkgdir, "")); true # regenerate the manual using AutoDoc gap> Read("makedoc.g"); # restore info levels and current directory gap> SetInfoLevel( InfoGAPDoc, oldGAPDocLevel ); gap> SetInfoLevel( InfoWarning, oldWarningLevel ); gap> ChangeDirectoryCurrent(olddir); true # prepare to compare the output to the reference output # No point in testing chapters 1 or 2 unless/until they are converted to autodoc gap> docdir := DirectoriesPackageLibrary( "AutoDoc", "doc" );; gap> ex_dir := DirectoriesPackageLibrary( "AutoDoc", "tst/manual.expected" );; # check chapter 3 gap> chap3 := Filename( docdir, "_Chapter_AutoDoc_worksheets.xml" );; gap> chap3ref := Filename( ex_dir, "_Chapter_AutoDoc_worksheets.xml" );; gap> AUTODOC_Diff("-u", chap3ref, chap3); 0 # check chapter 4 gap> chap4 := Filename( docdir, "_Chapter_AutoDoc.xml" );; gap> chap4ref := Filename( ex_dir, "_Chapter_AutoDoc.xml" );; gap> AUTODOC_Diff("-u", chap4ref, chap4); 0 # gap> STOP_TEST( "dogfood.tst" ); AutoDoc-2025.10.16/COPYRIGHT0000644000175100017510000000225315074117054014355 0ustar runnerrunnerAutoDoc: A GAP interface to Singular. AutoDoc 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 2 of the License, or (at your option) any later version. AutoDoc 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 AutoDoc; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Copyright (C) 2012-2019 by its authors and contributors: Authors: * Max Horn * Sebastian Gutsche Contributors: * Chris Wensley * Fabian Zickgraf * Glen Whitney * Jerry James * Markus Pfeiffer * Mohamed Barakat * Øystein Skartsæterhagen AutoDoc-2025.10.16/gap/0000755000175100017510000000000015074117054013627 5ustar runnerrunnerAutoDoc-2025.10.16/gap/DocumentationTree.gd0000644000175100017510000000614715074117054017604 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later ###################################### ## ## Tools ## ###################################### DeclareGlobalFunction( "AUTODOC_TREE_NODE_NAME_ITERATOR" ); DeclareGlobalFunction( "AUTODOC_LABEL_OF_CONTEXT" ); DeclareGlobalFunction( "AUTODOC_INSTALL_TREE_SETTERS" ); ###################################### ## ## Categories ## ###################################### DeclareCategory( "IsTreeForDocumentation", IsObject ); DeclareCategory( "IsTreeForDocumentationNode", IsObject ); ###################################### ## ## Attributes ## ###################################### DeclareOperation( "IsEmptyNode", [ IsTreeForDocumentationNode ] ); DeclareOperation( "IsEmptyNode", [ IsString ] ); DeclareAttribute( "Label", IsTreeForDocumentationNode, "mutable" ); DeclareAttribute( "ChapterInfo", IsTreeForDocumentationNode ); DeclareAttribute( "GroupName", IsTreeForDocumentationNode ); ###################################### ## ## Constructors ## ###################################### DeclareOperation( "DocumentationTree", [ ] ); DeclareOperation( "StructurePartInTree", [ IsTreeForDocumentation, IsList ] ); DeclareOperation( "ChapterInTree", [ IsTreeForDocumentation, IsString ] ); DeclareOperation( "SectionInTree", [ IsTreeForDocumentation, IsString, IsString ] ); DeclareOperation( "SubsectionInTree", [ IsTreeForDocumentation, IsString, IsString, IsString ] ); DeclareOperation( "DocumentationExample", [ IsTreeForDocumentation ] ); DeclareOperation( "DocumentationChunk", [ IsTreeForDocumentation, IsString ] ); DeclareOperation( "DocumentationManItem", [ IsTreeForDocumentation ] ); DeclareOperation( "SetManItemToDescription", [ IsTreeForDocumentationNode ] ); DeclareOperation( "SetManItemToReturnValue", [ IsTreeForDocumentationNode ] ); DeclareOperation( "DocumentationGroup", [ IsTreeForDocumentation, IsString ] ); DeclareOperation( "DocumentationGroup", [ IsTreeForDocumentation, IsString, IsList ] ); DeclareOperation( "Add", [ IsTreeForDocumentation, IsTreeForDocumentationNode ] ); DeclareOperation( "Add", [ IsTreeForDocumentationNode, IsTreeForDocumentationNode ] ); DeclareOperation( "Add", [ IsTreeForDocumentation, IsTreeForDocumentationNode, IsList ] ); DeclareOperation( "Add", [ IsTreeForDocumentation, IsTreeForDocumentationNode, IsString ] ); DeclareOperation( "Add", [ IsTreeForDocumentationNode, IsString ] ); DeclareOperation( "MergeGroupEntries", [ IsTreeForDocumentationNode, IsTreeForDocumentationNode ] ); DeclareOperation( "Add", [ IsTreeForDocumentation, IsString ] ); ####################################### ## ## Write methods ## ####################################### DeclareOperation( "WriteDocumentation", [ IsTreeForDocumentation, IsDirectory, IsInt ] ); DeclareOperation( "WriteDocumentation", [ IsTreeForDocumentationNode, IsStream, IsInt ] ); DeclareOperation( "WriteDocumentation", [ IsList, IsStream, IsInt ] ); DeclareOperation( "WriteDocumentation", [ IsTreeForDocumentationNode, IsStream, IsDirectory, IsInt ] ); AutoDoc-2025.10.16/gap/Parser.gd0000644000175100017510000000060615074117054015401 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later DeclareGlobalFunction( "Scan_for_AutoDoc_Part" ); DeclareGlobalFunction( "AutoDoc_Type_Of_Item" ); ## Argument should be a filename DeclareGlobalFunction( "AutoDoc_Parser_ReadFiles" ); AutoDoc-2025.10.16/gap/Markdown.gd0000644000175100017510000000052415074117054015726 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later DeclareGlobalFunction( "INSERT_IN_STRING_WITH_REPLACE" ); DeclareGlobalFunction( "CONVERT_LIST_OF_STRINGS_IN_MARKDOWN_TO_GAPDOC_XML" ); AutoDoc-2025.10.16/gap/ToolFunctions.gi0000644000175100017510000002442715074117054016767 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later # Check whether the given directory exists, and if not, attempt # to create it. InstallGlobalFunction( "AUTODOC_CreateDirIfMissing", function(d) local tmp; if not IsDirectoryPath(d) then tmp := CreateDir(d); # Note: CreateDir is currently undocumented if tmp = fail then Error("Cannot create directory ", d, "\n", "Error message: ", LastSystemError().message, "\n"); return false; fi; fi; return true; end ); InstallGlobalFunction( "AUTODOC_CurrentDirectory", function(args...) local pwd, result; pwd := Filename( DirectoriesSystemPrograms(), "pwd" ); if pwd = fail then Error("failed to locate 'pwd' tool"); fi; result := ""; Process(DirectoryCurrent(), pwd, InputTextNone(), OutputTextString(result, true), []); return Chomp(result); end); InstallGlobalFunction( "AUTODOC_OutputTextFile", function( dir, filename ) local filestream; filename := Filename( dir, filename ); filestream := OutputTextFile( filename, false ); SetPrintFormattingStatus( filestream, false ); return filestream; end ); ## InstallGlobalFunction( AutoDoc_WriteDocEntry, function( filestream, list_of_records, heading, level_value ) local return_value, description, current_description, labels, i; # look for a good return value (it should be the same everywhere) for i in list_of_records do if IsBound( i!.return_value ) then if IsList( i!.return_value ) and Length( i!.return_value ) > 0 then return_value := i!.return_value; break; elif IsBool( i!.return_value ) then return_value := i!.return_value; break; fi; fi; od; if not IsBound( return_value ) then return_value := false; fi; if IsList( return_value ) and ( not IsString( return_value ) ) and return_value <> "" then return_value := JoinStringsWithSeparator( return_value, " " ); fi; # collect description (for readability not in the loop above) description := [ ]; for i in list_of_records do current_description := i!.description; if IsString( current_description ) then current_description := [ current_description ]; fi; description := Concatenation( description, current_description ); od; labels := [ ]; for i in list_of_records do if HasGroupName( i ) then Add( labels, GroupName( i ) ); fi; od; if Length( labels ) > 1 then labels := [ labels[ 1 ] ]; fi; # Write stuff out # First labels, this has no effect in the current GAPDoc, btw. AppendTo( filestream, "\n" ); # Next possibly the heading for the entry if IsString( heading ) then AppendTo( filestream, "", heading, "\n" ); fi; # Function headers for i in list_of_records do AppendTo( filestream, " <", i!.item_type, " " ); if i!.arguments <> fail and i!.item_type <> "Var" then AppendTo( filestream, "Arg=\"", i!.arguments, "\" " ); fi; AppendTo( filestream, "Name=\"", i!.name, "\" " ); if i!.tester_names <> fail and i!.tester_names <> "" then AppendTo( filestream, "Label=\"", i!.tester_names, "\"" ); fi; AppendTo( filestream, "/>\n" ); od; if return_value <> false then if IsString( return_value ) then return_value := [ return_value ]; fi; AppendTo( filestream, " " ); WriteDocumentation( return_value, filestream, level_value ); AppendTo( filestream, "\n" ); fi; AppendTo( filestream, " \n" ); WriteDocumentation( description, filestream, level_value ); AppendTo( filestream, " \n" ); AppendTo( filestream, "\n\n" ); end ); InstallGlobalFunction( AutoDoc_CreatePrintOnceFunction, function( message ) local x; x := true; return function( ) if x then Info( InfoAutoDoc, 1, message ); fi; x := false; end; end ); InstallGlobalFunction( AUTODOC_Diff, function(args...) local diff; diff := Filename( DirectoriesSystemPrograms(), "diff" ); if diff = fail then Error("failed to locate 'diff' tool"); fi; return Process(DirectoryCurrent(), diff, InputTextUser(), OutputTextUser(), args); end); # AUTODOC_TestWorkSheet is used by AutoDocs test suite to test the worksheets # feature. Its single argument should be a string, and then # `tst/worksheets/` should be a directory containing a worksheet, and # `tst/worksheets/.expected` a directory containing the output of # AutoDocWorksheet for that worksheet. # # Then AUTODOC_TestWorkSheet will again run AutoDocWorksheet, put storing the # output into `tst/worksheets/.actual`; it then runs diff on all files in # order to find any differences that may have crept in. If no differences # exist, it outputs nothing. InstallGlobalFunction( AUTODOC_TestWorkSheet, function(ws) local wsdir, sheetdir, expecteddir, actualdir, filenames, old, f, expected, actual; # check worksheets dir exists wsdir := DirectoriesPackageLibrary("AutoDoc", "tst/worksheets"); wsdir := wsdir[1]; if not IsDirectoryPath(wsdir) then Error("could not access tst/worksheets/"); fi; # check input dir exists sheetdir := Filename(wsdir, Concatenation(ws, ".sheet")); if not IsString(sheetdir) or not IsDirectoryPath(sheetdir) then Error("could not access tst/", ws, ".sheet/"); fi; sheetdir := Directory(sheetdir); # check dir with expected output expecteddir := Filename(wsdir, Concatenation(ws, ".expected")); if not IsString(expecteddir) or not IsDirectoryPath(expecteddir) then Error("could not access tst/", ws, ".expected/"); fi; expecteddir := Directory(expecteddir); # create and clear the output directory actualdir := Filename(wsdir, Concatenation(ws, ".actual")); Exec(Concatenation("rm -rf \"", actualdir, "\"")); AUTODOC_CreateDirIfMissing(actualdir); actualdir := Directory(actualdir); # Run the worksheet filenames := DirectoryContents(sheetdir); filenames := Filtered(filenames, f -> f <> "." and f <> ".."); filenames := List(filenames, f -> Filename(sheetdir, f)); old := InfoLevel(InfoGAPDoc); SetInfoLevel(InfoGAPDoc, 0); AutoDocWorksheet(filenames, rec(dir := actualdir, extract_examples := true)); SetInfoLevel(InfoGAPDoc, old); # Check the results filenames := DirectoryContents(expecteddir); filenames := Filtered(filenames, f -> f <> "." and f <> ".."); for f in filenames do expected := Filename(expecteddir, f); actual := Filename(actualdir, f); if 0 <> AUTODOC_Diff("-u", expected, actual) then Error("diff detected in file ", f); fi; od; end); BindGlobal("AUTODOC_months", MakeImmutable([ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ])); # Format a date into a human readable string; a date may consist of only # a year; or a year and a month; or a year, month and day. Dates are # formatted as "2019", resp. "February 2019" resp. "5 February 2019". # # The input can be one of the following: # - AUTODOC_FormatDate(rec), where is a record with entries year, month, day; # - AUTODOC_FormatDate(year[, month[, day]]) # - AUTODOC_FormatDate(date_str) where date_str is a string of the form "DD/MM/YYYY" or "YYYY-MM-DD" # In each case, the year, month or day may be given as either an # integer, or as a string representing an integer. InstallGlobalFunction( AUTODOC_FormatDate, function(arg) local date, key, val, result; if Length(arg) = 1 and IsRecord(arg[1]) then date := ShallowCopy(arg[1]); elif Length(arg) = 1 and IsString(arg[1]) then if Length(arg[1]) = 10 then date := arg[1]; if date{[3,6]} = "//" then date := rec( day := Int(date{[1,2]}), month := Int(date{[4,5]}), year := Int(date{[7..10]}), ); elif date{[5,8]} = "--" then date := rec( year := Int(date{[1..4]}), month := Int(date{[6,7]}), day := Int(date{[9,10]}), ); else Unbind(date); fi; fi; elif Length(arg) in [1..3] then date := rec(); date.year := arg[1]; if Length(arg) >= 2 then date.month := arg[2]; fi; if Length(arg) >= 3 then date.day := arg[3]; fi; fi; if not IsBound(date) then Error("Invalid arguments"); fi; # convert string values to integers for key in [ "day", "month", "year" ] do if IsBound(date.(key)) then val := date.(key); if IsString(val) and Length(val) > 0 and ForAll(val, IsDigitChar) then date.(key) := Int(val); fi; fi; od; if not IsInt(date.year) or date.year < 2000 then Error(" must be an integer >= 2000, or a string representing such an integer"); fi; result := String(date.year); if IsBound(date.month) then if not date.month in [1..12] then Error(" must be an integer in the range [1..12], or a string representing such an integer"); fi; result := Concatenation(AUTODOC_months[date.month], " ", result); if IsBound(date.day) then if not date.day in [1..31] then # TODO: also account for differing length of months Error(" must be an integer in the range [1..31], or a string representing such an integer"); fi; result := Concatenation(String(date.day), " ", result); fi; fi; return result; end); AutoDoc-2025.10.16/gap/Magic.gd0000644000175100017510000004501715074117054015172 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later #! @Chapter AutoDoc #! @Section The AutoDoc() function #! @Description #! This is the main function of the &AutoDoc; package. It can perform #! any combination of the following tasks: #! #! #! It can (re)generate a scaffold for your package manual. #! That is, it can produce two XML files in &GAPDoc; format to be used as part #! of your manual: First, a file named doc/PACKAGENAME.xml #! (with your package's name substituted) which is used as #! main XML file for the package manual, i.e. this file sets the #! XML doctype and defines various XML entities, includes #! other XML files (both those generated by &AutoDoc; as well #! as additional files created by other means), tells &GAPDoc; #! to generate a table of contents and an index, and more. #! Secondly, it creates a file doc/title.xml containing a title #! page for your documentation, with information about your package #! (name, description, version), its authors and more, based #! on the data in your PackageInfo.g. #! #! #! It can scan your package for &AutoDoc; based documentation (by using &AutoDoc; #! tags and the Autodoc command. #! This will #! produce further XML files to be used as part of the package manual. #! #! #! It can use &GAPDoc; to generate PDF, text and HTML (with #! MathJaX enabled) documentation from the &GAPDoc; XML files it #! generated as well as additional such files provided by you. For #! this, it invokes #! to convert the XML sources, and it also instructs &GAPDoc; to copy #! supplementary files (such as CSS style files) into your doc directory #! (see ). #! #! #! For more information and some examples, please refer to Chapter . #!

#! The parameters have the following meanings: #! #! #! packageOrDirectory #! #! The purpose of this parameter is twofold: to determine the package #! directory in which &AutoDoc; will operate, and to find the metadata #! concerning the package being documented. The parameter is either a #! string, an IsDirectory object, or omitted. #! If it is a string, &AutoDoc; interprets it as the name of a #! package, uses the metadata of the first package known to &GAP; #! with that name, and uses the InstallationPath specified in that #! metadata as the package directory. If packageOrDirectory is #! an IsDirectory object, this is used as package directory; #! if the argument is omitted, then the current directory is used. #! In the last two cases, the specified directory must contain a #! PackageInfo.g file, and &AutoDoc; extracts all needed metadata #! from that. The IsDirectory form is for example useful if you #! have multiple versions of the package around and want to make sure the #! documentation of the correct version is built. #!

#! Note that when using AutoDocWorksheet (see #! ), there is #! no parameter corresponding to packageOrDirectory and so the #! package directory is always the current directory, and #! there is no metadata. #! #! #! #! optrec #! #! optrec can be a record with some additional options. #! The following are currently supported: #! #! dir #! #! This should either be a string, in which case it must be a path #! relative to the specified package directory, or a #! Directory() object. (Thus, the only way to designate an #! absolute directory is with a Directory() object.) This #! option specifies where the package documentation #! (e.g. the &GAPDoc; XML or the manual PDF, etc.) files are stored #! and/or will be generated. #!
#! Default value: "doc/". #!
#! scaffold #! #! This controls whether and how to generate scaffold XML files #! for the package documentation. #!

#! The value should be either true, false or a #! record. If it is a record or true (the latter is #! equivalent to specifying an empty record), then this feature is #! enabled. It is also enabled if opt.scaffold is missing but the #! package's info record in PackageInfo.g has an AutoDoc entry. #! In all other cases (in particular if opt.scaffold is #! false), scaffolding is disabled. #!

#! If scaffolding is enabled, and PackageInfo.AutoDoc exists, then it is #! assumed to be a record, and its contents are used as default values for #! the scaffold settings. #!

#! #! If opt.scaffold is a record, it may contain the following entries. #! #! #! #! includes #! #! A list of XML files to be included in the body of the main XML file. #! If you specify this list and also are using &AutoDoc; to document #! your operations with &AutoDoc; comments, #! you can add _AutoDocMainFile.xml to this list #! to control at which point the documentation produced by &AutoDoc; #! is inserted. If you do not do this, it will be added after the last #! of your own XML files. #! #! #! index #! #! By default, the scaffold creates an index. If you do not want an index, #! set this to false. #! #! #! appendix #! #! This entry is similar to opt.scaffold.includes but is used #! to specify files to include after the main body of the manual, #! i.e. typically appendices. #! #! #! bib #! #! The name of a bibliography file, in BibTeX or XML format. #! If this key is not set, but there is a file doc/PACKAGENAME.bib #! then it is assumed that you want to use this as your bibliography. #! #! #! entities #! #! A record whose keys are taken as entity names, set to the corresponding #! (string) values. For example, if you pass the record SomePackage, #!

SomePackage", #! RELEASEYEAR := "2015" )]]> #! then the following entity definitions are added to the XML preamble: #! SomePackage'> #! ]]> #! This allows you to write &SomePackage; and &RELEASEYEAR; #! in your documentation, which will be replaced by respective values specified #! in the entities definition. #! #! #! TitlePage #! #! A record whose entries are used to embellish the generated title page #! for the package manual with extra information, such as a copyright #! statement or acknowledgments. To this end, the names of the record #! components are used as XML element names, and the values of the #! components are outputted as content of these XML elements. For #! example, you could pass the following record to set a custom #! acknowledgements text: #! #! For a list of valid entries in the title page, please refer to the #! &GAPDoc; manual, specifically section . #! #! MainPage #! #! If scaffolding is enabled, by default a main XML file is generated (this #! is the file which contains the XML doctype and more). If you do not #! want this (e.g. because you have a handwritten main XML file), but #! still want &AutoDoc; to generate a title page for you, you can set this #! option to false #! #! document_class #! #! Sets the document class of the resulting PDF. The value can either be a string #! which has to be the name of the new document class, a list containing this string, or #! a list of two strings. Then the first one has to be the document class name, the second one #! the option string ( contained in [ ] ) in &LaTeX;. #! #! latex_header_file #! #! Replaces the standard header from &GAPDoc; completely with the header in this &LaTeX; file. #! Please be careful here, and look at &GAPDoc;'s latexheader.tex file for an example. #! #! #! #! #! #! #! autodoc #! #! This controls whether and how to generate additional XML documentation files #! by scanning for &AutoDoc; documentation comments. #!

#! The value should be either true, false or a #! record. If it is a record or true (the latter is #! equivalent to specifying an empty record), then this feature is #! enabled. It is also enabled if opt.autodoc is missing but the #! package depends (directly) on the &AutoDoc; package. #! In all other cases (in particular if opt.autodoc is #! false), this feature is disabled. #!

#! #! If opt.autodoc is a record, it may contain the following entries. #! #! #! #! files #! #! A list of files (given by paths relative to the package directory) #! to be scanned for &AutoDoc; documentation comments. #! Usually it is more convenient to use autodoc.scan_dirs, see below. #! #! #! scan_dirs #! #! A list of subdirectories of the package directory (given as relative paths) #! which &AutoDoc; then scans for .gi, .gd, .g, and .autodoc files; all of these files #! are then scanned for &AutoDoc; documentation comments. #!
#! Default value: [ ".", "gap", "lib", "examples", "examples/doc" ]. #!
#! #! level #! #! This defines the level of the created documentation. The default value is 0. #! When parts of the manual are declared with a higher value #! they will not be printed into the manual. #! #! #### TODO: Document section_intros later on. #### However, note that thanks to the new AutoDoc comment syntax, the only remaining #### use for this seems to be the ability to specify the order of chapters and #### sections. #### section_intros #### #### TODO. #### #! #!
#! #! #! #! gapdoc #! #! This controls whether and how to invoke &GAPDoc; to create HTML, PDF and text #! files from your various XML files. #!

#! The value should be either true, false or a #! record. If it is a record or true (the latter is #! equivalent to specifying an empty record), then this feature is #! enabled. It is also enabled if opt.gapdoc is missing. #! In all other cases (in particular if opt.gapdoc is #! false), this feature is disabled. #!

#! #! If opt.gapdoc is a record, it may contain the following entries. #! #! #! #! #### Note: 'main' is strictly speaking also used for the scaffold. #### However, if one uses the scaffolding mechanism, then it is not #### really necessary to specify a custom name for the main XML file. #### Thus, the purpose of this parameter is to cater for packages #### that have existing documentation using a different XML name, #### and which do not wish to use scaffolding. #### #### This explains why we only allow specifying gapdoc.main. #### The scaffolding code will still honor it, though, just in case. #! main #! #! The name of the main XML file of the package manual. #! This exists primarily to support packages with existing manual #! which use a filename here which differs from the default. #! In particular, specifying this is unnecessary when using scaffolding. #!
#! Default value: PACKAGENAME.xml. #!
#! #! files #! #! A list of files (given by paths relative to the package directory) #! to be scanned for &GAPDoc; documentation comments. #! Usually it is more convenient to use gapdoc.scan_dirs, see below. #! #! #! scan_dirs #! #! A list of subdirectories of the package directory (given as relative paths) #! which &AutoDoc; then scans for .gi, .gd and .g files; all of these files #! are then scanned for &GAPDoc; documentation comments. #!
#! Default value: [ ".", "gap", "lib", "examples", "examples/doc" ]. #!
#! #! LaTeXOptions #! #! Must be a record with entries which can be understood by #! . Each entry can be a #! string, which will be given to &GAPDoc; directly, or a list containing of #! two entries: The first one must be the string "file", the second one a #! filename. This file will be read and then its content is passed to &GAPDoc; #! as option with the name of the entry. #! #! #! gap_root_relative_path #! #! Either a boolean, or a string containing a relative path. #! By default (if this option is not set, or is set to false), #! references in the generated documentation referring to external documentation #! (such as the &GAP; manual) are encoded using absolute paths. #! This is fine as long as the documentation stays on only a single #! computer, but is problematic when preparing documentation that should be #! used on multiple computers, e.g., when creating a distribution archive of #! a &GAP; package.
#! Thus, if a relative path is provided via this option (or if it is set to true, #! in which case the relative path ../../.. is used), then &AutoDoc; #! and &GAPDoc; attempt to replace all absolute paths in references to &GAP; #! manuals by paths based on this relative path.

#! #! On a technical level, &AutoDoc; passes the relative path to the #! gaproot parameter of

#! #! #! #! #! extract_examples #! #! Either true or a record. #! If set to true, then all manual examples are extracted and placed #! into files tst/PACKAGENAME01.tst, tst/PACKAGENAME02.tst, ... #! and so on, with one file for each chapter. For chapters with no examples, #! no file is created.

#! As a record, the entry can have the following entries itself, to specify some options. #! #! units #! #! This controls how examples are grouped into files. Recognized values are #! "Chapter" (default), "Section", "Subsection" or "Single". Depending on the value, #! one file is created for each chapter, each section, each subsection or each example. #! For all other values only a single file is created. #! #! On a technical level, &AutoDoc; passes the value to the #! units parameter of . #! #! skip_empty_in_numbering #! #! If set to true (the default), the generated files use #! filenames with strictly sequential numbering; that means that #! if chapter 1 (or whatever units are being used) contains no #! examples but chapter 2 does, then the examples for chapter 2 #! are put into the file tst/PACKAGENAME01.tst. If this #! option is set to false, then the chapter numbers are #! used to generate the filenames; so the examples for chapter 2 #! would be put into the file tst/PACKAGENAME02.tst. #! #! #! #! #! #! #! #! #! @Returns nothing #! @Arguments [packageOrDirectory], [optrec] DeclareGlobalFunction( "AutoDoc" ); #! @Description #! Info class for the AutoDoc package. Set this to #! 0 to suppress info messages, 1 to allow most messages, and 2 to allow all #! messages including those that contain file paths. #! #! This can be set by calling, for example, #! SetInfoLevel(InfoPackageManager, 0). Default value 1. DeclareInfoClass("InfoAutoDoc"); SetInfoLevel(InfoAutoDoc, 1); #! @Section Examples #! #! Some basic examples for using AutoDoc were already shown in #! Chapter . AutoDoc-2025.10.16/gap/Magic.gi0000644000175100017510000005717615074117054015210 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later # Given a string containing a ".", , return its suffix, # i.e. the bit after the last ".". For example, given "test.txt", # it returns "txt". BindGlobal( "AUTODOC_GetSuffix", function(str) local i; i := Length(str); while i > 0 and str[i] <> '.' do i := i - 1; od; if i = 0 then return ""; fi; return str{[i+1..Length(str)]}; end ); # Scan the given (by name) subdirs of a package dir for # files with one of the given extensions, and return the corresponding # filenames, as relative paths (relative to the package dir). # # For example, the invocation # AUTODOC_FindMatchingFiles(pkgdir, [ "gap/" ], [ "gi", "gd" ]); # might return a list looking like # [ "gap/AutoDocMainFunction.gd", "gap/AutoDocMainFunction.gi", ... ] BindGlobal( "AUTODOC_FindMatchingFiles", function (pkgdir, subdirs, extensions) local d_rel, d, tmp, files, result; result := []; for d_rel in subdirs do # Get the absolute path to the directory in side the package... d := Filename( pkgdir, d_rel ); if not IsDirectoryPath( d ) then continue; fi; d := Directory( d ); # ... but also keep the relative path (such as "gap") if d_rel = "" or d_rel = "." then d_rel := ""; else d_rel := Directory( d_rel ); fi; files := DirectoryContents( d ); Sort( files ); for tmp in files do if not AUTODOC_GetSuffix( tmp ) in extensions then continue; fi; if not IsReadableFile( Filename( d, tmp ) ) then continue; fi; if d_rel = "" then Add( result, tmp ); else Add( result, Filename( d_rel, tmp ) ); fi; od; od; return result; end ); # InstallGlobalFunction( AutoDoc, function( arg ) local pkgname, pkginfo, pkgdir, opt, scaffold, gapdoc, extract_examples, autodoc, i, doc_dir, doc_dir_rel, tmp, key, val, file, pkgdirstr, docdirstr, title_page, tree, is_worksheet, position_document_class, args; if Length( arg ) >= 3 then Error( "too many arguments" ); fi; # check whether the last argument is an options record if Length( arg ) > 0 and IsRecord( arg[Length(arg)] ) then opt := Remove( arg ); else opt := rec(); fi; # check the first argument if Length(arg) = 0 then pkgdir := DirectoryCurrent( ); elif IsString( arg[1] ) then pkgname := Remove( arg, 1 ); elif IsDirectory( arg[1] ) then pkgdir := Remove( arg, 1 ); fi; # if there are any arguments left, at least one was of unsupported type if Length(arg) > 0 then Error( "wrong arguments" ); fi; if IsBound( pkgdir ) then is_worksheet := false; file := Filename( pkgdir, "PackageInfo.g" ); if not IsExistingFile( file ) then Error( "no package name given and no PackageInfo.g file found" ); elif not IsReadableFile( file ) then Error( "cannot read PackageInfo.g" ); fi; Unbind( GAPInfo.PackageInfoCurrent ); Read( file ); if not IsBound( GAPInfo.PackageInfoCurrent ) then Error( "reading PackageInfo.g failed" ); fi; pkginfo := GAPInfo.PackageInfoCurrent; if IsRecord( pkginfo.PackageDoc ) then pkginfo.PackageDoc:= [ pkginfo.PackageDoc ]; fi; pkgname := pkginfo.PackageName; elif pkgname = "AutoDocWorksheet" then # For internal use only -- for details, refer to the AutoDocWorksheet() function. is_worksheet := true; pkginfo := rec( ); pkgdir := DirectoryCurrent( ); else is_worksheet := false; pkginfo := PackageInfo( pkgname ); if IsEmpty( pkginfo ) then Error( "Could not find package ", pkgname ); elif Length( pkginfo ) > 1 then Info( InfoWarning, 1, "multiple versions of package ", pkgname, " are present, using the first one" ); fi; pkginfo := pkginfo[ 1 ]; pkgdir := Directory( pkginfo.InstallationPath ); fi; # # Check for user supplied options. If present, they take # precedence over any defaults as well as the opt record. # for key in [ "dir", "scaffold", "autodoc", "gapdoc", "extract_examples" ] do val := ValueOption( key ); if val <> fail then opt.(key) := val; fi; od; # # Setup the output directory # if not IsBound( opt.dir ) then doc_dir := "doc"; elif IsString( opt.dir ) or IsDirectory( opt.dir ) then doc_dir := opt.dir; else Error( "opt.dir must be a string containing a path, or a directory object" ); fi; if IsString( doc_dir ) then # Record the relative version of the path # FIXME: this assumes that doc_dir contains a relative path in the first place... doc_dir_rel := Directory( doc_dir ); # We intentionally do not use # DirectoriesPackageLibrary( pkgname, "doc" ) # because it returns an empty list if the subdirectory is missing. # But we want to handle that case by creating the directory. doc_dir := Filename( pkgdir, doc_dir ); doc_dir := Directory( doc_dir ); else # In this case, if doc_dir happens to lie below pkgdir, we want the # doc_dir_rel to be the difference; if not we avoid binding doc_dir_rel # and leave MakeGAPDocDoc to muddle through with absolute paths. pkgdirstr := Filename( pkgdir, "" ); docdirstr := Filename( doc_dir, "" ); if StartsWith( docdirstr, pkgdirstr ) then doc_dir_rel := Directory( docdirstr{[(Length(pkgdirstr)+1)..Length(docdirstr)]} ); fi; fi; # Ensure the output directory exists, create it if necessary AUTODOC_CreateDirIfMissing(Filename(doc_dir, "")); # Let the developer know where we are generating the documentation. # This helps diagnose problems where multiple instances of a package # are visible to GAP and the wrong one is used for generating the # documentation. Info( InfoAutoDoc, 2, "Generating documentation in ", doc_dir); # # Extract scaffolding settings, which can be controlled via # opt.scaffold or pkginfo.AutoDoc. The former has precedence. # if not IsBound(opt.scaffold) then # Default: enable scaffolding if and only if pkginfo.AutoDoc is present if IsBound( pkginfo.AutoDoc ) then scaffold := rec( ); fi; elif IsRecord(opt.scaffold) then scaffold := opt.scaffold; elif IsBool(opt.scaffold) then if opt.scaffold = true then scaffold := rec(); fi; else Error("opt.scaffold must be a bool or a record"); fi; # Merge pkginfo.AutoDoc into scaffold if IsBound(scaffold) and IsBound( pkginfo.AutoDoc ) then for key in RecNames( pkginfo.AutoDoc ) do if IsBound( scaffold.(key) ) then Info(InfoAutoDoc, 1, "WARNING: ", key, " specified in both PackageInfo.AutoDoc and opt.scaffold"); else scaffold.(key) := pkginfo.AutoDoc.(key); fi; od; fi; if IsBound( scaffold ) then AUTODOC_SetIfMissing( scaffold, "TitlePage", rec() ); AUTODOC_SetIfMissing( scaffold, "MainPage", true ); fi; # # Extract AutoDoc settings # if not IsBound(opt.autodoc) and not is_worksheet then # Enable AutoDoc support if the package depends on AutoDoc. tmp := Concatenation( pkginfo.Dependencies.NeededOtherPackages, pkginfo.Dependencies.SuggestedOtherPackages ); ## Empty entries are allowed in Dependencies tmp := Filtered( tmp, i -> i <> [ ] ); if ForAny( tmp, x -> LowercaseString(x[1]) = "autodoc" ) then autodoc := rec(); fi; elif IsRecord(opt.autodoc) then autodoc := opt.autodoc; elif IsBool(opt.autodoc) and opt.autodoc = true then autodoc := rec(); fi; if IsBound(autodoc) then if not IsBound( autodoc.files ) then autodoc.files := [ ]; elif not IsList( autodoc.files ) then Error("autodoc.files must be a list"); elif Length(autodoc.files) >0 and IsString( autodoc.files ) then Error("autodoc.files must be a list of strings, not a string"); fi; if not is_worksheet then if not IsBound( autodoc.scan_dirs ) then autodoc.scan_dirs := [ ".", "gap", "lib", "examples", "examples/doc" ]; fi; Append( autodoc.files, AUTODOC_FindMatchingFiles(pkgdir, autodoc.scan_dirs, [ "g", "gi", "gd", "autodoc" ]) ); autodoc.files := DuplicateFreeList( autodoc.files ); fi; # Make sure all of the files exist, making the file names absolute if # necessary for i in [ 1 .. Length( autodoc.files ) ] do if IsExistingFile( autodoc.files[ i ] ) then continue; fi; if IsExistingFile( Filename( pkgdir, autodoc.files[ i ] ) ) then autodoc.files[ i ] := Filename( pkgdir, autodoc.files[ i ] ); continue; fi; Error( autodoc.files[ i ], " does not specify an existing file either as an absolute path or relative to the package directory" ); od; if not IsBound( autodoc.level ) then autodoc.level := 0; fi; fi; # # Extract GAPDoc settings # if not IsBound( opt.gapdoc ) then # Enable GAPDoc support by default gapdoc := rec(); elif IsRecord( opt.gapdoc ) then gapdoc := opt.gapdoc; elif IsBool( opt.gapdoc ) and opt.gapdoc = true then gapdoc := rec(); fi; if IsBound( gapdoc ) then AUTODOC_SetIfMissing( gapdoc, "main", pkgname ); if IsBound( pkginfo.PackageDoc ) and not IsEmpty( pkginfo.PackageDoc ) then if Length( pkginfo.PackageDoc ) > 1 then Info(InfoAutoDoc, 1, "WARNING: Package contains multiple books, only using the first one"); fi; gapdoc.bookname := pkginfo.PackageDoc[1].BookName; gapdoc.SixFile := pkginfo.PackageDoc[1].SixFile; elif not is_worksheet then # Default: book name = package name gapdoc.bookname := pkgname; gapdoc.SixFile := "doc/manual.six"; Info(InfoAutoDoc, 1, "WARNING: PackageInfo.g is missing a PackageDoc entry!"); Info(InfoAutoDoc, 1, "Without this, your package manual will not be recognized by the GAP help system."); Info(InfoAutoDoc, 1, "You can correct this by adding the following to your PackageInfo.g:"); Info(InfoAutoDoc, 1, "PackageDoc := rec("); Info(InfoAutoDoc, 1, " BookName := ~.PackageName,"); Info(InfoAutoDoc, 1, " ArchiveURLSubset := [\"doc\"],"); Info(InfoAutoDoc, 1, " HTMLStart := \"doc/chap0.html\","); Info(InfoAutoDoc, 1, " PDFFile := \"doc/manual.pdf\","); Info(InfoAutoDoc, 1, " SixFile := \"doc/manual.six\","); Info(InfoAutoDoc, 1, " LongTitle := ~.Subtitle,"); Info(InfoAutoDoc, 1, "),"); fi; if not IsBound( gapdoc.files ) then gapdoc.files := []; elif not IsList( gapdoc.files ) then Error("gapdoc.files must be a list"); elif not ForAll( gapdoc.files, IsString ) then Error("gapdoc.files must be a list of strings, not a string"); fi; if not is_worksheet then if not IsBound( gapdoc.scan_dirs ) then gapdoc.scan_dirs := [ ".", "gap", "lib", "examples", "examples/doc" ]; fi; Append( gapdoc.files, AUTODOC_FindMatchingFiles(pkgdir, gapdoc.scan_dirs, [ "g", "gi", "gd" ]) ); fi; # Attempt to weed out duplicates as they may confuse GAPDoc (this # will not work if there are any non-normalized paths in the list). gapdoc.files := Set( gapdoc.files ); # If possible, convert the file paths in gapdoc.files, which are # relative to the package directory, to paths which are relative to # the doc directory. if IsBound( doc_dir_rel ) then # For this, we assume that doc_dir_rel is normalized (e.g. # it does not contains '//') and relative. # FIXME: this is an ugly hack, can't we do something better? tmp := Number( Filename( doc_dir_rel, "" ), x -> x = '/' ); tmp := Concatenation( ListWithIdenticalEntries(tmp, "../") ); gapdoc.files := List( gapdoc.files, f -> Concatenation( tmp, f ) ); else # Here presumably the doc_dir was given by an absolute path that # does not lie below the package dir. In that case, we can't make # the gapdoc.files relative to the doc dir, but rather we have no # choice but to make them absolute, which MakeGAPDocDoc can handle, # even if perhaps less gracefully/portably. gapdoc.files := List( gapdoc.files, f -> Filename( pkgdir, f ) ); fi; fi; # read tree # FIXME: shouldn't tree be declared inside of an 'if IsBound(autodoc)' section? tree := DocumentationTree( ); if IsBound( autodoc ) then if IsBound( autodoc.section_intros ) then AUTODOC_PROCESS_INTRO_STRINGS( autodoc.section_intros, tree ); fi; AutoDocScanFiles( autodoc.files, pkgname, tree ); fi; if is_worksheet then # FIXME: We use scaffold and autodoc here without checking whether # they are bound. Does that mean worksheets always use them? if IsBound( scaffold.TitlePage.Title ) then pkgname := scaffold.TitlePage.Title; elif IsBound( tree!.TitlePage.Title ) then pkgname := tree!.TitlePage.Title; elif IsBound( autodoc.files ) and Length( autodoc.files ) > 0 then tmp := autodoc.files[ 1 ]; # Remove everything before the last '/' tmp := SplitString(tmp, "/"); tmp := tmp[Length(tmp)]; # Remove everything after the first '.' tmp := SplitString(tmp, "."); tmp := tmp[1]; pkgname := tmp; else Error( "could not figure out a title." ); fi; if not IsString( pkgname ) then pkgname := JoinStringsWithSeparator( pkgname, " " ); fi; gapdoc.main := ReplacedString( pkgname, " ", "_" ); gapdoc.bookname := ReplacedString( pkgname, " ", "_" ); fi; # # Generate scaffold # if IsBound( scaffold ) then ## Syntax is [ "class", [ "options" ] ] if IsBound( scaffold.document_class ) then position_document_class := PositionSublist( GAPDoc2LaTeXProcs.Head, "documentclass" ); if IsString( scaffold.document_class ) then scaffold.document_class := [ scaffold.document_class ]; fi; if position_document_class = fail then Error( "something is wrong with the LaTeX header" ); fi; GAPDoc2LaTeXProcs.Head := Concatenation( GAPDoc2LaTeXProcs.Head{[ 1 .. PositionSublist( GAPDoc2LaTeXProcs.Head, "{", position_document_class ) ]}, scaffold.document_class[ 1 ], GAPDoc2LaTeXProcs.Head{[ PositionSublist( GAPDoc2LaTeXProcs.Head, "}", position_document_class ) .. Length( GAPDoc2LaTeXProcs.Head ) ]} ); if Length( scaffold.document_class ) = 2 then GAPDoc2LaTeXProcs.Head := Concatenation( GAPDoc2LaTeXProcs.Head{[ 1 .. PositionSublist( GAPDoc2LaTeXProcs.Head, "[", position_document_class ) ]}, scaffold.document_class[ 2 ], GAPDoc2LaTeXProcs.Head{[ PositionSublist( GAPDoc2LaTeXProcs.Head, "]", position_document_class ) .. Length( GAPDoc2LaTeXProcs.Head ) ]} ); fi; fi; if IsBound( scaffold.latex_header_file ) then GAPDoc2LaTeXProcs.Head := StringFile( scaffold.latex_header_file ); fi; AUTODOC_SetIfMissing( scaffold, "includes", [ ] ); if IsBound( autodoc ) then # If scaffold.includes is already set, then we add # AutoDocMainFile.xml to it, but *only* if it not already # there. This way, package authors can control where # it is put in their includes list. if not _AUTODOC_GLOBAL_OPTION_RECORD.AutoDocMainFile in scaffold.includes then Add( scaffold.includes, _AUTODOC_GLOBAL_OPTION_RECORD.AutoDocMainFile ); fi; fi; if IsBound( scaffold.bib ) and IsBool( scaffold.bib ) then if scaffold.bib = true then scaffold.bib := Concatenation( pkgname, ".bib" ); else Unbind( scaffold.bib ); fi; elif not IsBound( scaffold.bib ) then # If there is a doc/PKG.bib file, assume that we want to reference it in the scaffold. tmp := Concatenation( pkgname, ".bib" ); if IsReadableFile( Filename( doc_dir, tmp ) ) then scaffold.bib := tmp; fi; fi; AUTODOC_SetIfMissing( scaffold, "index", true ); if IsBound( gapdoc ) then if AUTODOC_GetSuffix( gapdoc.main ) = "xml" then scaffold.main_xml_file := gapdoc.main; else scaffold.main_xml_file := Concatenation( gapdoc.main, ".xml" ); fi; fi; if IsBound( scaffold.TitlePage ) and scaffold.TitlePage <> false then title_page := ShallowCopy( scaffold.TitlePage ); AUTODOC_MergeRecords( title_page, tree!.TitlePage ); if not is_worksheet then AUTODOC_MergeRecords( title_page, ExtractTitleInfoFromPackageInfo( pkginfo ) ); fi; # Worksheets get date as a list if is_worksheet then title_page!.Date := Concatenation( title_page!.Date ); fi; CreateTitlePage( doc_dir, title_page ); fi; CreateEntitiesPage( gapdoc.bookname, doc_dir, scaffold ); if IsBound( scaffold.MainPage ) and scaffold.MainPage <> false then CreateMainPage( gapdoc.bookname, doc_dir, scaffold ); fi; fi; # # Write AutoDoc XML files # if IsBound( autodoc ) then WriteDocumentation( tree, doc_dir, autodoc.level ); if IsBound( gapdoc ) then if IsBound( doc_dir_rel ) then Add( gapdoc.files, "_Chunks.xml" ); else Add( gapdoc.files, Filename( doc_dir, "_Chunks.xml" ) ); fi; fi; fi; # # Run GAPDoc # if IsBound( gapdoc ) then AUTODOC_SetIfMissing(gapdoc, "LaTeXOptions", rec() ); if not IsRecord( gapdoc.LaTeXOptions ) then Error("gapdoc.LaTeXOptions must be a record"); fi; for key in RecNames( gapdoc.LaTeXOptions ) do if not IsString( gapdoc.LaTeXOptions.( key ) ) and IsList( gapdoc.LaTeXOptions.( key ) ) and LowercaseString( gapdoc.LaTeXOptions.( key )[ 1 ] ) = "file" then gapdoc.LaTeXOptions.( key ) := StringFile( gapdoc.LaTeXOptions.( key )[ 2 ] ); fi; od; # Ask GAPDoc to use UTF-8 as input encoding for LaTeX, as the XML files # of the documentation are also in UTF-8 encoding, and may contain characters # not contained in the default Latin 1 encoding. AUTODOC_SetIfMissing( gapdoc.LaTeXOptions, "InputEncoding", "utf8" ); SetGapDocLaTeXOptions( gapdoc.LaTeXOptions ); ## HACK: If there is an empty index, MakeGAPDocDoc throws an error when creating the pdf. ## this addition prevents this by fake adding the index to the page number log. See issue 106. ## FIXME: Once an empty index is allowed in GapDoc, this should be removed. GAPDoc2LaTeXProcs.Tail := Concatenation( "\\immediate\\write\\pagenrlog{[\"Ind\", 0, 0], \\arabic{page},}\n", GAPDoc2LaTeXProcs.Tail ); # Default parameters for MakeGAPDocDoc args := [ doc_dir, gapdoc.main, gapdoc.files, gapdoc.bookname, "MathJax" ]; # Don't try to generate PDFs if pdflatex is not available if Filename( DirectoriesSystemPrograms(), "pdflatex" ) = fail then Add(args, "nopdf" ); fi; # The global option "relativePath" can be set to ensure the manual # is built in such a way that all references to the GAP reference manual # are using relative file paths. This is mainly useful when building # a package manual for use in a distribution tarball. tmp := ValueOption( "relativePath" ); if IsBound( gapdoc.gap_root_relative_path ) and tmp = fail then ## the option overrides the settings in the call. tmp := gapdoc.gap_root_relative_path; fi; if tmp = true then Add( args, "../../.." ); elif IsString( tmp ) then Add( args, tmp ); fi; # don't build PDF docs if the environment variable NOPDF is set if IsBound( GAPInfo.SystemEnvironment.NOPDF ) then Add( args, "nopdf" ); fi; # Finally, invoke GAPDoc CallFuncList( MakeGAPDocDoc, args ); # NOTE: We cannot just write CopyHTMLStyleFiles(doc_dir) here, as # CopyHTMLStyleFiles its argument directly to Directory(), leading # to an error in all GAP versions up to and including 4.8.6. This # will be fixed with GAP 4.9, where Directory() is made idempotent. CopyHTMLStyleFiles( Filename( doc_dir, "" ) ); # The following (undocumented) API is there for compatibility # with old-style gapmacro.tex based package manuals. It # produces a manual.lab file which those packages can use if # they wish to link to things in the manual we are currently # generating. This can probably be removed eventually, but for # now, doing it does not hurt. # FIXME: It seems that this command does not work if pdflatex # is not present. Maybe we should remove it. if IsBound( gapdoc.SixFile ) then file := Filename(pkgdir, gapdoc.SixFile); if file = fail or not IsReadableFile(file) then Error("could not open `", file, "' for package `", pkgname, "'.\n"); fi; GAPDocManualLabFromSixFile( gapdoc.bookname, file ); fi; fi; # # Handle extract_examples # if IsBound( opt.extract_examples ) then if IsRecord( opt.extract_examples ) then extract_examples := opt.extract_examples; elif opt.extract_examples = true then extract_examples := rec( ); fi; fi; if IsBound( extract_examples ) then if is_worksheet then # HACK: not even sure this is really what we want for worksheets, but # it is useful for our "dogfood" test suite pkgdir := doc_dir; fi; if not IsBound( extract_examples.units ) then extract_examples.units := "Chapter"; fi; if not IsBound( extract_examples.skip_empty_in_numbering ) then extract_examples.skip_empty_in_numbering := true; fi; AUTODOC_ExtractMyManualExamples( pkgname, pkgdir, doc_dir, gapdoc.main, gapdoc.files, extract_examples ); fi; return true; end ); AutoDoc-2025.10.16/gap/AutoDocMainFunction.gi0000644000175100017510000003740615074117054020033 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later InstallGlobalFunction( AUTODOC_SetIfMissing, function( record, name, val ) if not IsBound( record.(name) ) then record.(name) := val; fi; end ); ## InstallGlobalFunction( AUTODOC_APPEND_STRING_ITERATIVE, function( arg ) local string, i; string := arg[ 1 ]; for i in [ 2 .. Length( arg ) ] do Append( string, arg[ i ] ); od; Append( string, "\n" ); end ); ## ## Given two records, this adds all key/values pairs of the ## second record to the first record, unless the first record already ## has an entry for that key. InstallGlobalFunction( AUTODOC_MergeRecords, function( dst, src ) local key; for key in RecNames( src ) do AUTODOC_SetIfMissing( dst, key, src.( key ) ); od; end ); ## InstallGlobalFunction( CreateDefaultChapterData, function( pkgname ) local chapter_name, default_chapter_record, list_of_types, i; if not IsString( pkgname ) then Error( "CreateDefaultChapterData must be called with a possible package name\n" ); fi; chapter_name := Concatenation( pkgname, "_automatic_generated_documentation" ); default_chapter_record := rec(); list_of_types := [ "categories", "methods", "attributes", "properties", "global_functions", "global_variables", "info_classes" ]; for i in list_of_types do default_chapter_record.(i) := [ chapter_name, Concatenation( chapter_name, "_of_", i ) ]; od; return default_chapter_record; end ); ## InstallGlobalFunction( CreateEntitiesPage, function( book_name, dir, opt ) local filestream, i, ent, val, entities; if IsString(dir) then dir := Directory(dir); fi; if not IsBound( opt.entities ) then entities := rec(); elif IsList( opt.entities ) then entities := rec(); for i in opt.entities do if IsString( i ) then ent := i; val := Concatenation("", ent, ""); else ent := i[2]; val := Concatenation("<", i[1], ">", ent, ""); fi; entities.(ent) := val; od; elif IsRecord( opt.entities ) then entities := opt.entities; else Error("CreateEntitiesPage: must be a list or a record"); fi; # add book_name unconditionally to the list of entities if not IsBound(entities.(book_name)) then entities.(book_name) := Concatenation( "", book_name, "" ); fi; # open the target XML file filestream := AUTODOC_OutputTextFile( dir, "_entities.xml" ); # output all entities for ent in RecNames(entities) do val := String(entities.(ent)); # escape single quotes, if any val := ReplacedString( val, "'", "\\\'" ); # convert spaces in entity name to underscores ent := ReplacedString( ent, " ", "_" ); AppendTo( filestream, "\n" ); od; CloseStream( filestream ); end ); ## InstallGlobalFunction( CreateMainPage, function( book_name, dir, opt ) local filestream, i; if IsString(dir) then dir := Directory(dir); fi; # open the target XML file filestream := AUTODOC_OutputTextFile( dir, opt.main_xml_file ); # output the initial file header AppendTo( filestream, AUTODOC_XML_HEADER ); AppendTo( filestream, "\n"); AppendTo( filestream, "]\n>\n" ); # now start the actual book AppendTo( filestream, "\n" ); AppendTo( filestream, "<#Include SYSTEM \"title.xml\">\n" ); if not IsBound( opt.table_of_contents ) or opt.table_of_contents <> false then AppendTo( filestream, "\n" ); fi; AppendTo( filestream, "\n" ); if IsBound( opt.includes ) then for i in opt.includes do AppendTo( filestream, "<#Include SYSTEM \"", i, "\">\n" ); od; else AppendTo( filestream, "<#Include SYSTEM \"", _AUTODOC_GLOBAL_OPTION_RECORD.AutoDocMainFile, "\">\n" ); fi; AppendTo( filestream, "\n" ); if IsBound( opt.appendix ) then for i in opt.appendix do AppendTo( filestream, "<#Include SYSTEM \"", i, "\">\n" ); od; fi; if IsBound( opt.bib ) and opt.bib <> false then AppendTo( filestream, "\n" ); fi; if IsBound( opt.index ) and opt.index = true then AppendTo( filestream, "\n" ); fi; AppendTo( filestream, "\n" ); CloseStream( filestream ); return true; end ); ## InstallGlobalFunction( ExtractTitleInfoFromPackageInfo, function( pkginfo ) local title_rec, i, tmp_list, j, author_rec, author_string; if IsBound( pkginfo.AutoDoc ) and IsBound( pkginfo.AutoDoc.TitlePage ) then title_rec := ShallowCopy( pkginfo.AutoDoc.TitlePage ); else title_rec := rec( ); fi; AUTODOC_SetIfMissing( title_rec, "Title", pkginfo.PackageName ); AUTODOC_SetIfMissing( title_rec, "Subtitle", ReplacedString( pkginfo.Subtitle, "GAP", "&GAP;" ) ); AUTODOC_SetIfMissing( title_rec, "Version", pkginfo.Version ); ## Sanitize author info if not IsBound( title_rec.Author ) then title_rec.Author := [ ]; i := 1; for author_rec in pkginfo.Persons do if not author_rec.IsAuthor then continue; fi; author_string := ""; AUTODOC_APPEND_STRING_ITERATIVE( author_string, author_rec.FirstNames, " ", author_rec.LastName, "
" ); if IsBound( author_rec.PostalAddress ) then tmp_list := SplitString( StripBeginEnd( author_rec.PostalAddress, "\n\r" ), "\n" ); AUTODOC_APPEND_STRING_ITERATIVE( author_string, "

" ); for j in tmp_list do AUTODOC_APPEND_STRING_ITERATIVE( author_string, j, "
" ); od; AUTODOC_APPEND_STRING_ITERATIVE( author_string, "
" ); fi; if IsBound( author_rec.Email ) then AUTODOC_APPEND_STRING_ITERATIVE( author_string, "", author_rec.Email, "" ); fi; if IsBound( author_rec.WWWHome ) then AUTODOC_APPEND_STRING_ITERATIVE( author_string, "", author_rec.WWWHome, "" ); fi; title_rec.Author[ i ] := author_string; i := i + 1; od; fi; AUTODOC_SetIfMissing( title_rec, "Date", pkginfo.Date ); return title_rec; end ); ## ## This creates a titlepage out of an argument record. ## Please make sure that every entry in the record ## has the name of its tag, even title etc. ## Please note that entities will be treated ## separately. InstallGlobalFunction( CreateTitlePage, function( dir, argument_rec ) local indent, tag, names, filestream, entity_list, OutWithTag, Out, i; filestream := AUTODOC_OutputTextFile( dir, "title.xml" ); indent := 0; Out := function(arg) local s; s := ListWithIdenticalEntries( indent * 2, ' '); Append( s, Concatenation( arg ) ); AppendTo( filestream, s ); end; OutWithTag := function( tag, content ) local lines, s, l; if not IsList( content ) then Error( "can only print string or list of strings" ); fi; if IsString( content ) then content := [ content ]; fi; s := ListWithIdenticalEntries( indent * 2, ' '); AppendTo( filestream, s, "<", tag, ">\n" ); for l in content do AppendTo( filestream, s, " ", l, "\n" ); od; AppendTo( filestream, s, "\n" ); end; Out( AUTODOC_XML_HEADER ); Out( "\n" ); indent := indent + 1; for i in [ "Title", "Subtitle", "Version", "TitleComment" ] do if IsBound( argument_rec.( i ) ) then OutWithTag( i, argument_rec.( i ) ); fi; od; if IsBound( argument_rec.Author ) then for i in argument_rec.Author do OutWithTag( "Author", i ); od; fi; if IsBound( argument_rec.Date ) then # try to parse the date in format DD/MM/YYYY (we also accept single # digit day or month, which is formally not allowed in PackageInfo.g, # but happens in a few legacy packages) argument_rec.Date := Chomp( argument_rec.Date ); # remove trailing newlines, if present OutWithTag( "Date", AUTODOC_FormatDate(argument_rec.Date) ); fi; for i in [ "Address", "Abstract", "Copyright", "Acknowledgements", "Colophon" ] do if IsBound( argument_rec.( i ) ) then OutWithTag( i, StripBeginEnd( argument_rec.( i ), "\n\r" ) ); fi; od; Out( "" ); CloseStream( filestream ); end ); InstallGlobalFunction( AUTODOC_PROCESS_INTRO_STRINGS, function( introduction_list, tree ) local intro, intro_string, i; for intro in introduction_list do if Length( intro ) = 2 then intro_string := intro[ 2 ]; if IsString( intro_string ) then intro_string := [ intro_string ]; fi; for i in intro_string do Add( ChapterInTree( tree, ReplacedString( intro[ 1 ], " ", "_" ) ), i ); od; elif Length( intro ) = 3 then intro_string := intro[ 3 ]; if IsString( intro_string ) then intro_string := [ intro_string ]; fi; for i in intro_string do Add( SectionInTree( tree, ReplacedString( intro[ 1 ], " ", "_" ), ReplacedString( intro[ 2 ], " ", "_" ) ), i ); od; else Error( "wrong format of introduction string list\n" ); fi; od; return tree; end ); ## ## Optional argument is PackageName, which creates a ## Default chapter record. This is not available for ## worksheets. InstallGlobalFunction( AutoDocScanFiles, function( files_to_scan, pkgname, tree ) local default_chapter_record; default_chapter_record := CreateDefaultChapterData( pkgname ); AutoDoc_Parser_ReadFiles( files_to_scan, tree, default_chapter_record ); return tree; end ); ## InstallGlobalFunction( AutoDocWorksheet, function( arg ) local autodoc_rec, scaffold_rec; if Length( arg ) = 1 then arg[ 2 ] := rec( ); fi; scaffold_rec := ValueOption( "scaffold" ); if scaffold_rec = fail then scaffold_rec := rec( ); fi; AUTODOC_SetIfMissing( scaffold_rec, "index", false ); if Length( arg ) = 2 then autodoc_rec := ValueOption( "autodoc" ); if autodoc_rec = fail then autodoc_rec := rec( ); fi; if IsString( arg[ 1 ] ) then arg[ 1 ] := [ arg[ 1 ] ]; fi; if IsBound( autodoc_rec.files ) then Append( autodoc_rec.files, arg[ 1 ] ); else autodoc_rec.files := arg[ 1 ]; fi; AutoDoc( "AutoDocWorksheet", arg[ 2 ] : autodoc := autodoc_rec, scaffold := scaffold_rec ); fi; if Length( arg ) = 0 then AutoDoc( "AutoDocWorksheet" : scaffold := scaffold_rec ); fi; end ); # The following function is based on code by Alexander Konovalov BindGlobal("AUTODOC_ExtractMyManualExamples", function( pkgname, pkgdir, docdir, main, files, opt ) local tst, i, s, basename, name, output, ch, a, location, pos, comment, pkgdirString, nonempty_units_found, number_of_digits, lpkgname, tstdir; Info(InfoAutoDoc, 1, "Extracting manual examples for ", pkgname, " package ..."); lpkgname := LowercaseString(pkgname); lpkgname := ReplacedString(lpkgname, " ", "_"); if not EndsWith(main, ".xml") then main := Concatenation( main, ".xml" ); fi; tst:=ExtractExamples( docdir, main, files, opt.units ); Info(InfoAutoDoc, 1, Length(tst), " ", LowercaseString( opt.units ), "s detected"); pkgdirString := Filename(pkgdir, ""); # ensure the 'tst' directory exists tstdir := Filename(pkgdir, "tst"); AUTODOC_CreateDirIfMissing(tstdir); tstdir := Directory(tstdir); # first delete all old extracted tests in case chapter numbering etc. changed for s in DirectoryContents(tstdir) do # check prefix and suffix... if StartsWith(s, lpkgname) and EndsWith(s, ".tst") # ... and between them, there should be only digits (at least 2)... and Length(s) - Length(lpkgname) - 4 >= 2 and ForAll(s{[1 + Length(lpkgname) .. Length(s) - 4]}, IsDigitChar) then RemoveFile(Filename(tstdir, s)); fi; od; # nonempty_units_found := 0; number_of_digits := Length( String( Length( tst ) ) ); if number_of_digits = 1 then number_of_digits := 2; fi; for i in [ 1 .. Length(tst) ] do Info(InfoAutoDoc, 1, opt.units, " ", i, "..."); if Length( tst[i] ) = 0 then Info(InfoAutoDoc, 1, "no examples"); continue; fi; nonempty_units_found := nonempty_units_found + 1; if opt.skip_empty_in_numbering then s := String( nonempty_units_found ); else s := String( i ); fi; # pad s to number_of_digits s := Concatenation( ListWithIdenticalEntries( number_of_digits - Length( s ), '0' ), s ); basename := Concatenation( lpkgname, s, ".tst" ); name := Filename( tstdir, basename ); output := OutputTextFile( name, false ); # to empty the file first SetPrintFormattingStatus( output, false ); # to avoid line breaks ch := tst[i]; AppendTo(output, "# ", pkgname, ", ", LowercaseString( opt.units ), " ", i, "\n"); AppendTo(output, """# # DO NOT EDIT THIS FILE - EDIT EXAMPLES IN THE SOURCE INSTEAD! # # This file has been generated by AutoDoc. It contains examples extracted from # the package documentation. Each example is preceded by a comment which gives # the name of a GAPDoc XML file and a line range from which the example were # taken. Note that the XML file in turn may have been generated by AutoDoc # from some other input. # """); AppendTo(output, "gap> START_TEST(\"", basename, "\");\n\n"); for a in ch do location := a[2][1]; if StartsWith(location, pkgdirString) then comment := location{[ Length(pkgdirString)+1 .. Length(location) ]}; else pos := PositionSublist(location, LowercaseString(pkgname)); if pos <> fail then comment := location{[ pos+Length(pkgname)+1 .. Length(location) ]}; else pos := PositionSublist(location,"./"); if pos <> fail then comment := location{[ pos+2 .. Length(location) ]}; else Error("oops"); fi; fi; fi; AppendTo(output, "# ", comment, ":", a[2][2], "-", a[2][3]); if not StartsWith(a[1], "\n") then AppendTo(output, "\n"); fi; if not EndsWith(a[1], "\n") then AppendTo(output, a[1], "\n\n"); else AppendTo(output, a[1], "\n"); fi; od; AppendTo(output, "#\n"); AppendTo(output, "gap> STOP_TEST(\"", basename, "\", 1);\n"); CloseStream( output ); Info(InfoAutoDoc, 1, "extracted ", Length(ch), " examples"); od; end); AutoDoc-2025.10.16/gap/Parser.gi0000644000175100017510000011613615074117054015414 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later ## InstallGlobalFunction( Scan_for_AutoDoc_Part, function( line, plain_text_mode ) local position, whitespace_position, command, argument; #! @DONT_SCAN_NEXT_LINE position := PositionSublist( line, "#!" ); if position = fail and plain_text_mode = false then return [ false, line ]; fi; if plain_text_mode <> true then line := StripBeginEnd( line{[ position + 2 .. Length( line ) ]}, " " ); fi; ## Scan for a command position := PositionSublist( line, "@" ); if position = fail then return [ "STRING", line ]; fi; whitespace_position := PositionSublist( line, " " ); if whitespace_position = fail then command := line{[ position .. Length( line ) ]}; argument := ""; else command := line{[ position .. whitespace_position - 1 ]}; argument := line{[ whitespace_position + 1 .. Length( line ) ]}; fi; return [ command, argument ]; end ); ## Scans a string for after appeared. ## This is necessary to scan the filter list for method declarations ## that contain \[\]. BindGlobal( "AUTODOC_PositionElementIfNotAfter", function( list, element, element_not_before_element ) local current_pos; if not IsList( list ) then Error( " must be a list" ); fi; if Length( list ) > 0 and list[ 1 ] = element then return 1; fi; for current_pos in [ 2 .. Length( list ) ] do if list[ current_pos ] = element and list[ current_pos - 1 ] <> element_not_before_element then return current_pos; fi; od; return fail; end ); BindGlobal( "AutoDoc_PrintWarningForConstructor", AutoDoc_CreatePrintOnceFunction( "Installed GAPDoc version does not support constructors" ) ); ## InstallGlobalFunction( AutoDoc_Type_Of_Item, function( current_item, type, default_chapter_data ) local item_rec, entries, has_filters, ret_val; item_rec := current_item; if PositionSublist( type, "DeclareCategoryCollections") <> fail then entries := [ "Filt", "categories" ]; ret_val := "true or false"; has_filters := "No"; if not IsBound( item_rec!.arguments ) then item_rec!.arguments := "obj"; fi; item_rec!.coll_suffix := true; elif PositionSublist( type, "DeclareCategory" ) <> fail then entries := [ "Filt", "categories" ]; ret_val := "true or false"; has_filters := 1; elif PositionSublist( type, "DeclareRepresentation" ) <> fail then entries := [ "Filt", "categories" ]; ret_val := "true or false"; has_filters := 1; elif PositionSublist( type, "DeclareAttribute" ) <> fail then entries := [ "Attr", "attributes" ]; has_filters := 1; elif PositionSublist( type, "DeclareProperty" ) <> fail then entries := [ "Prop", "properties" ]; ret_val := "true or false"; has_filters := 1; elif PositionSublist( type, "DeclareOperation" ) <> fail then entries := [ "Oper", "methods" ]; has_filters := "List"; elif PositionSublist( type, "DeclareConstructor" ) <> fail then if IsPackageMarkedForLoading( "GAPDoc", ">=1.6.1" ) then entries := [ "Constr", "methods" ]; else AutoDoc_PrintWarningForConstructor(); entries := [ "Oper", "methods" ]; fi; has_filters := "List"; elif PositionSublist( type, "DeclareGlobalFunction" ) <> fail then entries := [ "Func", "global_functions" ]; has_filters := "No"; if not IsBound( item_rec!.arguments ) then item_rec!.arguments := "arg"; fi; elif PositionSublist( type, "DeclareGlobalVariable" ) <> fail then entries := [ "Var", "global_variables" ]; has_filters := "No"; item_rec!.arguments := fail; item_rec!.return_value := false; elif PositionSublist( type, "DeclareGlobalName" ) <> fail then entries := [ "Var", "global_variables" ]; has_filters := "No"; item_rec!.arguments := fail; item_rec!.return_value := false; elif PositionSublist( type, "DeclareFilter" ) <> fail then entries := [ "Filt", "properties" ]; has_filters := "No"; item_rec!.arguments := fail; item_rec!.return_value := false; elif PositionSublist( type, "DeclareInfoClass" ) <> fail then entries := [ "InfoClass", "info_classes" ]; has_filters := "No"; item_rec!.arguments := fail; item_rec!.return_value := false; elif PositionSublist( type, "KeyDependentOperation" ) <> fail then entries := [ "Oper", "methods" ]; has_filters := 2; else return fail; fi; item_rec!.item_type := entries[ 1 ]; if not IsBound( item_rec!.chapter_info ) or item_rec!.chapter_info = [ ] then item_rec!.chapter_info := default_chapter_data.( entries[ 2 ] ); fi; if IsBound( ret_val ) and ( item_rec!.return_value = [ ] or item_rec!.return_value = false ) then item_rec!.return_value := [ ret_val ]; fi; return has_filters; end ); ## InstallGlobalFunction( AutoDoc_Parser_ReadFiles, function( filename_list, tree, default_chapter_data ) local current_item, flush_and_recover, chapter_info, current_string_list, Scan_for_Declaration_part, flush_and_prepare_for_item, current_line, filestream, level_scope, scope_group, read_example, command_function_record, autodoc_read_line, current_command, was_declaration, filename, system_scope, groupnumber, rest_of_file_skipped, context_stack, new_man_item, add_man_item, Reset, read_code, title_item, title_item_list, plain_text_mode, current_line_unedited, deprecated, ReadLineWithLineCount, Normalized_ReadLine, line_number, ErrorWithPos, create_title_item_function, current_line_positition_for_filter, read_session_example; groupnumber := 0; level_scope := 0; autodoc_read_line := false; context_stack := [ ]; chapter_info := [ ]; line_number := 0; ReadLineWithLineCount := function( stream ) line_number := line_number + 1; return ReadLine( stream ); end; Normalized_ReadLine := function( stream ) local string; string := ReadLineWithLineCount( stream ); if string = fail then return fail; fi; NormalizeWhitespace( string ); return string; end; ErrorWithPos := function(arg) local list; list := Concatenation(arg, [ ",\n", "at ", filename, ":", line_number]); CallFuncList(Error, list); end; new_man_item := function( ) local man_item; if IsBound( current_item ) and IsTreeForDocumentationNodeForManItemRep( current_item ) then return current_item; fi; # implicitly end any subsection if IsBound( chapter_info[ 3 ] ) then Unbind( chapter_info[ 3 ] ); current_item := SectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ] ); fi; if IsBound( current_item ) then Add( context_stack, current_item ); fi; man_item := DocumentationManItem( tree ); if IsBound( scope_group ) then SetGroupName( man_item, scope_group ); fi; man_item!.chapter_info := ShallowCopy( chapter_info ); man_item!.tester_names := fail; return man_item; end; add_man_item := function( ) local man_item; man_item := current_item; if context_stack <> [ ] then current_item := Remove( context_stack ); else Unbind( current_item ); fi; if IsBound( man_item!.chapter_info ) then SetChapterInfo( man_item, man_item!.chapter_info ); fi; if Length( ChapterInfo( man_item ) ) <> 2 then ErrorWithPos( "declarations must be documented within a section" ); fi; Add( tree, man_item ); end; Reset := function( ) chapter_info := [ ]; context_stack := [ ]; Unbind( current_item ); plain_text_mode := false; end; Scan_for_Declaration_part := function() local declare_position, current_type, filter_string, has_filters, position_parenthesis, nr_of_attr_loops, i; ## fail is bigger than every integer declare_position := Minimum( [ PositionSublist( current_line, "Declare" ), PositionSublist( current_line, "KeyDependentOperation" ) ] ); if declare_position <> fail then current_item := new_man_item(); current_line := current_line{[ declare_position .. Length( current_line ) ]}; position_parenthesis := PositionSublist( current_line, "(" ); if position_parenthesis = fail then ErrorWithPos( "Something went wrong" ); fi; current_type := current_line{ [ 1 .. position_parenthesis - 1 ] }; has_filters := AutoDoc_Type_Of_Item( current_item, current_type, default_chapter_data ); if has_filters = fail then ErrorWithPos( "Unrecognized scan type" ); return false; fi; current_line := current_line{ [ position_parenthesis + 1 .. Length( current_line ) ] }; ## Now the funny part begins: ## try fetching the name: ## Assuming the name is in the same line as its while PositionSublist( current_line, "," ) = fail and PositionSublist( current_line, ");" ) = fail do current_line := Normalized_ReadLine( filestream ); od; current_line := StripBeginEnd( current_line, " " ); current_item!.name := current_line{ [ 1 .. Minimum( [ PositionSublist( current_line, "," ), PositionSublist( current_line, ");" ) ] ) - 1 ] }; current_item!.name := StripBeginEnd( ReplacedString( current_item!.name, "\"", "" ), " " ); # Deal with DeclareCategoryCollections: this has some special # rules on how the name of a new category is derived from the # string given to it. Since the code for that is not available in # a separate GAP function, we have to replicate this logic here. # To understand what's going on, please refer to the # DeclareCategoryCollections documentation and implementation. if IsBound(current_item!.coll_suffix) then if EndsWith(current_item!.name, "Collection") then current_item!.name := current_item!.name{[1..Length(current_item!.name)-6]}; fi; if EndsWith(current_item!.name, "Coll") then current_item!.coll_suffix := "Coll"; else current_item!.coll_suffix := "Collection"; fi; current_item!.name := Concatenation(current_item!.name, current_item!.coll_suffix); fi; current_line := current_line{ [ Minimum( [ PositionSublist( current_line, "," ), PositionSublist( current_line, ");" ) ] ) + 1 .. Length( current_line ) ] }; filter_string := "for "; ## FIXME: The next two if's can be merged at some point if IsInt( has_filters ) then for i in [ 1 .. has_filters ] do ## We now search for the filters. A filter is either followed by a ',', if there is more than one, ## or by ');' if it is the only or last one. So we search for the next delimiter. while PositionSublist( current_line, "," ) = fail and PositionSublist( current_line, ");" ) = fail do Append( filter_string, StripBeginEnd( current_line, " " ) ); current_line := ReadLineWithLineCount( filestream ); NormalizeWhitespace( current_line ); od; current_line_positition_for_filter := Minimum( [ PositionSublist( current_line, "," ), PositionSublist( current_line, ");" ) ] ) - 1; Append( filter_string, StripBeginEnd( current_line{ [ 1 .. current_line_positition_for_filter ] }, " " ) ); current_line := current_line{[ current_line_positition_for_filter + 1 .. Length( current_line ) ]}; if current_line[ 1 ] = ',' then current_line := current_line{[ 2 .. Length( current_line ) ]}; elif current_line[ 1 ] = ')' then current_line := current_line{[ 3 .. Length( current_line ) ]}; fi; ## FIXME: Refactor this whole if IsInt( has_filters ) case! if has_filters - i > 0 then Append( filter_string, ", " ); fi; od; elif has_filters = "List" then while AUTODOC_PositionElementIfNotAfter( current_line, '[', '\\' ) = fail do current_line := ReadLineWithLineCount( filestream ); NormalizeWhitespace( current_line ); od; current_line := current_line{ [ AUTODOC_PositionElementIfNotAfter( current_line, '[', '\\' ) + 1 .. Length( current_line ) ] }; while AUTODOC_PositionElementIfNotAfter( current_line, ']', '\\' ) = fail do Append( filter_string, StripBeginEnd( current_line, " " ) ); current_line := ReadLineWithLineCount( filestream ); NormalizeWhitespace( current_line ); od; Append( filter_string, StripBeginEnd( current_line{[ 1 .. AUTODOC_PositionElementIfNotAfter( current_line, ']', '\\' ) - 1 ]}, " " ) ); else filter_string := false; fi; if IsString( filter_string ) then filter_string := ReplacedString( filter_string, "\"", "" ); fi; if filter_string <> false then if current_item!.tester_names = fail and StripBeginEnd( filter_string, " " ) <> "for" then current_item!.tester_names := filter_string; fi; if StripBeginEnd( filter_string, " " ) = "for" then has_filters := "empty_argument_list"; fi; ##Adjust arguments if not IsBound( current_item!.arguments ) then if IsInt( has_filters ) then if has_filters = 1 then current_item!.arguments := "arg"; else current_item!.arguments := JoinStringsWithSeparator( List( [ 1 .. has_filters ], i -> Concatenation( "arg", String( i ) ) ), "," ); fi; elif has_filters = "List" then current_item!.arguments := List( [ 1 .. Length( SplitString( filter_string, "," ) ) ], i -> Concatenation( "arg", String( i ) ) ); if Length( current_item!.arguments ) = 1 then current_item!.arguments := "arg"; else current_item!.arguments := JoinStringsWithSeparator( current_item!.arguments, "," ); fi; elif has_filters = "empty_argument_list" then current_item!.arguments := ""; fi; fi; fi; add_man_item(); return true; fi; declare_position := Minimum( [ PositionSublist( current_line, "InstallMethod" ), PositionSublist( current_line, "InstallOtherMethod" ) ] ); ## Fail is larger than every integer. if declare_position <> fail then current_item := new_man_item(); current_item!.item_type := "Oper"; ##Find name position_parenthesis := PositionSublist( current_line, "(" ); current_line := current_line{ [ position_parenthesis + 1 .. Length( current_line ) ] }; ## find next colon current_item!.name := ""; while PositionSublist( current_line, "," ) = fail do Append( current_item!.name, current_line ); current_line := Normalized_ReadLine( filestream ); od; position_parenthesis := PositionSublist( current_line, "," ); Append( current_item!.name, current_line{[ 1 .. position_parenthesis - 1 ]} ); NormalizeWhitespace( current_item!.name ); current_item!.name := StripBeginEnd( current_item!.name, " " ); while AUTODOC_PositionElementIfNotAfter( current_line, '[', '\\' ) = fail do current_line := Normalized_ReadLine( filestream ); od; position_parenthesis := AUTODOC_PositionElementIfNotAfter( current_line, '[', '\\' ); current_line := current_line{[ position_parenthesis + 1 .. Length( current_line ) ]}; filter_string := "for "; while PositionSublist( current_line, "]" ) = fail do Append( filter_string, current_line ); od; position_parenthesis := AUTODOC_PositionElementIfNotAfter( current_line, ']', '\\' ); Append( filter_string, current_line{[ 1 .. position_parenthesis - 1 ]} ); current_line := current_line{[ position_parenthesis + 1 .. Length( current_line )]}; NormalizeWhitespace( filter_string ); if IsString( filter_string ) then filter_string := ReplacedString( filter_string, "\"", "" ); fi; if current_item!.tester_names = fail then current_item!.tester_names := filter_string; fi; ##Maybe find some argument names if not IsBound( current_item!.arguments ) then while PositionSublist( current_line, "function(" ) = fail and PositionSublist( current_line, ");" ) = fail do current_line := Normalized_ReadLine( filestream ); od; position_parenthesis := PositionSublist( current_line, "function(" ); if position_parenthesis <> fail then current_line := current_line{[ position_parenthesis + 9 .. Length( current_line ) ]}; filter_string := ""; while PositionSublist( current_line, ")" ) = fail do; current_line := StripBeginEnd( current_line, " " ); Append( filter_string, current_line ); current_line := Normalized_ReadLine( current_line ); od; position_parenthesis := PositionSublist( current_line, ")" ); Append( filter_string, current_line{[ 1 .. position_parenthesis - 1 ]} ); NormalizeWhitespace( filter_string ); filter_string := StripBeginEnd( filter_string, " " ); current_item!.arguments := filter_string; fi; fi; if not IsBound( current_item!.arguments ) then current_item!.arguments := Length( SplitString( current_item!.tester_names, "," ) ); current_item!.arguments := JoinStringsWithSeparator( List( [ 1 .. current_item!.arguments ], i -> Concatenation( "arg", String( i ) ) ), "," ); fi; add_man_item(); return true; fi; return false; end; read_code := function( ) local code, temp_curr_line, comment_pos, before_comment; code := [ " fail then before_comment := NormalizedWhitespace( temp_curr_line{ [ 1 .. comment_pos - 1 ] } ); if before_comment = "" then temp_curr_line := temp_curr_line{[ comment_pos + 2 .. Length( temp_curr_line ) ]}; fi; fi; fi; if PositionSublist( temp_curr_line, "@EndCode" ) <> fail then break; fi; Add( code, temp_curr_line ); od; Add( code, "]]>\n" ); return code; end; read_example := function( is_tested_example ) local temp_string_list, temp_curr_line, temp_pos_comment, is_following_line, item_temp, example_node; example_node := DocumentationExample( tree ); example_node!.is_tested_example := is_tested_example; temp_string_list := example_node!.content; is_following_line := false; while true do temp_curr_line := Chomp( ReadLineWithLineCount( filestream ) ); if PositionSublist( temp_curr_line, "@EndExample" ) <> fail or PositionSublist( temp_curr_line, "@EndLog" ) <> fail then break; fi; ##if is comment, simply remove comments. #! @DONT_SCAN_NEXT_LINE temp_pos_comment := PositionSublist( temp_curr_line, "#!" ); if temp_pos_comment <> fail then temp_curr_line := temp_curr_line{[ temp_pos_comment + 3 .. Length( temp_curr_line ) ]}; Add( temp_string_list, temp_curr_line ); is_following_line := false; continue; else if is_following_line then temp_curr_line := Concatenation( "> ", temp_curr_line ); if PositionSublist( temp_curr_line, ";" ) <> fail then is_following_line := false; fi; else if temp_curr_line = "" then continue; fi; temp_curr_line := Concatenation( "gap> ", temp_curr_line ); is_following_line := PositionSublist( temp_curr_line, ";" ) = fail; fi; Add( temp_string_list, temp_curr_line ); continue; fi; od; return example_node; end; read_session_example := function( is_tested_example, plain_text_mode ) local temp_string_list, temp_curr_line, temp_pos_comment, is_following_line, item_temp, example_node, incorporate_this_line; example_node := DocumentationExample( tree ); example_node!.is_tested_example := is_tested_example; temp_string_list := example_node!.content; while true do temp_curr_line := Chomp( ReadLineWithLineCount( filestream ) ); if PositionSublist( temp_curr_line, "@EndExampleSession" ) <> fail or PositionSublist( temp_curr_line, "@EndLogSession" ) <> fail then break; fi; incorporate_this_line := plain_text_mode; if not plain_text_mode then #! @DONT_SCAN_NEXT_LINE temp_pos_comment := PositionSublist( temp_curr_line, "#!" ); if temp_pos_comment <> fail then incorporate_this_line := true; temp_curr_line := temp_curr_line{[ temp_pos_comment + 2 .. Length( temp_curr_line ) ]}; if Length( temp_curr_line ) >= 1 and temp_curr_line[ 1 ] = ' ' then Remove( temp_curr_line, 1 ); fi; fi; fi; if incorporate_this_line then Add( temp_string_list, temp_curr_line ); fi; od; return example_node; end; deprecated := function(name, f) return function(args...) Info(InfoWarning, 1, TextAttr.1, "WARNING: ----------------------------------------------------------------------------", TextAttr.reset); Info(InfoWarning, 1, TextAttr.1, "WARNING: ", name, " is deprecated; please refer to the AutoDoc manual for details", TextAttr.reset); Info(InfoWarning, 1, TextAttr.1, "WARNING: ----------------------------------------------------------------------------", TextAttr.reset); f(); end; end; command_function_record := rec( ## HACK: Needed for AutoDoc parser to be scanned safely. ## The lines where the AutoDoc comments are ## searched cause problems otherwise. @DONT_SCAN_NEXT_LINE := function() ReadLineWithLineCount( filestream ); end, @DoNotReadRestOfFile := function() Reset(); rest_of_file_skipped := true; end, @Chapter := function() local scope_chapter; scope_chapter := ReplacedString( current_command[ 2 ], " ", "_" ); current_item := ChapterInTree( tree, scope_chapter ); chapter_info[ 1 ] := scope_chapter; end, @ChapterLabel := function() local scope_chapter, label_name; if not IsBound( chapter_info[ 1 ] ) then ErrorWithPos( "found @ChapterLabel with no active chapter" ); fi; label_name := ReplacedString( current_command[ 2 ], " ", "_" ); scope_chapter := ChapterInTree( tree, chapter_info[ 1 ] ); SetLabel( scope_chapter, Concatenation( "Chapter_", label_name ) ); end, @ChapterTitle := function() local scope_chapter; if not IsBound( chapter_info[ 1 ] ) then ErrorWithPos( "found @ChapterTitle with no active chapter" ); fi; scope_chapter := ChapterInTree( tree, chapter_info[ 1 ] ); scope_chapter!.title_string := current_command[ 2 ]; end, @Section := function() local scope_section; if not IsBound( chapter_info[ 1 ] ) then ErrorWithPos( "found @Section with no active chapter" ); fi; scope_section := ReplacedString( current_command[ 2 ], " ", "_" ); current_item := SectionInTree( tree, chapter_info[ 1 ], scope_section ); Unbind( chapter_info[ 3 ] ); chapter_info[ 2 ] := scope_section; end, @SectionLabel := function() local scope_section, label_name; if not IsBound( chapter_info[ 2 ] ) then ErrorWithPos( "found @SectionLabel with no active section" ); fi; label_name := ReplacedString( current_command[ 2 ], " ", "_" ); scope_section := SectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ] ); SetLabel( scope_section, Concatenation( "Section_", label_name ) ); end, @SectionTitle := function() local scope_section; if not IsBound( chapter_info[ 2 ] ) then ErrorWithPos( "found @SectionTitle with no active section" ); fi; scope_section := SectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ] ); scope_section!.title_string := current_command[ 2 ]; end, @Subsection := function() local scope_subsection; if not IsBound( chapter_info[ 1 ] ) or not IsBound( chapter_info[ 2 ] ) then ErrorWithPos( "found @Subsection with no active section" ); fi; scope_subsection := ReplacedString( current_command[ 2 ], " ", "_" ); current_item := SubsectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ], scope_subsection ); chapter_info[ 3 ] := scope_subsection; end, @SubsectionLabel := function() local scope_subsection, label_name; if not IsBound( chapter_info[ 3 ] ) then ErrorWithPos( "found @SubsectionLabel with no active subsection" ); fi; label_name := ReplacedString( current_command[ 2 ], " ", "_" ); scope_subsection := SubsectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ], chapter_info[ 3 ] ); SetLabel( scope_subsection, Concatenation( "Subsection_", label_name ) ); end, @SubsectionTitle := function() local scope_subsection; if not IsBound( chapter_info[ 3 ] ) then ErrorWithPos( "found @SubsectionTitle with no active subsection" ); fi; scope_subsection := SubsectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ], chapter_info[ 3 ] ); scope_subsection!.title_string := current_command[ 2 ]; end, @BeginGroup := function() local grp; if current_command[ 2 ] = "" then groupnumber := groupnumber + 1; current_command[ 2 ] := Concatenation( "AutoDoc_generated_group", String( groupnumber ) ); fi; scope_group := ReplacedString( current_command[ 2 ], " ", "_" ); end, @EndGroup := function() Unbind( scope_group ); end, @Description := function() current_item := new_man_item(); SetManItemToDescription( current_item ); NormalizeWhitespace( current_command[ 2 ] ); if current_command[ 2 ] <> "" then Add( current_item, current_command[ 2 ] ); fi; end, @Returns := function() current_item := new_man_item(); SetManItemToReturnValue( current_item ); if current_command[ 2 ] <> "" then Add( current_item, current_command[ 2 ] ); fi; end, @Arguments := function() current_item := new_man_item(); current_item!.arguments := current_command[ 2 ]; end, @Label := function() current_item := new_man_item(); current_item!.tester_names := current_command[ 2 ]; end, @Group := function() local group_name; current_item := new_man_item(); group_name := ReplacedString( current_command[ 2 ], " ", "_" ); SetGroupName( current_item, group_name ); end, @GroupTitle := function() local group_name, chap_info, group_obj; current_item := new_man_item(); if not HasGroupName( current_item ) then ErrorWithPos( "found @GroupTitle with no Group set" ); fi; group_name := GroupName( current_item ); chap_info := fail; if HasChapterInfo( current_item ) then chap_info := ChapterInfo( current_item ); elif IsBound( current_item!.chapter_info ) then chap_info := current_item!.chapter_info; fi; if chap_info = fail or Length( chap_info ) = 0 then chap_info := chapter_info; fi; if Length( chap_info ) <> 2 then ErrorWithPos( "can only set @GroupTitle within a Chapter and Section."); fi; group_obj := DocumentationGroup( tree, group_name, chap_info ); group_obj!.title_string := current_command[ 2 ]; end, @ChapterInfo := function() local current_chapter_info; current_item := new_man_item(); current_chapter_info := SplitString( current_command[ 2 ], "," ); current_chapter_info := List( current_chapter_info, i -> ReplacedString( StripBeginEnd( i, " " ), " ", "_" ) ); SetChapterInfo( current_item, current_chapter_info ); end, @BREAK := function() ErrorWithPos( current_command[ 2 ] ); end, @SetLevel := function() level_scope := Int( current_command[ 2 ] ); end, @ResetLevel := function() level_scope := 0; end, @Level := function() current_item!.level := Int( current_command[ 2 ] ); end, @InsertChunk := function() local label_name; label_name := ReplacedString( current_command[ 2 ], " ", "_" ); Add( current_item, DocumentationChunk( tree, label_name ) ); end, @BeginChunk := function() local label_name; if IsBound( current_item ) then Add( context_stack, current_item ); fi; label_name := ReplacedString( current_command[ 2 ], " ", "_" ); current_item := DocumentationChunk( tree, label_name ); end, @Chunk := ~.@BeginChunk, @EndChunk := function() if autodoc_read_line = true then autodoc_read_line := false; fi; if context_stack <> [ ] then current_item := Remove( context_stack ); else Unbind( current_item ); fi; end, @BeginCode := function() local label_name, tmp_system; label_name := ReplacedString( current_command[ 2 ], " ", "_" ); tmp_system := DocumentationChunk( tree, label_name ); Append( tmp_system!.content, read_code() ); end, @Code := ~.@BeginCode, @InsertCode := ~.@InsertChunk, @BeginExample := function() local example_node; example_node := read_example( true ); Add( current_item, example_node ); end, @Example := ~.@BeginExample, @BeginLog := function() local example_node; example_node := read_example( false ); Add( current_item, example_node ); end, @Log := ~.@BeginLog, STRING := function() local comment_pos; if not IsBound( current_item ) then return; fi; comment_pos := PositionSublist( current_line_unedited, "#!" ); if comment_pos <> fail then current_line_unedited := current_line_unedited{[ comment_pos + 2 .. Length( current_line_unedited ) ]}; fi; Add( current_item, current_line_unedited ); end, @BeginLatexOnly := function() Add( current_item, " "" then Add( current_item, current_command[ 2 ] ); fi; end, @EndLatexOnly := function() if autodoc_read_line = true then autodoc_read_line := false; fi; Add( current_item, "]]>" ); end, @LatexOnly := function() Add( current_item, "" ); end, @BeginNotLatex := function() Add( current_item, " "" then Add( current_item, current_command[ 2 ] ); fi; end, @EndNotLatex := function() if autodoc_read_line = true then autodoc_read_line := false; fi; Add( current_item, "]]>" ); end, @NotLatex := function() Add( current_item, "" ); end, @Dependency := function() if not IsBound( tree!.worksheet_dependencies ) then tree!.worksheet_dependencies := [ ]; fi; NormalizeWhitespace( current_command[ 2 ] ); Add( tree!.worksheet_dependencies, SplitString( current_command[ 2 ], " " ) ); end, @ExampleSession := function() local example_node; example_node := read_session_example( true, plain_text_mode ); Add( current_item, example_node ); end, @BeginExampleSession := ~.@ExampleSession, @LogSession := function() local example_node; example_node := read_session_example( false, plain_text_mode ); Add( current_item, example_node ); end, @BeginLogSession := ~.@LogSession ); ## The following commands are specific for worksheets. They do not have a packageinfo, ## and no place to extract those infos. So these commands are needed to make insert the ## information directly into the document. title_item_list := [ "Title", "Subtitle", "Version", "TitleComment", "Author", "Date", "Address", "Abstract", "Copyright", "Acknowledgements", "Colophon" ]; create_title_item_function := function( name ) return function() if not IsBound( tree!.TitlePage.( name ) ) then tree!.TitlePage.( name ) := [ ]; fi; current_item := tree!.TitlePage.( name ); Add( current_item, current_command[ 2 ] ); end; end; ## Note that we need to create these functions in the helper function ## create_title_item_function to ensure that the variable is bound properly. ## Without this intermediate helper, the wrong closure is taken, ## and later, when the function is executed, the value for will be the last ## value had, i.e., the last entry of . for title_item in title_item_list do command_function_record.( Concatenation( "@", title_item ) ) := create_title_item_function( title_item ); od; rest_of_file_skipped := false; ##Now read the files. for filename in filename_list do Reset(); ## FIXME: Is this dangerous? if PositionSublist( filename, ".autodoc" ) <> fail then plain_text_mode := true; fi; filestream := InputTextFile( filename ); if filestream = fail then Error( "could not open ", filename ); fi; line_number := 0; while true do if rest_of_file_skipped = true then rest_of_file_skipped := false; break; fi; current_line := ReadLineWithLineCount( filestream ); if current_line = fail then break; fi; current_line_unedited := ShallowCopy( current_line ); NormalizeWhitespace( current_line ); current_command := Scan_for_AutoDoc_Part( current_line, plain_text_mode ); if current_command[ 1 ] <> false then if autodoc_read_line <> fail then autodoc_read_line := true; fi; if not IsBound( command_function_record.(current_command[ 1 ]) ) then ErrorWithPos("unknown AutoDoc command ", current_command[ 1 ]); fi; command_function_record.(current_command[ 1 ])(); continue; fi; current_line := current_command[ 2 ]; if autodoc_read_line = true or autodoc_read_line = fail then was_declaration := Scan_for_Declaration_part( ); if not was_declaration and autodoc_read_line <> fail then autodoc_read_line := false; fi; fi; od; CloseStream( filestream ); od; end ); AutoDoc-2025.10.16/gap/Markdown.gi0000644000175100017510000001620115074117054015732 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later ## InstallGlobalFunction( INSERT_IN_STRING_WITH_REPLACE, function( string, new_string, position, nr_letters_to_be_replaced ) return Concatenation( string{[ 1 .. position - 1 ]}, new_string, string{[ position + nr_letters_to_be_replaced .. Length( string ) ]} ); end ); ## InstallGlobalFunction( CONVERT_LIST_OF_STRINGS_IN_MARKDOWN_TO_GAPDOC_XML, function( string_list ) local i, current_list, current_string, max_line_length, current_position, already_in_list, command_list_with_translation, beginning, commands, position_of_command, insert, beginning_whitespaces, temp, string_list_temp, skipped, already_inserted_paragraph, in_list, in_item; ## Check for paragraphs by turning an empty string into

already_inserted_paragraph := false; for i in [ 1 .. Length( string_list ) ] do if NormalizedWhitespace( string_list[ i ] ) = "" then if already_inserted_paragraph = false then string_list[ i ] := "

"; already_inserted_paragraph := true; fi; else already_inserted_paragraph := false; fi; i := i + 1; od; ## We need to find lists. Lists are indicated by a beginning ## *, -, or +. Lists can be nested. Save list as list of strings, ## and at the same time, concatenate all the other strings ## FIXME: @Max: where are my regular expressions? ## Do this in several iterations max_line_length := Maximum( List( string_list, Length ) ); current_position := 1; while current_position < max_line_length do already_in_list := false; i := 1; skipped := false; ## maybe make the first line marked by definition? while i <= Length( string_list ) do if PositionSublist( string_list[ i ], " fail then skipped := true; fi; if PositionSublist( string_list[ i ], "]]>" ) <> fail then skipped := false; i := i + 1; continue; fi; if skipped = true then i := i + 1; continue; fi; if PositionSublist( string_list[ i ], "* " ) = current_position or PositionSublist( string_list[ i ], "+ " ) = current_position or PositionSublist( string_list[ i ], "- " ) = current_position then if not ForAll( [ 1 .. current_position - 1 ], j -> string_list[ i ][ j ] = ' ' ) then i := i + 1; continue; fi; if already_in_list = false then Add( string_list, "", i ); Add( string_list, "", i ); i := i + 2; string_list[ i ] := string_list[ i ]{[ current_position + 2 .. Length( string_list[ i ] ) ]}; already_in_list := true; else Add( string_list, "", i ); Add( string_list, "", i ); i := i + 2; string_list[ i ] := string_list[ i ]{[ current_position + 2 .. Length( string_list[ i ] ) ]}; fi; ## find out if line has to be marked ## THIS is buggy. Discuss this ## FIXME: This causes strange problems with GAPDoc. # if PositionSublist( string_list[ i ], "**" ) = 1 then # string_list[ i ] := string_list[ i ]{[ 3 .. Length( string_list[ i ] ) ]}; # temp := string_list[ i ]; # string_list[ i ] := string_list[ i - 1 ]; # string_list[ i - 1 ] := temp; # Add( string_list, "", i - 1 ); # Add( string_list, "", i + 1 ); # i := i + 2; # fi; elif already_in_list = true and PositionSublist( string_list[ i ], " " ) > current_position then already_in_list := false; Add( string_list, "", i ); Add( string_list, "", i ); i := i + 2; fi; i := i + 1; od; if already_in_list = true then Add( string_list, "" ); Add( string_list, "" ); fi; current_position := current_position + 1; od; # Remove

if in List but not in item in_list := 0; in_item := 0; for current_position in [ 1 .. Length( string_list ) ] do if PositionSublist( string_list[ current_position ], "" ) <> fail then in_list := in_list + 1; fi; if PositionSublist( string_list[ current_position ], "" ) <> fail then in_list := in_list - 1; fi; if PositionSublist( string_list[ current_position ], "" ) <> fail then in_item := in_item + 1; fi; if PositionSublist( string_list[ current_position ], "" ) <> fail then in_item := in_item - 1; fi; if in_item < in_list and string_list[ current_position ] = "

" then string_list[ current_position ] := ""; fi; od; ## Find commands command_list_with_translation := [ [ "$$", "Display" ], [ "$", "Math" ], [ "`", "Code" ], [ "**", "Emph" ], [ "__", "Emph" ] ]; ## special handling for \$ for i in [ 1 .. Length( string_list ) ] do string_list[ i ] := ReplacedString( string_list[ i ], "\\$", "$" ); od; for commands in command_list_with_translation do beginning := true; skipped := false; for i in [ 1 .. Length( string_list ) ] do if PositionSublist( string_list[ i ], " fail then skipped := true; fi; if PositionSublist( string_list[ i ], "]]>" ) <> fail then skipped := false; fi; if skipped = true then continue; fi; while PositionSublist( string_list[ i ], commands[ 1 ] ) <> fail do position_of_command := PositionSublist( string_list[ i ], commands[ 1 ] ); if beginning = true then insert := Concatenation( "<", commands[ 2 ], ">" ); else insert := Concatenation( "" ); fi; string_list[ i ] := INSERT_IN_STRING_WITH_REPLACE( string_list[ i ], insert, position_of_command, Length( commands[ 1 ] ) ); beginning := not beginning; od; od; if beginning = false then Error( "did you forget some ", commands[ 1 ] ); fi; od; return string_list; end ); AutoDoc-2025.10.16/gap/ToolFunctions.gd0000644000175100017510000000114715074117054016754 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later DeclareGlobalFunction( "AUTODOC_CreateDirIfMissing" ); DeclareGlobalFunction( "AUTODOC_CurrentDirectory" ); DeclareGlobalFunction( "AUTODOC_OutputTextFile" ); DeclareGlobalFunction( "AutoDoc_WriteDocEntry" ); DeclareGlobalFunction( "AutoDoc_CreatePrintOnceFunction" ); DeclareGlobalFunction( "AUTODOC_Diff" ); DeclareGlobalFunction( "AUTODOC_TestWorkSheet" ); DeclareGlobalFunction( "AUTODOC_FormatDate" ); AutoDoc-2025.10.16/gap/DocumentationTree.gi0000644000175100017510000004744715074117054017621 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later ## BindGlobal( "AUTODOC_IdentifierLetters", "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" ); DeclareRepresentation( "IsTreeForDocumentationRep", IsAttributeStoringRep and IsTreeForDocumentation, [ ] ); BindGlobal( "TheFamilyOfDocumentationTrees", NewFamily( "TheFamilyOfDocumentationTrees" ) ); BindGlobal( "TheTypeOfDocumentationTrees", NewType( TheFamilyOfDocumentationTrees, IsTreeForDocumentationRep ) ); ## Metatype, specify later DeclareRepresentation( "IsTreeForDocumentationNodeRep", IsAttributeStoringRep and IsTreeForDocumentationNode, [ ] ); BindGlobal( "TheFamilyOfDocumentationTreeNodes", NewFamily( "TheFamilyOfDocumentationTreeNodes" ) ); BindGlobal( "TheTypeOfDocumentationTreeNodes", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationNodeRep ) ); ## Chapter node DeclareRepresentation( "IsTreeForDocumentationNodeForChapterRep", IsTreeForDocumentationNodeRep, [ ] ); BindGlobal( "TheTypeOfDocumentationTreeNodesForChapter", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationNodeForChapterRep ) ); ## Section node DeclareRepresentation( "IsTreeForDocumentationNodeForSectionRep", IsTreeForDocumentationNodeRep, [ ] ); BindGlobal( "TheTypeOfDocumentationTreeNodesForSection", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationNodeForSectionRep ) ); ## Subsection node DeclareRepresentation( "IsTreeForDocumentationNodeForSubsectionRep", IsTreeForDocumentationNodeRep, [ ] ); BindGlobal( "TheTypeOfDocumentationTreeNodesForSubsection", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationNodeForSubsectionRep ) ); ## Text node DeclareRepresentation( "IsTreeForDocumentationNodeForTextRep", IsTreeForDocumentationNodeRep, [ ] ); BindGlobal( "TheTypeOfDocumentationTreeNodesForText", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationNodeForTextRep ) ); ## ManItem node DeclareRepresentation( "IsTreeForDocumentationNodeForManItemRep", IsTreeForDocumentationNodeRep, [ ] ); BindGlobal( "TheTypeOfDocumentationTreeNodesForManItem", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationNodeForManItemRep ) ); ## Group Node DeclareRepresentation( "IsTreeForDocumentationNodeForGroupRep", IsTreeForDocumentationNodeRep, [ ] ); BindGlobal( "TheTypeOfDocumentationTreeNodesForGroup", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationNodeForGroupRep ) ); ## DeclareRepresentation DeclareRepresentation( "IsTreeForDocumentationChunkNodeRep", IsTreeForDocumentationNodeRep, [ ] ); BindGlobal( "TheTypeOfDocumentationTreeChunkNodes", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationChunkNodeRep ) ); ## DeclareRepresentation DeclareRepresentation( "IsTreeForDocumentationExampleNodeRep", IsTreeForDocumentationNodeRep, [ ] ); BindGlobal( "TheTypeOfDocumentationTreeExampleNodes", NewType( TheFamilyOfDocumentationTreeNodes, IsTreeForDocumentationExampleNodeRep ) ); ################################### ## ## Tools ## ################################### ## InstallGlobalFunction( AUTODOC_TREE_NODE_NAME_ITERATOR, function( tree ) local curr_val; curr_val := tree!.node_name_iterator; tree!.node_name_iterator := curr_val + 1; return curr_val; end ); ## InstallGlobalFunction( AUTODOC_LABEL_OF_CONTEXT, function( context ) local label; if not IsList( context ) then Error( "wrong type of context" ); fi; if IsString( context ) then label := context; elif Length( context ) = 1 then label := Concatenation( "Chapter_", context[ 1 ] ); elif Length( context ) = 2 then label := Concatenation( "Chapter_", context[ 1 ], "_Section_", context[ 2 ] ); elif Length( context ) = 3 then label := Concatenation( "Chapter_", context[ 1 ], "_Section_", context[ 2 ], "_Subsection_", context[ 3 ] ); else Error( "wrong type of context" ); fi; label := Filtered(label, x -> x in AUTODOC_IdentifierLetters); return label; end ); ################################### ## ## Constructors ## ################################### ## InstallMethod( DocumentationTree, [ ], function( ) local tree; tree := rec( content := [ ], # a list of nodes nodes_by_label := rec( ), node_name_iterator := 0, current_level := 0, TitlePage := rec( ), chunks := rec( ), ); ObjectifyWithAttributes( tree, TheTypeOfDocumentationTrees ); return tree; end ); ## create a chapter, section or subsection InstallMethod( StructurePartInTree, [ IsTreeForDocumentation, IsList ], function( tree, context ) local label, parent, new_node, type; if IsEmpty( context ) then return tree; fi; # if the part already exist, use that label := AUTODOC_LABEL_OF_CONTEXT( context ); if IsBound( tree!.nodes_by_label.( label ) ) then return tree!.nodes_by_label.( label ); fi; parent := StructurePartInTree( tree, context{[1..Length(context)-1]} ); new_node := rec( content := [ ], level := tree!.current_level, name := context[ Length( context ) ], chapter_info := context ); if Length( context ) = 1 then type := TheTypeOfDocumentationTreeNodesForChapter; elif Length( context ) = 2 then type := TheTypeOfDocumentationTreeNodesForSection; elif Length( context ) = 3 then type := TheTypeOfDocumentationTreeNodesForSubsection; fi; ObjectifyWithAttributes( new_node, type, Label, label ); tree!.nodes_by_label.( label ) := new_node; Add( parent!.content, new_node ); return new_node; end ); ## InstallMethod( DocumentationExample, [ IsTreeForDocumentation ], function( tree ) local node, label; node := rec( content := [ ], level := tree!.current_level ); label := Concatenation( "Example_", String( AUTODOC_TREE_NODE_NAME_ITERATOR( tree ) ) ); ObjectifyWithAttributes( node, TheTypeOfDocumentationTreeExampleNodes, Label, label ); tree!.nodes_by_label.( label ) := node; return node; end ); ## InstallMethod( DocumentationChunk, [ IsTreeForDocumentation, IsString ], function( tree, name ) local node; if IsBound( tree!.chunks.( name ) ) then return tree!.chunks.( name ); fi; node := rec( content := [ ], level := tree!.current_level ); ObjectifyWithAttributes( node, TheTypeOfDocumentationTreeChunkNodes, Label, name ); tree!.chunks.( name ) := node; return node; end ); ## InstallMethod( DocumentationManItem, [ IsTreeForDocumentation ], function( tree ) local node, name; node := rec( description := [ ], return_value := [ ], level := tree!.current_level ); ObjectifyWithAttributes( node, TheTypeOfDocumentationTreeNodesForManItem ); name := Concatenation( "ManItem_", String( AUTODOC_TREE_NODE_NAME_ITERATOR( tree ) ) ); tree!.nodes_by_label.( name ) := node; node!.content := node!.description; return node; end ); ## InstallMethod( SetManItemToDescription, [ IsTreeForDocumentationNodeForManItemRep ], function( node ) node!.content := node!.description; end ); ## InstallMethod( SetManItemToReturnValue, [ IsTreeForDocumentationNodeForManItemRep ], function( node ) node!.content := node!.return_value; end ); ## InstallMethod( DocumentationGroup, [ IsTreeForDocumentation, IsString ], function( tree, group_name ) local group, name; name := Concatenation( "GROUP_", group_name ); if IsBound( tree!.nodes_by_label.( name ) ) then return tree!.nodes_by_label.( name ); fi; group := rec( content := [ ], level := tree!.current_level ); ObjectifyWithAttributes( group, TheTypeOfDocumentationTreeNodesForGroup, Label, name ); tree!.nodes_by_label.( name ) := group; group!.is_added := false; return group; end ); ## InstallMethod( DocumentationGroup, [ IsTreeForDocumentation, IsString, IsList ], function( tree, group_name, context ) local name, group; name := Concatenation( "GROUP_", group_name ); if IsBound( tree!.nodes_by_label.( name ) ) then return tree!.nodes_by_label.( name ); fi; context := AUTODOC_LABEL_OF_CONTEXT( context ); group := DocumentationGroup( tree, group_name ); Add( tree!.nodes_by_label.( context ), group ); group!.is_added := true; return group; end ); ## InstallMethod( Add, [ IsTreeForDocumentationNode, IsTreeForDocumentationNode ], function( parent_node, node ) Add( parent_node!.content, node ); end ); ## InstallMethod( Add, [ IsTreeForDocumentationNode, IsString ], function( parent_node, string ) Add( parent_node!.content, string ); end ); ## InstallMethod( Add, [ IsTreeForDocumentation, IsTreeForDocumentationNodeForManItemRep and HasChapterInfo ], function( tree, node ) local chapter_info, section; chapter_info := ChapterInfo( node ); section := SectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ] ); Add( section, node ); end ); ## InstallMethod( Add, [ IsTreeForDocumentation, IsTreeForDocumentationNodeForManItemRep and HasGroupName ], function( tree, node ) local group; group := DocumentationGroup( tree, GroupName( node ) ); Add( group, node ); end ); ## InstallMethod( Add, [ IsTreeForDocumentation, IsTreeForDocumentationNodeForManItemRep and HasGroupName and HasChapterInfo ], function( tree, node ) local chapter_info, group; chapter_info := ChapterInfo( node ); group := DocumentationGroup( tree, GroupName( node ), chapter_info ); Add( group, node ); end ); ## InstallMethod( Add, [ IsTreeForDocumentation, IsTreeForDocumentationNode, IsList ], function( tree, node, context ) local label, context_node; label := AUTODOC_LABEL_OF_CONTEXT( context ); context_node := tree!.nodes_by_label.(label); Add( context_node, node ); end ); ## InstallMethod( IsEmptyNode, [ IsTreeForDocumentationNode ], function( node ) if IsBound( node!.content ) then return ForAll( node!.content, IsEmptyNode ); fi; return false; end ); ## InstallMethod( IsEmptyNode, [ IsString ], function( node ) return node = ""; end ); ## InstallMethod( IsEmptyNode, [ IsTreeForDocumentationNodeForManItemRep ], function( node ) return false; end ); #################################### ## ## Add functions ## #################################### ## InstallMethod( ChapterInTree, [ IsTreeForDocumentation, IsString ], function( tree, name ) return StructurePartInTree( tree, [ name ] ); end ); ## InstallMethod( SectionInTree, [ IsTreeForDocumentation, IsString, IsString ], function( tree, chapter_name, section_name ) return StructurePartInTree( tree, [ chapter_name, section_name ] ); end ); ## InstallMethod( SubsectionInTree, [ IsTreeForDocumentation, IsString, IsString, IsString ], function( tree, chapter_name, section_name, subsection_name ) return StructurePartInTree( tree, [ chapter_name, section_name, subsection_name ] ); end ); ############################################# ## ## Write functions ## ############################################# BindGlobal( "WriteChunks", function( tree, path_to_xmlfiles, level_value ) local chunks_stream, filename, chunk_names, current_chunk_name, current_chunk; filename := "_Chunks.xml"; chunks_stream := AUTODOC_OutputTextFile( path_to_xmlfiles, filename ); chunk_names := RecNames( tree!.chunks ); for current_chunk_name in chunk_names do current_chunk := tree!.chunks.( current_chunk_name ); AppendTo( chunks_stream, "<#GAPDoc Label=\"", current_chunk_name, "\">\n" ); if IsBound( current_chunk!.content ) then WriteDocumentation( current_chunk!.content, chunks_stream, level_value ); fi; AppendTo( chunks_stream, "\n<#/GAPDoc>\n" ); od; CloseStream( chunks_stream ); end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentation, IsDirectory, IsInt ], function( tree, path_to_xmlfiles, level_value ) local stream, i; stream := AUTODOC_OutputTextFile( path_to_xmlfiles, _AUTODOC_GLOBAL_OPTION_RECORD.AutoDocMainFile ); AppendTo( stream, AUTODOC_XML_HEADER ); for i in tree!.content do if not IsTreeForDocumentationNodeForChapterRep( i ) then Error( "this should never happen" ); fi; ## FIXME: If there is anything else than a chapter, this will break! WriteDocumentation( i, stream, path_to_xmlfiles, level_value ); od; WriteChunks( tree, path_to_xmlfiles, level_value ); # Workaround for issue #65 if IsEmpty( tree!.content ) then AppendTo( stream, " \n" ); fi; CloseStream( stream ); end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationNodeForChapterRep, IsStream, IsDirectory, IsInt ], function( node, stream, path_to_xmlfiles, level_value ) local filename, chapter_stream, replaced_name; if node!.level > level_value then return; fi; if ForAll( node!.content, IsEmptyNode ) then return; fi; if IsBound( node!.title_string ) then replaced_name := NormalizedWhitespace( node!.title_string ); else replaced_name := ReplacedString( node!.name, "_", " " ); fi; # Remove any characters outside of A-Za-z0-9 and -, +, _ from the filename. # See issues #77 and #78 filename := Filtered( Label( node ), x -> x in AUTODOC_IdentifierLetters); filename := Concatenation( "_", filename, ".xml" ); chapter_stream := AUTODOC_OutputTextFile( path_to_xmlfiles, filename ); AppendTo( stream, "<#Include SYSTEM \"", filename, "\">\n" ); AppendTo( chapter_stream, AUTODOC_XML_HEADER ); AppendTo( chapter_stream, "\n" ); AppendTo( chapter_stream, Concatenation( [ "", replaced_name, "\n\n" ] ) ); WriteDocumentation( node!.content, chapter_stream, level_value ); AppendTo( chapter_stream, "\n\n" ); CloseStream( chapter_stream ); end ); ## InstallMethod( WriteDocumentation, [ IsList, IsStream, IsInt ], function( node_list, filestream, level_value ) local current_string_list, i, last_position; i := 1; current_string_list := [ ]; for i in [ 1 .. Length( node_list ) ] do if IsString( node_list[ i ] ) then Add( current_string_list, ShallowCopy( node_list[ i ] ) ); else if current_string_list <> [ ] then current_string_list := CONVERT_LIST_OF_STRINGS_IN_MARKDOWN_TO_GAPDOC_XML( current_string_list ); Perform( current_string_list, function( i ) WriteDocumentation( i, filestream, level_value ); end ); current_string_list := [ ]; fi; WriteDocumentation( node_list[ i ], filestream, level_value ); AppendTo( filestream, "\n" ); fi; od; if current_string_list <> [ ] then current_string_list := CONVERT_LIST_OF_STRINGS_IN_MARKDOWN_TO_GAPDOC_XML( current_string_list ); Perform( current_string_list, function( i ) WriteDocumentation( i, filestream, level_value ); end ); fi; end ); ## InstallMethod( WriteDocumentation, [ IsString, IsStream, IsInt ], function( text, filestream, level_value ) ## In case the list is empty, do nothing. ## Once the empty string = empty list bug is fixed, ## this could be removed. text := Chomp( text ); if NormalizedWhitespace( text ) = "" then return; fi; AppendTo( filestream, text, "\n" ); end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationNodeForSectionRep, IsStream, IsInt ], function( node, filestream, level_value ) local replaced_name; if node!.level > level_value then return; fi; if ForAll( node!.content, IsEmptyNode ) then return; fi; if IsBound( node!.title_string ) then replaced_name := NormalizedWhitespace( node!.title_string ); else replaced_name := ReplacedString( node!.name, "_", " " ); fi; AppendTo( filestream, "

\n" ); AppendTo( filestream, Concatenation( [ "", replaced_name, "\n\n" ] ) ); WriteDocumentation( node!.content, filestream, level_value ); AppendTo( filestream, "
\n\n" ); end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationNodeForSubsectionRep, IsStream, IsInt ], function( node, filestream, level_value ) local replaced_name; if node!.level > level_value then return; fi; if ForAll( node!.content, IsEmptyNode ) then return; fi; if IsBound( node!.title_string ) then replaced_name := NormalizedWhitespace( node!.title_string ); else replaced_name := ReplacedString( node!.name, "_", " " ); fi; AppendTo( filestream, "\n" ); AppendTo( filestream, Concatenation( [ "", replaced_name, "\n\n" ] ) ); WriteDocumentation( node!.content, filestream, level_value ); AppendTo( filestream, "\n\n" ); end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationNodeForManItemRep, IsStream, IsInt ], function( node, filestream, level_value ) if node!.level > level_value then return; fi; AutoDoc_WriteDocEntry( filestream, [ node ], fail, level_value ); end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationNodeForGroupRep, IsStream, IsInt ], function( node, filestream, level_value ) local heading; if node!.level > level_value then return; fi; heading := fail; if IsBound( node!.title_string ) then heading := node!.title_string; fi; AutoDoc_WriteDocEntry( filestream, node!.content, heading, level_value ); end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationChunkNodeRep, IsStream, IsInt ], function( node, filestream, level_value ) if node!.level > level_value then return; fi; WriteDocumentation( Concatenation( "<#Include Label=\"", Label( node ), "\">" ), filestream, level_value ); end ); ## InstallMethod( WriteDocumentation, [ IsTreeForDocumentationExampleNodeRep, IsStream, IsInt ], function( node, filestream, level_value ) local contents, i, tested, inserted_string; if node!.level > level_value then return; fi; contents := node!.content; tested := node!.is_tested_example; if tested = true then inserted_string := "Example"; elif tested = false then inserted_string := "Log"; else Error( "This should not happen!" ); fi; AppendTo( filestream, "<", inserted_string, ">. i := ReplacedString(i, "]]>", "]]]]>"); AppendTo( filestream, i, "\n" ); od; AppendTo( filestream, "]]>\n\n" ); end ); AutoDoc-2025.10.16/gap/AutoDocMainFunction.gd0000644000175100017510000000404415074117054020016 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later BindGlobal( "AUTODOC_XML_HEADER", Concatenation( "\n\n", "\n" ) ); DeclareGlobalFunction( "AUTODOC_SetIfMissing" ); DeclareGlobalFunction( "AUTODOC_APPEND_STRING_ITERATIVE" ); DeclareGlobalFunction( "AUTODOC_MergeRecords" ); DeclareGlobalFunction( "AUTODOC_PROCESS_INTRO_STRINGS" ); DeclareGlobalFunction( "AutoDocScanFiles" ); ## Global option record BindGlobal( "_AUTODOC_GLOBAL_OPTION_RECORD", rec( AutoDocMainFile := "_AutoDocMainFile.xml" ) ); ## ## This function creates a title file. It must be called with the package name and the path to doc files. DeclareGlobalFunction( "CreateTitlePage" ); ## ## This function creates _entities.xml, which is included by the default main page DeclareGlobalFunction( "CreateEntitiesPage" ); ## ## This function creates the main page. Do not call it out of context. DeclareGlobalFunction( "CreateMainPage" ); ## ## This function is for internal use only. ## It creates names for the default chapters and sections. DeclareGlobalFunction( "CreateDefaultChapterData" ); DeclareGlobalFunction( "ExtractTitleInfoFromPackageInfo" ); #! @Chapter AutoDoc worksheets #! @Section Worksheets #! @Description #! The intention of these function is to create stand-alone pdf and html files #! using AutoDoc without having them associated to a package. #! It uses the same optional records as the &AutoDoc; command itself, but instead of #! a package name there should be a filename or a list of filenames containing AutoDoc #! text from which the documents are created. Please see the &AutoDoc; command for more #! information about this and have a look at for a simple worksheet example. #! @Arguments list_of_filenames : options DeclareGlobalFunction( "AutoDocWorksheet" ); AutoDoc-2025.10.16/CHANGES.md0000644000175100017510000002153515074117054014460 0ustar runnerrunnerThis file describes changes in the AutoDoc package. 2025.10.16 - Make handling `Date` in `PackageInfo.g` more strict (previously some malformed variants were accepted to deal with very old packages, but by now all packages are compliant) - Remove a bunch of features that were deprecated since 2019: - `AutoDoc` option `scaffold.gapdoc_latex_options` has been replaced by `gapdoc.LaTeXOptions` - `AutoDoc` option `maketest` has been superseded by `extract_examples` - Various AutoDoc commands were removed (see the manual for replacements) - `@EndSection`, `@EndSubsection` - `@AutoDoc`, `@BeginAutoDoc`, `@EndAutoDoc` - `@System`, `@BeginSystem`, `@EndSystem`, `@InsertSystem` - `@AutoDocPlainText`, `@BeginAutoDocPlainText`, `@EndAutoDocPlainText` 2025.05.09 - Add `InfoAutoDoc` info class for messages - Various janitorial changes 2023.06.19 - Revise handling of chunks XML file - Remove `AUTODOC_AbsolutePath` - Don't build PDF docs if `NOPDF` environment variable is set - Various janitorial changes 2022.10.20 - Prevent some file descriptor leaks - Do not try to read non-existing file `gap/ContextObject.gd` 2022.07.10 - Output all entities defined via either the `scaffold.entities` option to AutoDoc (or equivalently via the `AutoDoc.entities` record in `PackageInfo.g`) into a file `_entities.xml`, so that they can also be used with a hand-made main XML file (and not just when AutoDoc generated the main page) - Remove `&see;` entity from the default list of entities 2022.03.10 - Strip trailing newlines in `PostalAddress` and some TitlePage elements - Allow AutoDoc record in `PackageInfo.g` to not contain a TitlePage entry 2022.02.24 - true/false are keywords, not just code: use K tags - extract examples: do not flush pkgname.tst - remove duplicate entries in autodoc.files 2020.08.11 - Add support for using the string `]]>` in examples - Add support for `DeclareGlobalName` (new in GAP 4.12) - Add `extract_examples.skip_empty_in_numbering` option - Enhance `extract_examples` to remove outdated .tst files (e.g. if chapter number changes, we won't leave outdated extracted .tst examples behind) - Fix a warning about a missing file `/doc/_Chunks.xml` which appeared when building the documentation of some packages 2019.09.04 - Deprecate `@BeginAutoDoc` and `@EndAutoDoc`; they will be removed in a future AutoDoc version - Deprecate `@BeginAutoDocPlainText` and `@EndAutoDocPlainText`; they will be removed in a future AutoDoc version - Fix `@BeginCode` / `@EndCode` / `@InsertCode`, which were broken in version 2019.07.03 2019.07.24 - Add support for ISO 8601 dates in package metadata (to prepare for GAP adding official support for this in the future) - Remove undocumented and long-unused support entities specified using a raw `` entity string - Fix the `&see;` entity we always generate (for legacy support) to display the correct output in LaTeX / PDF mode - Fix support for chunks with names / labels that contain spaces (GAPDoc does not like these, so we replace the spaces by underscores) 2019.07.17 - Fix bug in `extract_examples` option that could result in invalid .tst files 2019.07.03 - Make Chunks compatible with GAPDoc chunks - Tweak two error messages, add two more error checks - Check that gapdoc.files is a list of strings - Add `@GroupTitle` command (thanks to Glen Whitney) - Make @Begin.../@EndExampleSession respect plain_text_mode (thanks to Glen Whitney) - Handle documentation of DeclareCategoryCollection declarations (thanks to Glen Whitney) - Repair minor omissions/imprecisions in AutoDoc() function doc (thanks to Glen Whitney) - Improve manual further 2019.05.20 - Ensure that starting a "manpage" (= documentation for a filter, function, property, ...) ends any active subsection (in GAPDoc, manpages are equivalent to subsections internally, and hence cannot be nested in each other) - Add deprecation warnings for @InsertSystem, @System, @BeginSystem, @EndSystem (use @Chunk etc. instead), and also @EndSection, @EndSubsection - Rename scaffold.gapdoc_latex_options to gapdoc.LaTeXOptions. The old name is still supported, but triggers a deprecation warning. - Update copyright information and author's contact data - Minor fixes in the manual 2019.04.10 - Add opt.extract_examples to AutoDoc function - Add @NotLatex command to complement @LatexOnly - Allow disabling title page creation, by teaching `AutoDoc()` to correctly handle `scaffold := rec( TitlePage := false )` instead of raising an error - When generating a manual title page, only include persons as authors for which IsAuthor is set to true in PackageInfo.g - Some improvements to the manual - Various internal changes 2019.02.22 - Updated changes file 2019.02.21 - Removed possibility to mark function arguments via curly braces, as {A}, as it caused problems with writing {} in math mode. 2019.02.20 - Accept single backticks to indicate inline code spans - Added possibility to mark function arguments via curly braces, as {A} 2018.09.20 - Scan bracket `\[\]` declarations correctly (PR #162) - Removed the hardcoded utf8 option, make it overridable via gapdoc_latex_option - Allow AutoDoc() to take absolute dirs and run from any dir (thanks to Glen Whitney) - Add a test suite for AutoDoc (thanks to Glen Whitney) - Fix documenting DeclareInfoClass 2018.02.14 - Added @*Title commands to specify titles for Chapters etc. - Document @BeginExampleSession instead of @ExampleSession - Document the aliases @Example, @ExampleSession, @Log, and @LogSession - Improve manual (thanks to Chris Wensley): - fix a few typos - added abstract and acknowledgments - added bibliography file AutoDoc.bib - added checklist subsection 1.3.3 - added some index entries - change makedoc.g to highlight some useful features of the AutoDoc() function - Various other tweaks and fixes 2017.09.08 - Add ChapterLabel, SectionLabel, and SubsectionLabel - Add ExampleSession environment to support GAPDoc-Style examples - Add support for documenting DeclareConstructor - Empty lines in AutoDoc comments start a new paragraph, as in TeX - Improve @Example documentation - Fix some spelling mistakes in the manual - Fix support for KeyDependendOperations (see issue #124) - Don't show a return value if no @Returns is given - Various other tweaks and fixes 2016.12.04: - Revise and officially document the `entities` option for AutoDoc() 2016.11.26: - Use english month names on title pages - Ignore empty dependency lists in PackageInfo.g files - Better error message when .six file is not available 2016.03.08: - Fix the "empty index" workaround from the previous release 2016.03.04: - Improved the manual. - AutoDoc can now be instructed to invoke GAPDoc in such a way that links in the generated documentation to the GAP reference manual use relative paths. - Also scan for .autodoc files (Issue #104) - Workaround a problem with GAPDoc where an empty index could lead to an error. - Allow entities in chapter and section titles. - Fix a bug where the indentation for code blocks was not preserved. 2016.02.24: - Again improved the error messages produced by the parser. - Document worksheets (and fix them -- the previous release broke them). - Removed the @URL documentation comment command. - Add current directory to default list of directories which are scanned for *.{g,gi,gd} files containing documentation. - Fixed various typos and other mistakes in the documentation. - Make it possible to tell AutoDoc to build manuals with relative paths (issue #103). 2016.02.16: - AutoDoc does not anymore produce an error when invoked on a new project which has no documentation yet (issue #65) - Various errors in the parser now produce much better error messages, with information in which file and line the error occurred, and what the error is (issue #89) - Files generated by AutoDoc for chapters as well as the "main" file now have names starting with an underscore, to make it easy to distinguish generated files from those maintained by hand. - Removed the old "Declare*WithDoc" API. Any packages still using it must upgrade to use documentation comments. 2016.01.31: - Improved the documentation of AutoDoc itself - Some code is now more robust, detects more error conditions and reports them clearly to the user, instead of triggering some weird error later on. - Lots of minor tweaks, fixes and cleanip 2016-01-21: - The AutoDoc() function now accepts IsDirectory() objects as first argument, and you can omit the first argument (it then defaults to the current directory). Packages using AutoDoc may want to adapt their makedoc.g to use this new facility for improved robustness. AutoDoc-2025.10.16/init.g0000644000175100017510000000076315074117054014201 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later ReadPackage( "AutoDoc", "gap/DocumentationTree.gd" ); ReadPackage( "AutoDoc", "gap/Parser.gd" ); ReadPackage( "AutoDoc", "gap/AutoDocMainFunction.gd" ); ReadPackage( "AutoDoc", "gap/ToolFunctions.gd" ); ReadPackage( "AutoDoc", "gap/Magic.gd" ); ReadPackage( "AutoDoc", "gap/Markdown.gd" ); AutoDoc-2025.10.16/PackageInfo.g0000644000175100017510000001112315074117054015375 0ustar runnerrunner# AutoDoc: Generate documentation from GAP source code # # Copyright of AutoDoc belongs to its developers. # Please refer to the COPYRIGHT file for details. # # SPDX-License-Identifier: GPL-2.0-or-later SetPackageInfo( rec( PackageName := "AutoDoc", Subtitle := "Generate documentation from GAP source code", Version := "2025.10.16", Date := ~.Version{[ 1 .. 10 ]}, Date := Concatenation( ~.Date{[ 9, 10 ]}, "/", ~.Date{[ 6, 7 ]}, "/", ~.Date{[ 1 .. 4 ]} ), License := "GPL-2.0-or-later", Persons := [ rec( LastName := "Gutsche", FirstNames := "Sebastian", IsAuthor := true, IsMaintainer := true, Email := "gutsche@mathematik.uni-siegen.de", WWWHome := "https://algebra.mathematik.uni-siegen.de/gutsche/", PostalAddress := Concatenation( "Department Mathematik\n", "Universität Siegen\n", "Walter-Flex-Straße 3\n", "57072 Siegen\n", "Germany" ), Place := "Siegen", Institution := "Universität Siegen" ), rec( LastName := "Horn", FirstNames := "Max", IsAuthor := true, IsMaintainer := true, Email := "mhorn@rptu.de", WWWHome := "https://www.quendi.de/math", GitHubUsername := "fingolfin", PostalAddress := Concatenation( "Fachbereich Mathematik\n", "RPTU Kaiserslautern-Landau\n", "Gottlieb-Daimler-Straße 48\n", "67663 Kaiserslautern\n", "Germany" ), Place := "Kaiserslautern, Germany", Institution := "RPTU Kaiserslautern-Landau" ), # Contributors: rec( LastName := "Barakat", FirstNames := "Mohamed", IsAuthor := false, IsMaintainer := false, ), rec( LastName := "Pfeiffer", FirstNames := "Markus", IsAuthor := false, IsMaintainer := false, ), rec( LastName := "Skartsæterhagen", FirstNames := "Øystein", IsAuthor := false, IsMaintainer := false, ), rec( LastName := "Wensley", FirstNames := "Chris", IsAuthor := false, IsMaintainer := false, ), rec( LastName := "Whitney", FirstNames := "Glen", IsAuthor := false, IsMaintainer := false, ), rec( LastName := "Zickgraf", FirstNames := "Fabian", IsAuthor := false, IsMaintainer := false, ), ], Status := "deposited", PackageWWWHome := "https://gap-packages.github.io/AutoDoc/", SourceRepository := rec( Type := "git", URL := Concatenation( "https://github.com/gap-packages/", ~.PackageName ), ), IssueTrackerURL := Concatenation( ~.SourceRepository.URL, "/issues" ), PackageWWWHome := Concatenation( "https://gap-packages.github.io/", ~.PackageName ), README_URL := Concatenation( ~.PackageWWWHome, "/README.md" ), PackageInfoURL := Concatenation( ~.PackageWWWHome, "/PackageInfo.g" ), ArchiveURL := Concatenation( ~.SourceRepository.URL, "/releases/download/v", ~.Version, "/", ~.PackageName, "-", ~.Version ), ArchiveFormats := ".tar.gz", AbstractHTML := "", PackageDoc := rec( BookName := "AutoDoc", ArchiveURLSubset := ["doc"], HTMLStart := "doc/chap0_mj.html", PDFFile := "doc/manual.pdf", SixFile := "doc/manual.six", LongTitle := "Generate documentation from GAP source code", ), Dependencies := rec( GAP := ">= 4.5", NeededOtherPackages := [ [ "GAPDoc", ">= 1.6.3" ] ], SuggestedOtherPackages := [ ], ExternalConditions := [], ), AvailabilityTest := ReturnTrue, TestFile := "tst/testall.g", Keywords := [ "Automatic documentation, GAP, GAPDoc" ], AutoDoc := rec( entities := rec( VERSION := ~.Version, DATE := ~.Date, io := "io", PackageName := "PackageName", ), TitlePage := rec( Copyright := Concatenation( "©right; 2012-2022 by Sebastian Gutsche and Max Horn

\n\n", "This package may be distributed under the terms and conditions ", "of the GNU Public License Version 2 or (at your option) any later version.\n" ), Abstract := Concatenation( "&AutoDoc; is a &GAP; package whose purpose is to aid ", "&GAP; package authors in creating and maintaining the ", "documentation of their packages.\n" ), Acknowledgements := Concatenation( "This documentation was prepared using the ", "&GAPDoc; package .\n", "

\n" ), ), ), ));