00f0fd4449eacfadeea90fe1e0680498c22b6459
[platform/upstream/aspell.git] / manual / aspell-dev.texi
1 \input texinfo   @c -*-texinfo-*-
2
3 @setfilename aspell-dev.info
4 @settitle Aspell Developer's Manual
5 @setchapternewpage off
6 @syncodeindex pg cp
7 @documentencoding ISO-8859-1
8 @documentdescription
9 Aspell spell checker developer's manual.
10 @end documentdescription
11
12 @copying
13 This is the developer's manual for Aspell.
14
15 Copyright @copyright{} 2002, 2003, 2004, 2006 Kevin Atkinson.
16
17 @quotation
18 Permission is granted to copy, distribute and/or modify this document
19 under the terms of the GNU Free Documentation License, Version 1.1 or
20 any later version published by the Free Software Foundation; with no
21 Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.  A
22 copy of the license is included in the section entitled "GNU Free
23 Documentation License".
24 @end quotation
25 @end copying
26
27 @dircategory GNU Packages
28 @direntry
29 * Aspell-dev: (aspell-dev).        For Aspell developers
30 @end direntry
31
32 @titlepage
33 @title Aspell Developer's Manual
34 @author Kevin Atkinson (@email{kevina@@gnu.org})
35 @page
36 @vskip 0pt plus 1filll
37 @insertcopying
38 @end titlepage
39
40 @contents
41
42 @ifnottex
43 @node Top, Style Guidelines, (dir), (dir)
44 @top Notes
45 This manual is designed for those who wish to develop Aspell.  It is
46 currently very sketchy.  However, it should improve over time.  The
47 latest version of this document can be found at
48 @uref{http://savannah.gnu.org/download/aspell/manual/devel/devel.html}.
49
50 @menu
51 * Style Guidelines::            
52 * How to Submit a Patch::       
53 * C++ Standard Library::        
54 * Templates::                   
55 * Error Handling::              
56 * Source Code Layout ::         
57 * Strings::                     
58 * Smart Pointers::              
59 * I/O::                         
60 * Config Class::                
61 * Filter Interface::            
62 * Filter Modes::            
63 * Data Structures::             
64 * Mk-Src Script::               
65 * How It All Works::
66 * Copying::
67 @end menu
68
69 @end ifnottex
70
71 @node Style Guidelines, How to Submit a Patch, Top, Top
72 @chapter Style Guidelines
73
74 * Style Guidelines::            
75 * How to Submit a Patch::            
76 * C++ Standard Library::        
77 * Templates::                   
78 * Error Handling::              
79 * Source Code Layout ::         
80 * Strings::
81 * Smart Pointers::              
82 * I/O::                         
83 * Config Class::                
84 * Filter Interface::            
85 * Filter Modes::            
86 * Data Structures::             
87 * Mk-Src Script::               
88 * How It All Works::
89 * Copying::
90
91 As far as coding styles go I am really not that picky.  The important
92 thing is to stay consistent.  However, please whatever you do, do not
93 indent with more than 4 characters as I find indenting with more than
94 that extremely difficult to read as most of the code ends up on the
95 right side of the screen.
96
97 @node How to Submit a Patch, C++ Standard Library, Style Guidelines, Top
98 @chapter How to Submit a Patch
99
100 Bug reports and patches should be submitted via the Sourceforge Tracker
101 at @uref{http://sourceforge.net/@/tracker/?group_id=245} rather than
102 being posted to any of the mailing lists.
103
104 The mailing lists are good if you need to check something out or need
105 help or feedback from other readers, but they are not the best place to
106 submit bugs or patches because they will likely get forgotten or lost
107 within the mailing list traffic if not acted upon immediately.
108
109 Please make the effort to use the tracker.
110
111 @node C++ Standard Library, Templates, How to Submit a Patch, Top
112 @chapter C++ Standard Library
113
114 The C++ Standard library is not used directly except under very
115 specific circumstances.  The string class and the STL are used
116 indirectly through wrapper classes and all I/O is done using the
117 standard C library with light right helper classes to make using C I/O
118 a bit more C++ like.
119
120 However the @code{new}, @code{new[]}, @code{delete} and
121 @code{delete[]} operators are used to allocate memory when
122 appropriate.
123
124 @node Templates, Error Handling, C++ Standard Library, Top
125 @chapter Templates
126
127 Templates are used in Aspell when there is a clear advantage to doing
128 so.  Whenever you use templates please use them carefully and try very
129 hard not to create code bloat by generating a lot of unnecessary and
130 duplicate code.
131
132 @node Error Handling, Source Code Layout , Templates, Top
133 @chapter Error Handling
134
135 Exceptions are not used in Aspell as I find them more trouble than
136 they are worth.  Instead an alternate method of error handling is used
137 which is based around the PosibErr class.  PosibErr is a special Error
138 handling device that will make sure that an error is properly handled.
139 It is defined in @code{posib_err.hpp}.  PosibErr is expected to be
140 used as the return type of the function. It will automatically be
141 converted to the "normal" return type however if the normal returned
142 type is accessed and there is an "unhandled" error condition it will
143 abort. It will also abort if the object is destroyed with an
144 "unhandled" error condition.  This includes ignoring the return type
145 of a function returning an error condition.  An error condition is
146 handled by simply checking for the presence of an error, calling
147 ignore, or taking ownership of the error.
148
149 The PosibErr class is used extensively throughout Aspell.  Please
150 refer to the Aspell source for examples of using PosibErr until better
151 documentation is written.
152
153 @node Source Code Layout , Strings, Error Handling, Top
154 @chapter Source Code Layout 
155
156 @table @file
157 @item common/
158  Common code used by all parts of Aspell.
159
160 @item lib/
161  Library code used only by the actual Aspell library.
162
163 @item data/
164  Data files used by Aspell.
165
166 @item modules/
167  Aspell modules which are eventually meant to be pluggable.
168
169 @table @file
170   @item speller/ 
171   @table @file
172     @item default/
173       Main speller Module.
174   @end table
175
176   @item filter/ 
177
178   @item tokenizer/
179 @end table
180
181 @item auto/
182 Scripts and data files to automatically generate code used by Aspell.
183
184 @item interface/
185 Header files and such that external programs should use when in order
186 to use the Aspell library.
187 @table @file
188
189 @item cc/
190 The external C interface that programs should be using when they wish
191 to use Aspell.
192 @end table
193
194 @item prog/
195 Actual programs based on the Aspell library. The main Aspell utility
196 is included here.
197
198 @item scripts/
199 Miscellaneous scripts used by Aspell.
200
201 @item manual/
202
203 @item examples/
204 Example programs demonstrating the use of the Aspell library.
205 @end table
206
207
208 @node  Strings, Smart Pointers, Source Code Layout , Top
209 @chapter Strings
210
211 @section String
212
213 The @code{String} class provided the same functionality of the C++
214 string except for fewer constructors.  It also inherits @code{OStream}
215 so that you can write to it with the @code{<<} operator.  It is
216 defined in @code{string.hpp}.
217
218 @section ParmString
219
220 ParmString is a special string class that is designed to be used as a
221 parameter for a function that is expecting a string.  It is defined in
222 @code{parm_string.hpp}.  It will allow either a @code{const char *} or
223 @code{String} class to be passed in.  It will automatically convert to
224 a @code{const char *}.  The string can also be accessed via the
225 @code{str} method.  Usage example:
226 @verbatim
227 void foo(ParmString s1, ParmString s2) {
228    const char * str0 = s1;
229    unsigned int size0 = s2.size()
230    if (s1 == s2 || s2 == "bar") {
231      ...
232    }
233 }
234 ...
235 String s1 = "...";
236 foo(s1);
237 const char * s2 = "...";
238 foo(s2);
239 @end verbatim
240
241 This class should be used when a string is being passed in as a
242 parameter.  It is faster than using @code{const String &} (as that
243 will create an unnecessary temporary when a @code{const char *} is
244 passed in), and is less annoying than using @code{const char *} (as it
245 doesn't require the @code{c_str()} method to be used when a
246 @code{String} is passed in).
247
248 @section CharVector
249
250 A character vector is basically a @code{Vector<char>} but it has a few
251 additional methods for dealing with strings which @code{Vector} does
252 not provide.  It, like @code{String}, is also inherits @code{OStream}
253 so that you can write to it with the @code{<<} operator.  It is
254 defined in @code{char_vector.hpp}.  Use it when ever you need a string
255 which is guaranteed to be in a continuous block of memory which you
256 can write to.
257
258 @node Smart Pointers, I/O, Strings, Top
259 @chapter Smart Pointers
260
261 Smart pointers are used extensively in Aspell to
262 simplify memory management tasks and to avoid memory leaks. 
263
264 @section CopyPtr
265
266 The @code{CopyPtr} class makes a deep copy of an object whenever it is
267 copied.  The @code{CopyPtr} class is defined in @file{copy_ptr.hpp}.
268 This header should be included wherever @code{CopyPtr} is used.  The
269 complete definition of the object @code{CopyPtr} is pointing to does
270 not need to be defined at this point.  The implementation is defined
271 in @file{copy_ptr-t.hpp}.  The implementation header file should be
272 included at a point in your code where the class @code{CopyPtr} is
273 pointing to is completely defined.
274
275 @section ClonePtr
276
277 @code{ClonePtr} is like copy pointer except the @code{clone()} method
278 is used instead of the copy constructor to make copies of an object.
279 If is defined in @file{clone_ptr.hpp} and implemented in
280 @file{clone_ptr-t.hpp}.
281
282 @section StackPtr
283
284 A @code{StackPtr} is designed to be used whenever the only pointer to
285 a new object allocated with @command{new} is on the stack.  It is
286 similar to the standard C++ @code{auto_ptr} but the semantics are a
287 bit different.  It is defined in @file{stack_ptr.hpp} --- unlike
288 @code{CopyPtr} or @code{ClonePtr} it is defined and implemented in
289 this header file.
290
291 @section GenericCopyPtr
292
293 A generalized version of @code{CopyPtr} and @code{ClonePtr} which the
294 two are based on.  It is defined in @file{generic_copy_ptr.hpp} and
295 implemented in @file{generic_copy_ptr-t.hpp}.
296
297 @node I/O, Config Class, Smart Pointers, Top
298 @chapter I/O
299
300 Aspell does not use C++ I/O classes and functions in any way since
301 they do not provide a way to get at the underlying file number and can
302 often be slower than the highly tuned C I/O functions found in the
303 standard C library.  However, some lightweight wrapper classes are
304 provided so that standard C I/O can be used in a more C++ like way.
305
306 @section IStream/OStream
307
308 These two base classes mimic some of the functionally of the C++
309 functionally of the corresponding classes.  They are defined in
310 @file{istream.hpp} and @file{ostream.hpp} respectively.  They are
311 however based on standard C I/O and are not proper C++ streams.
312
313 @section FStream
314
315 Defined in @file{fstream.hpp}.
316
317
318 @section Standard Streams
319
320 @code{CIN}/@code{COUT}/@code{CERR}.  Defined in @file{iostream.hpp}.
321
322 @node Config Class, Filter Interface, I/O, Top
323 @chapter Config Class
324
325 The @code{Config} class is used to hold configuration information.  It
326 has a set of keys which it will accept.  Inserting or even trying to
327 look at a key that it does not know will produce an error.  It is
328 defined in @file{common/config.hpp}.
329
330
331 @node Filter Interface, Filter Modes, Config Class, Top
332 @chapter Filter Interface
333
334 @section Overview
335 @anchor{Filter Overview}
336
337 In Aspell there are 5 types of filters:
338 @enumerate
339 @item
340 @emph{Decoders} which take input in some standard format such as
341 iso8859-1 or UTF-8 and convert it into a string of @code{FilterChars}.
342 @item
343 @emph{Decoding filters} which manipulate a string of
344 @code{FilterChars} by decoding the text is some way such as converting
345 an SGML character into its Unicode value.
346 @item
347 @emph{True filters} which manipulate a string of @code{FilterChars} to
348 make it more suitable for spell checking.  These filters generally
349 blank out text which should not be spell checked
350 @item
351 @emph{Encoding filters} which manipulate a string of
352 @code{FilterChars} by encoding the text in some way such as converting
353 certain Unicode characters to SGML characters.
354 @item
355 @emph{Encoders} which take a string of @code{FilterChars} and convert
356 into a standard format such as iso8859-1 or UTF-8
357 @end enumerate
358
359 Which types of filters are used depends on the situation
360 @enumerate
361 @item
362 When @emph{decoding words} for spell checking:
363 @itemize @bullet
364 @item
365 The @emph{decoder} to convert from a standard format
366 @item
367 The @emph{decoding filter} to perform high level decoding if necessary
368 @item
369 The @emph{encoder} to convert into an internal format used by the
370 speller module
371 @end itemize
372
373 @item
374 When @emph{checking a document}
375 @itemize @bullet
376 @item
377 The @emph{decoder} to convert from a standard format
378 @item
379 The @emph{decoding filter} to perform high level decoding if necessary
380 @item
381 A @emph{true filter} to filter out parts of the document which should
382 not be spell checked
383 @item
384 The @emph{encoder} to convert into an internal format used by the
385 speller module
386 @end itemize
387
388 @item
389 When @emph{encoding words} such as those returned for suggestions:
390 @itemize @bullet
391 @item
392 The @emph{decoder} to convert from the internal format used by the
393 speller module
394 @item
395 The @emph{encoding filter} to perform high level encodings if
396 necessary
397 @item
398 The @emph{encoder} to convert into a standard format
399 @end itemize
400 @end enumerate
401
402
403 A @code{FilterChar} is a struct defined in
404 @file{common/filter_char.hpp} which contains two members, a character,
405 and a width.  Its purpose is to keep track of the width of the
406 character in the original format.  This is important because when a
407 misspelled word is found the exact location of the word needs to be
408 returned to the application so that it can highlight it for the user.
409 For example if the filters translated this:
410 @verbatim
411 Mr. foo said &quot;I hate my namme&quot;.
412 @end verbatim
413
414 to this
415 @verbatim
416 Mr. foo said "I hate my namme".
417 @end verbatim
418
419 without keeping track of the original width of the characters the application
420  will likely highlight 
421 @code{e my }
422  as the misspelling because the spell checker will return 25 as the offset
423  instead of 30.
424  However with keeping track of the width using @code{FilterChar} the
425  spell checker 
426  will know that the real position is 30 since the quote is really 6 characters
427  wide.
428  In particular the text will be annotated something like the following:
429 @verbatim
430 1111111111111611111111111111161
431 Mr. foo said "I hate my namme".
432 @end verbatim
433
434 The standard @emph{encoder} and @emph{decoder} filters are defined in
435 @file{common/convert.cpp}.  There should generally not be any need to
436 deal with them so they will not be discussed here.  The other three
437 filters, the @emph{encoding filter}, the @emph{true filter}, and the
438 @emph{decoding filter}, are all defined the exact same way; they are
439 inherited from the @code{IndividualFilter} class.
440
441 @section Adding a New Filter
442
443 A new filter basically is added by placing the corresponding loadable
444 object inside a directory reachable by Aspell via @option{filter-path}
445 list.  Further it is necessary that the corresponding filter
446 description file is located in one of the directories listed by the
447 @option{option-path} list.
448
449 The name of the loadable object has to conform to the following
450 convention @file{lib@i{filtername}-filter.so} where
451 @code{@i{filtername}} stands for the name of the filter which is
452 passed to Aspell by the @option{add-filter} option.  The same applies
453 to the filter description file which has to conform to the following
454 naming scheme: @file{@i{filtername}-filter.opt}.
455
456 To add a new loadable filter object create a new file.
457
458 Basically the file should be a C++ file and end in @file{.cpp}.  The
459 file should contain a new filter class inherited from
460 @code{IndividualFilter} and a constructor function called
461 @file{new_@i{filtertype}} (see @ref{Constructor Function}) returning a
462 new filter object.  Further it is necessary to manually generate the
463 filter description file.  Finally the resulting object has to be
464 turned into a loadable filter object using libtool.
465
466 Alternatively a new filter may extend the functionality of an existing
467 filter. In this case the new filter has to be derived form the 
468 corresponding valid filter class instead of the @code{IndividualFilter}
469 class.
470
471 @section IndividualFilter class
472
473 All filters are required to inherit from the @code{IndividualFilter}
474 class found in @file{indiv_filter.hpp}.  See that file for more
475 details and the other filter modules for examples of how it is used.
476
477 @section Constructor Function
478 @anchor{Constructor Function}
479
480 After the class is created a function must be created which will
481 return a new filter allocated with @code{new}.  The function must have
482 the following prototype:
483 @example
484 C_EXPORT IndividualFilter * new_aspell_@var{filtername}_@var{filtertype}
485 @end example
486
487 Filters are defined in groups where each group contains an
488 @emph{encoding filter}, a @emph{true filter}, and a @emph{decoding
489 filter} (see @ref{Filter Overview}).  Only one of them is required to
490 be defined, however they all need a separate constructor function.
491
492 @section Filter Description File
493 @anchor{Filter Description File}
494
495 This file contains the description of a filter which is loaded by
496 Aspell immediately when the @option{add-filter} option is invoked.  If
497 this file is missing Aspell will complain about it.  It consists of
498 lines containing comments which must be started by a @kbd{#}
499 character and lines containing key value pairs describing the filter.
500 Each file at least has to contain the following two lines in the given
501 order.
502  
503 @example
504 ASPELL >=0.60
505 DESCRIPTION this is short filter description
506 @end example
507
508 The first non blank, non comment line has to contain the keyword
509 @code{ASPELL} followed by the version of Aspell which the filter is
510 usable with.  To denote multiple Aspell versions the version number may
511 be prefixed by `@kbd{<}', `@kbd{<=}', `@kbd{=}', `@kbd{>=}' or `@kbd{>}.
512 If the range prefix is omitted `@kbd{=}' is assumed.  The
513 @code{DESCRIPTION} of the filter should be under 50, begin in lower
514 case, and note include any trailing punctuation characters.
515 The keyword @code{DESCRIPTION} may be abbreviated by @code{DESC}.
516
517 For each filter feature (see @ref{Filter Overview}) provided by the
518 corresponding loadable object, the option file has to contain the
519 following line:
520 @example
521 STATIC @code{@i{filtertype}}
522 @end example
523 @code{@i{filtertype}} stands for one of @code{decoder}, @code{filter}
524 or @code{encoder} denoting the entire filter type.  This line allows
525 to statically (see @ref{Link Filters Static}) link the filter into
526 Aspell if requested by the user or by the system Aspell is built for.
527
528 @example
529 OPTION newoption
530 DESCRIPTION this is a short description of newoption
531 TYPE bool
532 DEFAULT false
533 ENDOPTION
534 @end example
535
536 An option is added by a line containing the keyword @code{OPTION}
537 followed by the name of the option.  If this name is not prefixed by
538 the name of the filter Aspell will implicitly do that.  For the
539 @code{DESCRIPTION} of a filter option the same holds as for the filter
540 description.  The @code{TYPE} of the option may be one of @code{bool},
541 @code{int}, @code{string} or @code{list}.  If the @code{TYPE} is
542 omitted @code{bool} is assumed.  The default value(s) for an option is
543 specified via @code{DEFAULT} (short @code{DEF}) followed by the
544 desired @code{TYPE} dependent default value.  The table @ref{Filter
545 Default Values} shows the possible values for each @code{TYPE}.
546
547 @anchor{Filter Default Values}
548 @multitable {string} {Default} {any comma separated list of strings}
549 @item @b{Type} @tab @b{Default} @tab @b{Available}
550 @item bool @tab true    @tab true false
551 @item int  @tab 0       @tab any number value
552 @item string @tab       @tab any printable string
553 @item list   @tab       @tab any comma separated list of strings 
554 @end multitable
555
556 Table 1. Shows the default values Aspell assumes if option
557 @option{description} lacks a @code{DEFAULT} or @code{DEF} line.
558
559 The @code{ENDOPTION} line may be omitted as it is assumed implicitly
560 if a line containing @code{OPTION}, @code{STATIC}.
561
562 @quotation
563 @strong{Note@:} The keywords in a filter description file are case
564 insensitive.  The above examples use the all uppercase for better
565 distinguishing them from values and comments.  Further a filter
566 description may contain blank lines to enhance their readability.
567 @end quotation
568
569 @quotation
570 @strong{Note@:} An option of @code{list} type may contain multiple
571 consecutive lines for default values starting with @code{DEFAULT} or
572 @code{DEF}, to specify numerous default values.
573 @end quotation
574
575
576 @section Retrieve Options by a Filter
577
578 An option always has to be retrieved by a filter using its full
579 qualified name as the following example shows.
580  
581
582 @example
583 config->retrieve_bool("filter-@i{filtername}-newoption"); 
584 @end example
585
586 The prefix @code{filter-} allows user to relate option uniquely to the
587 specific filter when @code{@i{filtername}-newoption} ambiguous an
588 existing option of Aspell.  The @code{@i{filtername}} stands for the
589 name of the filter the option belongs to and @code{-@i{newoption}} is
590 the name of the option as specified in the corresponding @file{.opt}
591 file (see @ref{Filter Description File}
592
593
594 @section Compiling and Linking
595
596 See a good book on Unix programming on how to turn the filter source
597 into a loadable object.
598
599
600 @section Programmer's Interface
601 @anchor{Programmer's Interface}
602
603
604 @anchor{Recommended Standard Aspell} A more convenient way
605 recommended, if filter is added to Aspell standard distribution to
606 build a new filter is provided by Aspell's programmers interface for
607 filter.  It is provided by the @file{loadable-filter-API.hpp} file.
608 Including this file gives access to a collection of macros hiding
609 nasty details about runtime construction of a filter and about filter
610 debugging.  Table @ref{Interface Macros} shows the macros provided by
611 the interface.  For details upon the entire macros see
612 @file{loadable-filter-API.hpp}.  An example on how to use these macros
613 can be found at @file{examples/loadable/ccpp-context.hpp} and
614 @file{examples/loadable/ccpp-context.cpp}.
615
616 @multitable @columnfractions .25 .06 .34 .34
617 @item @b{Macro} @tab @b{Type} @tab @b{Description} @tab @b{Notes}
618 @item ACTIVATE_ENCODER @tab M @tab makes the entire encoding
619 filter callable by Aspell @tab do not call inside class declaration;
620 these macros define new_<filtertype> function; 
621 @item ACTIVATE_DECODER @tab M @tab makes the entire decoding
622 filter callable by Aspell @tab @emph{as above}
623 @item ACTIVATE_FILTER @tab M @tab makes the entire filter
624 callable by Aspell @tab @emph{as above} 
625 @item FDEBUGOPEN @tab D @tab Initialises the macros for debugging a
626 filter and opens the debug file stream @tab These macros are only
627 active if the @code{FILTER_PROGRESS_CONTROL} macro is defined and
628 denotes the name of the file debug messages should be sent to.
629
630 If debugging should go to Aspell standard debugging output (right now
631 stderr) use empty string constant as filename
632 @item FDEBUGNOTOPEN @tab D @tab Same as ``FDEBUGOPEN'' but
633 only if debug file stream was not opened yet @tab @emph{as above}
634 @item FDEBUGCLOSE @tab D @tab closes the debugging device opened by ``FDEBUGOPEN'' and reverts it to ``stderr''; @tab @emph{as above}
635 @item FDEBUG @tab D @tab prints the filename and the line
636 number it occurs @tab @emph{as above}
637 @item FDEBUGPRINTF @tab D @tab special printf for debugging
638 @tab @emph{as above} 
639 @end multitable
640
641 Table 2. Shows the macros provided by @file{loadable-filter-API.hpp}
642 (@strong{M} mandatory, @strong{D} debugging) @anchor{Interface Macros}
643
644
645 @section Adding a filter to Aspell standard distribution
646 @anchor{Link Filters Static}
647
648 Any filter which one day should be added to Aspell has to be built
649 using the developer interface, described in @ref{Programmer's
650 Interface}.  To add the filter the following steps have to be
651 performed:
652
653 @enumerate
654 @item
655 Decide whether the filter should be kept loadable if possible, or
656 always be statically linked to Aspell.
657
658 @item
659 @anchor{Place Sources} Place the filter sources inside the entire
660 directory of Aspell source tree.  Right now use
661 @code{@i{$top_srcdir}/modules/filter}.
662  
663 @item
664 Modify the @file{Makefile.am} file on the topmost directory of the
665 Aspell distribution.  Follow the instructions given by the
666 @code{#Filter Modules} section.
667  
668 @item
669 Run @file{autoconf}, @file{automake}, @dots{}
670
671 @item
672 Reconfigure sources.
673  
674 @item
675 @anchor{Build Sources} Clear away any remains of a previous build and
676 rebuild sources.
677  
678 @item
679 @anchor{Reinstall Aspell} Reinstall Aspell.
680  
681 @item
682 @anchor{Test Filter Installed} Test if filter has been added properly
683 otherwise return to steps 2--7
684 @c Doesn't work@ref{Place Sources}-@ref{Reinstall Aspell}.
685  
686 @item
687 Reconfigure sources with @option{enable-static} flag and repeat steps
688 2--7
689 @c Doesn't work @ref{Build Sources}-@ref{Test Filter Installed}
690 until your filter builds and runs properly in case of static linkage.
691  
692 @item
693 Add your source files to cvs, and commit all your changes.  Or in case
694 you are not allowed to commit to cvs submit a patch (see @ref{How to
695 Submit a Patch}) containing your changes.
696
697 @end enumerate
698 @c Following this comes the section ``Filter Modes''
699 @node Filter Modes, Data Structures,Filter Interface, Top
700 @chapter Filter Modes
701
702 Filter modes are the preferred way to specify combinations of
703 filters which are used regularly and thus abbreviate Aspell's
704 command line arguments.
705
706 A new filter mode is specified by a file named like the filter
707 new mode and prefixed by @file{.amf} (Aspell Mode File). If such a file
708 is accessible by the path set via filter-path option Aspell
709 will try to load the contained mode specification.
710
711 @section Aspell Mode File
712 The first key in the made file has be the @code{mode} key.
713 It is checked against the mode name part of the .amf file.
714 If the @code{mode} key is missing mode file will be rejected.
715
716 The same holds for the @code{aspell} key which specifies the
717 version(s) of Aspell which is(are) required by the filter.
718
719 If these two keys are followed by at least one @code{magic} key
720 Aspell will be able to select the entire mode from extension and
721 if required from contents of the file to spell implicitly.
722
723 The last key of the required keys is the @code{des[c[ription]]}
724 key. It gives a short description of the filter mode which will
725 displayed when type @command{aspell help}.
726
727 The rest of the file consists of the keys @code{filter} and
728 @code{option} to load filters are set various options.
729
730 @subsection Version Line
731
732 Each version line must start with @code{aspell} and be followed by a
733 version, optionally prefixed by a relational operator. The relation
734 operator can be one of `<', `<=', `=', `>=' or '>' for allowing Aspell
735 version with version number being lower, lower or equal, equal to,
736 greater or equal or greater than required version number,
737 respectfully. If the relation operator is omitted `=' is assumed.
738
739 @subsection Magic Line
740
741 The magic line contains a description which requirements files
742 have to fulfill in order to implicitly activate the entire mode
743 at least one such line is required.  Each magic line has the following
744 format:
745 @example
746 MAGIC /<magic key>/<fileextention>[/<fileextention>]
747 @end example
748
749 The magic key consist of three `:' separated fields.
750 The first two are byte counts the last is a regular expression.
751 The first byte count indicates the first byte the regular expression
752 will be applied to the second byte count indicates the number of
753 bytes to test against the regular expression.
754
755 If mode selection should only occurred on basis of the listed file
756 extensions the magic key should consist of the ``<noregex>'' special
757 string.
758
759 At least one <fileextention> is required per MAGIC line.
760 <fileextention> may not be empty and should not contain a leading `.'
761 as this is assumed implicitly.
762
763 Multiple MAGIC lines are allowed. Modes may be extended limited by additional
764 <label>.amf files located in --filter-path
765 Thus file extensions may be prefixed by `+' or `-' to indicate that
766 the entire extension has to be added ore removed from this <magic key>
767 if neither is specified than a `+' is assumed implicitly.
768
769 @subsection Description Line
770
771 The required description line will be printed when typing
772 @command{aspell help}.  Keep it as short as possible.  Possible
773 abbreviations are @code{des} and @code{desc}.
774
775 @subsection Filter and Option Lines
776
777 The @code{filter} and @code{option} keys load filters and set filter
778 options.
779
780 The value of the @code{filter} key is equal to the value of Aspell's
781 @code{[add|rem]-filter} option. 
782
783 Each @code{option} line has the following format:
784
785 @example
786   OPTION <option> [<value>]
787 @end example
788
789 The format of the <option> and <value> is the same format as 
790 found in the Aspell configuration file.
791
792 @c Following this comes the section ``Data Structures''
793
794
795 @c -*- end of new text -*-
796 @c The section ``Config Options'' was here
797
798 @node Data Structures, Mk-Src Script, Filter Modes, Top
799 @chapter Data Structures
800
801 Whenever possible you should try to use one of the data structures
802 available.  If the data structures do not provide enough functionality
803 for your needs you should consider enhancing them rather than writing
804 something from scratch.
805
806 @section Vector
807
808 The @code{vector} class is defined in @file{vector.hpp} and works the
809 same way as the standard STL @code{vector} does except that it doesn't
810 have as many constructors.
811
812 @section BasicList
813
814 @code{BasicList} is a simple list structure which can either be
815 implemented as a singly or doubly linked list.  It is defined in
816 @file{basic_list.hpp}.
817
818 @section StringMap
819
820 @code{StringMap} is a associative array for strings.  You should try
821 to use this when ever possible to avoid code bloat.  It is defined in
822 @file{string_map.hpp}.
823
824
825 @section Hash Tables
826
827 Several hash tables are provided when @code{StringMap} is not
828 appropriate.  These hash tables provide a @code{hash_set},
829 @code{hash_multiset}, @code{hash_map} and @code{hash_multimap} which
830 are very similar to SGI's STL implementation with a few exceptions.
831 It is defined in @file{hash.hpp}.
832
833
834 @section BlockSList
835
836 @code{BlockSList} provided a pool of nodes which can be used for
837 singly linked lists.  It is defined in @file{block_slist.hpp}.
838
839 @node Mk-Src Script, How It All Works, Data Structures, Top
840 @chapter Mk-Src Script
841
842 A good deal of interface code is automatically generated by the
843 @file{mk-src.pl} Perl script.  I am doing it this way to avoid having
844 to write a lot of relative code for the C++ interface.  This should
845 also make adding interface for other languages a lot less tedious and
846 will allow the interface to automatically take advantage of new Aspell
847 functionality as it is made available.  The @file{mk-src.pl} script
848 uses @file{mk-src.in} as its input.
849
850 @include mksrc.texi
851
852 @node How It All Works, Part 1 - Compiled Dictionary Format, Mk-Src Script, Top
853 @chapter How It All Works
854
855 The details of how Aspell really works is a mystery to most users who
856 want to participate in developing and improving Aspell, so it is best
857 to fully explain Aspell's core algorithms and data structures to you.
858
859 In explaining these, it is hoped to bring prospective developers up to
860 speed more quickly and also help you understand the amount of thought
861 put into this.  In time, you may be able to improve Aspell even more.
862
863 There are many details to explain here, so these will need explaining
864 in small segments.
865
866 @menu
867 * Part 1 - Compiled Dictionary Format::
868 * Part 2 - Quickly Finding Similar Soundslike::
869 * Part 3::
870 @end menu
871
872 @node Part 1 - Compiled Dictionary Format, Part 2 - Quickly Finding Similar Soundslike, How It All Works, How It All Works
873 @section Part 1 - The Compiled Dictionary Format
874
875 In this part you will see how the data is laid out in the compiled
876 dictionary for Aspell 0.60.  See source file @file{readonly_ws.cpp}.
877
878 Aspell's main compiled wordlist dictionary file is made as follows:
879
880 @itemize
881 @item header
882 @item jump table for editdist 1
883 @item jump table for editdist 2
884 @item data block
885 @item hash table
886 @end itemize
887
888 There is nothing particularly interesting about the header.  Just a
889 bunch of meta information.
890
891 The jump tables are described in the next section @dots{}
892
893 Words in the data block are grouped based on the soundslike.  Each
894 group is as follows:
895
896 @example
897 <8 bit: offset to next item><8 bit: soundslike size><soundslike>
898 <null><words>
899 @end example
900
901 @noindent
902  Each word group is as follows: 
903
904 @example
905 <8 bit: flags><8 bit: offset to next word><8 bit: word size><word><null>
906 [<affix info><null>]
907 @end example
908
909 The offset for the final word in each group points to the next word in
910 the following group.  The offset for the final word and soundslike
911 group in the dictionary is 0.
912
913 There is some provisions for additional info to be stored with the word
914 but for simplicity, it's left out here.  If soundslike data is not used
915 then the soundslike block it not used.
916
917 This format makes it easy to iterate over the data without using the
918 hash table.
919
920 Each soundslike group can be a maximum of about 256 bytes.  If this
921 limit is reached then the soundslike group is split. Using 2 bytes for
922 the soundslike offset would of solved this problem however 256 bytes
923 is normally sufficient, thus I would of wasted some space by using an
924 extra byte.  More importantly, Using 2 bytes means I would of had to
925 worry about alignment issues.
926
927 The soundslike groups are sorted in more or less alphabetic order.
928
929 The hash table is a simple open address hash table.  The key is the
930 dictionary word in all lowercase form with all accents removed (what is
931 known as the "clean" form of the word).  The value stored in the table
932 is a 32-bit offset to the beginning of the word.  A 32-bit integer
933 offset is used rather than a pointer so that the compiled dictionary
934 can be mmaped to make loading the dictionary very fast and so that the
935 memory can be shared between processed, and on 64 bit platforms using
936 pointers would have doubled the size of the hash table.
937
938 Additional information for each word can be derived from each offset:
939
940 @example
941 word size: offset - 1
942 offset to next word: offset - 2
943 flags: offset - 3
944 @end example
945
946 I use helper functions for getting this information.  Doing it this way
947 rather than having a data structure is slightly evil, but admittedly,
948 I have my reasons.
949
950 In the next section, you will see how Aspell uses the jump tables to
951 search the list for @emph{soundslike} with @emph{edit-distance} of 1 or 2.
952
953 @node Part 2 - Quickly Finding Similar Soundslike, Part 3, Part 1 - Compiled Dictionary Format, How It All Works
954 @section Part 2 - Quickly Finding Similar Soundslike
955
956 In order for Aspell to find suggestions for a misspelled word Aspell 1)
957 creates a list of candidate words, 2) scores them, and 3) returns the most
958 likely candidates.  One of the ways Aspell finds candidate words is to look
959 for all words with a soundslike which is of a small edit distance from the
960 soundslike of the original word.  The edit distance is the total number of
961 deletions, insertions, exchanges, or adjacent swaps needed to make one
962 string equivalent to the other. The exact distance chosen is either 1 or 2
963 depending on a number of factors.  In this part I will focus on how Aspell
964 find all such soundslike efficiently and how the jump tables play a key
965 role.
966
967 This section will focus on how Aspell finds all such soundslike
968 efficiently and how the jump tables play a key role.
969
970 The naive way to scan the list for all possible soundslike is to
971 compute the edit-distance of every soundslike in the dictionary and
972 then keep the ones within the threshold.  This is exactly what Aspell
973 did prior to 0.60. before a faster method was created.  When a fast
974 enough edit distance function is used this method turns out not to be
975 unbearably slow, at least for English, but for other languages, with
976 large word lists and no soundslike, this can be slow due to the number
977 of items that need to be scanned.
978
979 Aspell uses a special edit distance function which gives up if the
980 distance is larger than the threshold, thus making it very fast.  The
981 basic algorithm is as follows:
982
983 @example
984 limit_edit_distance(A,B,limit) = ed(A,B,0)
985   where ed(A,B,d) = d                              if A & B is empty.
986                   = infinity                       if d > limit
987                   = ed(A[2..],B[2..], d)           if A[1] == B[1]
988                   = min ( ed(A[2..],B[2..], d+1),
989                           ed(A,     B[2..], d+1),
990                           ed(A[2..],B,      d+1) ) otherwise
991 @end example
992
993 However the algorithm used also allows for swaps and is not recursive.
994 Specialized versions are provided for an edit distance of one and two.
995 The running time is asymptotically bounded above by @code{(3^l)*n}
996 where @code{l} is the limit and @code{n} is the maximum of
997 @code{strlen(A),strlen(B)}.  Based on informal tests, the @code{n}
998 does not really matter and the running time is more like @code{(3^l)}.
999
1000 For complete details on this algorithm see the files
1001 @file{leditdist.hpp} and @file{leditdist.cpp} in the source
1002 distribution under @file{modules/speller/default}.
1003
1004 So, by exploiting the properties of @code{limit_edit_distance} it is
1005 possible to avoid having to look at many of the soundslikes in the
1006 dictionary.  @code{Limit_edit_distance} is efficient because in many
1007 cases, it does not have to look at the entire word before it can
1008 determine that it isn't within the given threshold, and then by having
1009 it return the last position looked at, @emph{p}, it is possible to
1010 avoid having to look at similar soundslike which are not within the
1011 threshold.  That is, if two soundslike are the same up to the position
1012 @code{p}, then neither of them are within the given threshold.
1013
1014 Aspell 0.60 exploits this property by using jump tables.  Each entry
1015 in the jump table contains two fields: the first @code{N} letters of a
1016 soundslike, and an offset.  The entries are sorted in lexicographic
1017 order based on the raw byte value.  Aspell maintains two jump tables.
1018
1019 The first table contains the first 2 letters of a soundslike and the
1020 offset points into the second jump table.
1021
1022 The second table contains the first 3 letters of a soundslike where
1023 the offset points to the location of the soundslike in the data block.
1024 The soundslike in the datablock are sorted so that a linear scan can
1025 be used to find all soundslike with the same prefix.  If the
1026 @code{limit_edit_distance} stops before reaching the end of a
1027 @emph{"soundslike"} in one of the jump tables then it is possible to
1028 skip all the soundslike in the data block with the same prefix.
1029
1030 Thus, the scan for all @emph{soundslike} within a given edit distance
1031 goes something like this:
1032
1033 @enumerate
1034
1035 @item
1036 Compare the entry in the first jump table using
1037 @code{limit_edit_distance}.  If the @code{limit_edit_distance} scanned
1038 passed the end of the word, then go to the first entry in the second
1039 jump table with the same prefix, otherwise go to the next entry in the
1040 first jump table and repeat.
1041
1042 @item
1043 Compare the entry in the second jump table.  If the
1044 @code{limit_edit_distance}  passed the end of the word, then go to the
1045 first @emph{soundslike} in the data block with this prefix, otherwise
1046 if the first two letters of the next entry are the same as the current
1047 one go to it and repeat.  If the first two letters are not the same
1048 then go to the next entry in the first jump table and repeat step 1.
1049
1050 @item
1051 Compare the @emph{soundslike} in the data block.  If the edit
1052 distance is within the target distance, then add the word to the
1053 candidate list, otherwise don't.  Let @code{N} be the position where
1054 @code{limit_edit_distance} stopped, (starting at 0).  If @code{N} is
1055 less than 6, then skip over any soundslike that have the same first
1056 @code{N + 1} letters.  If after skipping over any similar
1057 @emph{soundslike} the next @emph{soundslike} does not have the same
1058 first three letters, then go to the next entry in the second jump table
1059 and repeat step 2, otherwise repeat this step with the next
1060 @emph{soundslike}.
1061
1062 @end enumerate
1063
1064 The part of skipping over @emph{soundslike} with the first @code{N + 1}
1065 letters in step 3 were added in Aspell 0.60.3.  The function
1066 responsible for most of this is found in function
1067 @code{ReadOnlyDict::SoundslikeElements::next} which is found in file
1068 @file{readonly_ws.cpp}.
1069
1070 The next part will describe how Aspell deals with @emph{soundslike}
1071 lookup when affix compression is involved.
1072
1073 @node Part 3, Copying, Part 2 - Quickly Finding Similar Soundslike, How It All Works
1074 @section Part 3
1075
1076 Not written yet.
1077
1078 @node Copying,  , Part 3, Top
1079 @appendix Copying
1080
1081 Copyright @copyright{} 2002, 2003, 2004, 2006 Kevin Atkinson.
1082
1083 Permission is granted to copy, distribute and/or modify this document
1084 under the terms of the GNU Free Documentation License, Version 1.1 or
1085 any later version published by the Free Software Foundation; with no
1086 Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.  A
1087 copy of the license is included in the section entitled "GNU Free
1088 Documentation License".
1089
1090 @menu
1091 * GNU Free Documentation License::
1092 @end menu
1093
1094 @include fdl.texi
1095
1096
1097 @c @node Index,  , Copying, Top
1098 @c @unnumbered Index
1099
1100 @c @printindex cp
1101
1102 @bye
1103