docs/master

diff discussion.roff @ 219:8c537982d718

Further improvements of the discussion chapter. There's a bit more to come ... tomorrow.
author markus schnalke <meillo@marmaro.de>
date Sat, 14 Jul 2012 23:19:27 +0200
parents f3f65376bef9
children 95257474a123
line diff
     1.1 --- a/discussion.roff	Sat Jul 14 18:05:19 2012 +0200
     1.2 +++ b/discussion.roff	Sat Jul 14 23:19:27 2012 +0200
     1.3 @@ -2879,21 +2879,18 @@
     1.4  .H1 "Styling
     1.5  .P
     1.6  Kernighan and Pike have emphasized the importance of style in the
     1.7 -preface of their book:
     1.8 +preface of \fPThe Practice of Programming\fP:
     1.9  .[ [
    1.10  kernighan pike practice of programming
    1.11  .], p. x]
    1.12  .QS
    1.13  Chapter 1 discusses programming style.
    1.14 -Good style is so important to good programming that we have chose
    1.15 +Good style is so important to good programming that we have chosen
    1.16  to cover it first.
    1.17  .QE
    1.18  This section covers changes in mmh that were guided by the desire
    1.19  to improve on style.
    1.20 -Many of them follow the rules given in the quoted book.
    1.21 -.[
    1.22 -kernighan pike practice of programming
    1.23 -.]
    1.24 +Many of them follow the advice given in the quoted book.
    1.25  
    1.26  
    1.27  
    1.28 @@ -2903,12 +2900,11 @@
    1.29  .P
    1.30  .U3 "Indentation Style
    1.31  .P
    1.32 -Indentation styles are the holy cow of programmers.
    1.33 -Kernighan and Pike
    1.34 +Indentation styles are the holy cow of programming.
    1.35 +Kernighan and Pike write:
    1.36  .[ [
    1.37  kernighan pike practice of programming
    1.38  .], p. 10]
    1.39 -wrote:
    1.40  .QS
    1.41  Programmers have always argued about the layout of programs,
    1.42  but the specific style is much less important than its consistent
    1.43 @@ -2920,30 +2916,32 @@
    1.44  I agree that the constant application is most important,
    1.45  but I believe that some styles have advantages over others.
    1.46  For instance the indentation with tab characters only.
    1.47 -Tab characters directly map to the nesting level \(en
    1.48 +The number of tabs corresponds to the nesting level \(en
    1.49  one tab, one level.
    1.50 -Tab characters are flexible because developers can adjust them to
    1.51 -whatever width they like to have.
    1.52 -There is no more need to run
    1.53 -.Pn unexpand
    1.54 -or
    1.55 -.Pn entab
    1.56 -programs to ensure the correct mixture of leading tabs and spaces.
    1.57 -The simple rules are: (1) Leading whitespace must consist of tabs only.
    1.58 -(2) Any other whitespace should consist of spaces.
    1.59 -These two rules ensure the integrity of the visual appearance.
    1.60 +Tab characters provide flexible visual appearance because developers
    1.61 +can adjust their width as prefered.
    1.62 +There is no more need to check for the correct mixture of
    1.63 +tabs and spaces.
    1.64 +Two simple rules ensure the integrity and flexibility of the visual
    1.65 +appearance:
    1.66 +.LI 1
    1.67 +Leading whitespace must consist of tabs only.
    1.68 +.LI 2
    1.69 +All other whitespace should be spaces.
    1.70 +.LP
    1.71  Although reformatting existing code should be avoided, I did it.
    1.72  I did not waste time arguing; I just reformatted the code.
    1.73  .Ci a485ed478abbd599d8c9aab48934e7a26733ecb1
    1.74  
    1.75  .U3 "Comments
    1.76  .P
    1.77 -Section 1.6 of
    1.78 +Kernighan and Pike demand: ``Don't belabor the obvious''.
    1.79  .[ [
    1.80  kernighan pike practice of programming
    1.81  .], p. 23]
    1.82 -demands: ``Don't belabor the obvious.''
    1.83 -Hence, I simply removed all the comments in the following code excerpt:
    1.84 +Following the advice, I removed unnecessary comments.
    1.85 +For instance, I removed all comments in the following code excerpt
    1.86 +.Ci 426543622b377fc5d091455cba685e114b6df674 :
    1.87  .VS
    1.88  context_replace(curfolder, folder);  /* update current folder  */
    1.89  seq_setcur(mp, mp->lowsel);  /* update current message */
    1.90 @@ -2961,14 +2959,15 @@
    1.91  /* NUL-terminate the field */
    1.92  *cp = '\0';
    1.93  VE
    1.94 -.Ci 426543622b377fc5d091455cba685e114b6df674
    1.95  .P
    1.96 -The program code explains enough itself, already.
    1.97 +The information in each of the comments was present in the code
    1.98 +statements already, except for the NUL-termination, which became
    1.99 +obvious from the context.
   1.100  
   1.101  
   1.102  .U3 "Names
   1.103  .P
   1.104 -Kernighan and Pike suggest:
   1.105 +Regarding this topic, Kernighan and Pike suggest:
   1.106  ``Use active names for functions''.
   1.107  .[ [
   1.108  kernighan pike practice of programming
   1.109 @@ -2976,16 +2975,20 @@
   1.110  One application of this rule was the rename of
   1.111  .Fu check_charset()
   1.112  to
   1.113 -.Fu is_native_charset() .
   1.114 -.Ci 8d77b48284c58c135a6b2787e721597346ab056d
   1.115 -The same change fixed a violation of ``Be accurate''
   1.116 +.Fu is_native_charset()
   1.117 +.Ci 8d77b48284c58c135a6b2787e721597346ab056d .
   1.118 +The same change additionally fixed a violation of ``Be accurate'',
   1.119  .[ [
   1.120  kernighan pike practice of programming
   1.121  .], p. 4]
   1.122 -as well.
   1.123 -The code did not match the expectation the function suggested,
   1.124 -as it, for whatever reason, only compared the first ten characters
   1.125 -of the charset name.
   1.126 +as the code did not match the expectation the function suggested.
   1.127 +It did not compare charset names but prefixes of them only.
   1.128 +In case the native charset was `ISO-8859-1', then
   1.129 +.VS
   1.130 +check_charset("ISO-8859-11", strlen("ISO-8859-11"))
   1.131 +VE
   1.132 +had returned true although the upper halves of the code pages
   1.133 +are different.
   1.134  .P
   1.135  More important than using active names is using descriptive names.
   1.136  .VS
   1.137 @@ -2993,8 +2996,8 @@
   1.138  VE
   1.139  Renaming the obscure
   1.140  .Fu m_unknown()
   1.141 -function was a delightful event, although it made the code less funny.
   1.142 -.Ci 611d68d19204d7cbf5bd585391249cb5bafca846
   1.143 +function was a delightful event, although it made the code less funny
   1.144 +.Ci 611d68d19204d7cbf5bd585391249cb5bafca846 .
   1.145  .P
   1.146  Magic numbers are generally considered bad style.
   1.147  Obviously, Kernighan and Pike agree:
   1.148 @@ -3002,57 +3005,70 @@
   1.149  .[ [
   1.150  kernighan pike practice of programming
   1.151  .], p. 19]
   1.152 -One such change was naming the type of input \(en mbox or mail folder \(en
   1.153 -to be scanned:
   1.154 +.P
   1.155 +The argument
   1.156 +.CW outnum
   1.157 +of the function
   1.158 +.Fu scan()
   1.159 +in
   1.160 +.Fn uip/scansbr.c
   1.161 +holds the number of the message to be created.
   1.162 +As well it encodes program logic with negative numbers and zero.
   1.163 +This led to obscure code.
   1.164 +I clarified the code by introducing two variables that extracted
   1.165 +the hidden information:
   1.166 +.VS
   1.167 +int incing = (outnum > 0);
   1.168 +int ismbox = (outnum != 0);
   1.169 +VE
   1.170 +The readable names are thus used in conditions;
   1.171 +the variable
   1.172 +.CW outnum
   1.173 +is used only to extract ordinary message numbers
   1.174 +.Ci b8b075c77be7794f3ae9ff0e8cedb12b48fd139f .
   1.175 +.P
   1.176 +Through the clarity improvement of the change detours in the program
   1.177 +logic of related code parts became apparent.
   1.178 +The implementation was simplified.
   1.179 +This possibility to improve had been invisible before
   1.180 +.Ci aa60b0ab5e804f8befa890c0a6df0e3143ce0723 .
   1.181 +.P
   1.182 +The names just described were a first step, yet the situation
   1.183 +was further improved by giving names to the magic values of
   1.184 +.CW outnum :
   1.185  .VS
   1.186  #define SCN_MBOX (-1)
   1.187  #define SCN_FOLD 0
   1.188  VE
   1.189 +The two variables were updated thereafter as well:
   1.190 +.VS
   1.191 +int incing = (outnum != SCN_MBOX && outnum != SCN_FOLD);
   1.192 +int scanfolder = (outnum == SCN_FOLD);
   1.193 +VE
   1.194 +Furthermore,
   1.195 +.CW ismbox
   1.196 +was replaced by
   1.197 +.CW scanfolder
   1.198 +because that matched better to the program logic.
   1.199  .Ci 7ffb36d28e517a6f3a10272056fc127592ab1c19
   1.200 -.P
   1.201 -The argument
   1.202 -.Ar outnum
   1.203 -of the function
   1.204 -.Fu scan()
   1.205 -in
   1.206 -.Fn uip/scansbr.c
   1.207 -defines the number of the message to be created.
   1.208 -If no message is to be created, the argument is misused to transport
   1.209 -program logic.
   1.210 -This lead to obscure code.
   1.211 -I improved the clarity of the code by introducing two variables:
   1.212 -.VS
   1.213 -int incing = (outnum > 0);
   1.214 -int ismbox = (outnum != 0);
   1.215 -VE
   1.216 -They cover the magic values and are used for conditions.
   1.217 -The variable
   1.218 -.Ar outnum
   1.219 -is only used when it holds an ordinary message number.
   1.220 -.Ci b8b075c77be7794f3ae9ff0e8cedb12b48fd139f
   1.221 -The clarity improvement of the change showed detours in the program logic
   1.222 -of related code parts.
   1.223 -Having the new variables with descriptive names, a more
   1.224 -straight forward implementation became apparent.
   1.225 -Before the code was clarified, the possibility to improve had not be seen.
   1.226 -.Ci aa60b0ab5e804f8befa890c0a6df0e3143ce0723
   1.227 +
   1.228  
   1.229  
   1.230  
   1.231  .H2 "Structural Rework
   1.232  .P
   1.233 -Although the stylistic changes described up to here improve the
   1.234 -readability of the source code, all of them are changes ``in the small''.
   1.235 -Structural changes affect a much larger area.
   1.236 -They are more difficult to do but lead to larger improvements,
   1.237 -especially as they influence the outer shape of the tools as well.
   1.238 +Although the stylistic changes described already improve the
   1.239 +readability of the source code, all of them were changes ``in the small''.
   1.240 +Structural changes, in contrast, affect much larger code areas.
   1.241 +They are more difficult to accomplish but lead to larger improvements,
   1.242 +especially as they often influence the outer shape of the tools as well.
   1.243  .P
   1.244  At the end of their chapter on style,
   1.245  Kernighan and Pike ask: ``But why worry about style?''
   1.246  .[ [
   1.247  kernighan pike practice of programming
   1.248 -.], p. 28]
   1.249 -Following are two examples of structural rework that show
   1.250 +.], p. 28].
   1.251 +Following are two examples of structural rework that demonstrate
   1.252  why style is important in the first place.
   1.253  
   1.254  
   1.255 @@ -3060,11 +3076,11 @@
   1.256  .P
   1.257  Until 2002,
   1.258  .Pn anno
   1.259 -had six functional command line switches,
   1.260 +had six functional command line switches:
   1.261  .Sw -component
   1.262  and
   1.263  .Sw -text ,
   1.264 -which have an argument each,
   1.265 +each with an argument,
   1.266  and the two pairs of flags,
   1.267  .Sw -[no]date
   1.268  and
   1.269 @@ -3079,26 +3095,26 @@
   1.270  .Sw -append ,
   1.271  and
   1.272  .Sw -number ,
   1.273 -the last one taking an argument.
   1.274 -.Ci 7480dbc14bc90f2d872d434205c0784704213252
   1.275 +the last one taking an argument
   1.276 +.Ci 7480dbc14bc90f2d872d434205c0784704213252 .
   1.277  Later,
   1.278  .Sw -[no]preserve
   1.279 -was added.
   1.280 -.Ci d9b1d57351d104d7ec1a5621f090657dcce8cb7f
   1.281 +was added as well
   1.282 +.Ci d9b1d57351d104d7ec1a5621f090657dcce8cb7f .
   1.283  Then, the Synopsis section of the man page
   1.284  .Mp anno (1)
   1.285  read:
   1.286  .VS
   1.287 -anno [+folder] [msgs] [-component field] [-inplace | -noinplace]
   1.288 +anno [+folder] [msgs] [-component f(CIfieldfP] [-inplace | -noinplace]
   1.289  	[-date | -nodate] [-draft] [-append] [-list] [-delete]
   1.290 -	[-number [num|all]] [-preserve | -nopreserve] [-version]
   1.291 -	[-help] [-text body]
   1.292 +	[-number [f(CInumfP|fPallfP]] [-preserve | -nopreserve] [-version]
   1.293 +	[-help] [-text f(CIbodyfP]
   1.294  VE
   1.295  .LP
   1.296  The implementation followed the same structure.
   1.297  Problems became visible when
   1.298  .Cl "anno -list -number 42
   1.299 -worked on the current message instead on message number 42,
   1.300 +worked on the current message instead of on message number 42,
   1.301  and
   1.302  .Cl "anno -list -number l:5
   1.303  did not work on the last five messages but failed with the mysterious
   1.304 @@ -3122,59 +3138,51 @@
   1.305  .QE
   1.306  .LP
   1.307  The problem was manifold.
   1.308 -The code required a numeric argument to the
   1.309 -.Sw -number
   1.310 -switch.
   1.311 -If it was missing or non-numeric,
   1.312 -.Pn anno
   1.313 -aborted with an error message that had an off-by-one error,
   1.314 -printing the switch one before the failing one.
   1.315  Semantically, the argument to the
   1.316  .Sw -number
   1.317  switch is only necessary in combination with
   1.318  .Sw -delete ,
   1.319  but not with
   1.320  .Sw -list .
   1.321 +The code, however, required a numeric argument in any case.
   1.322 +If the argument was missing or non-numeric,
   1.323 +.Pn anno
   1.324 +aborted with an error message that additionally had an off-by-one error.
   1.325 +It printed the name of the switch one before the concerned one.
   1.326  .P
   1.327 -Trying to fix these problems on the surface would not have solved
   1.328 -them truly, as they originate from a discrepance between the
   1.329 +Trying to fix these problems on the surface would not have solved them.
   1.330 +They originate from a discrepance between the
   1.331  structure of the problem and the structure implemented in the program.
   1.332 -Such structural differences can not be cured on the surface.
   1.333 -They need to be solved by adjusting the structure of the implementation
   1.334 -to the structure of the problem.
   1.335 +Such structural differences can only be solved by adjusting the
   1.336 +structure of the implementation to the structure of the problem.
   1.337  .P
   1.338 -In 2002, the new switches
   1.339 +Steinhart had added the new
   1.340  .Sw -list
   1.341  and
   1.342  .Sw -delete
   1.343 -were added in the same way, the
   1.344 -.Sw -number
   1.345 -switch for instance had been added.
   1.346 -Yet, they are of structural different type.
   1.347 +switches in a style similar to the other switches though
   1.348 +they are of structural different type.
   1.349  Semantically,
   1.350  .Sw -list
   1.351  and
   1.352  .Sw -delete
   1.353 -introduce modes of operation.
   1.354 +introduce operation modes.
   1.355  Historically,
   1.356  .Pn anno
   1.357  had only one operation mode: adding header fields.
   1.358 -With the extension it got two more modes:
   1.359 -.\" XXX got
   1.360 +With the extension, two more modes were added:
   1.361  listing and deleting header fields.
   1.362  The structure of the code changes did not pay respect to this
   1.363 -fundamental change to
   1.364 -.Pn anno 's
   1.365 -behavior.
   1.366 +fundamental change.
   1.367  Neither the implementation nor the documentation did clearly
   1.368 -define them as being exclusive modes of operation.
   1.369 +declare the exclusive operation modes as such.
   1.370  Having identified the problem, I solved it by putting structure into
   1.371  .Pn anno
   1.372 -and its documentation.
   1.373 -.Ci d54c8db8bdf01e8381890f7729bc0ef4a055ea11
   1.374 +and its documentation
   1.375 +.Ci d54c8db8bdf01e8381890f7729bc0ef4a055ea11 .
   1.376  .P
   1.377  The difference is visible in both the code and the documentation.
   1.378 -The following code excerpt:
   1.379 +For instance in the following code excerpt:
   1.380  .VS
   1.381  int delete = -2;  /* delete header element if set */
   1.382  int list = 0;  /* list header elements if set */
   1.383 @@ -3187,7 +3195,7 @@
   1.384  		continue;
   1.385  VE
   1.386  .LP
   1.387 -was replaced by:
   1.388 +which was replaced by:
   1.389  .VS
   1.390  static enum { MODE_ADD, MODE_DEL, MODE_LIST } mode = MODE_ADD;
   1.391  [...]
   1.392 @@ -3203,20 +3211,19 @@
   1.393  it is easier to understand as well.
   1.394  The same applies to the documentation.
   1.395  The man page was completely reorganized to propagate the same structure.
   1.396 -This is visible in the Synopsis section:
   1.397 +This is already visible in the Synopsis section:
   1.398  .VS
   1.399 -anno [+folder] [msgs] [-component field] [-text body]
   1.400 +anno [+folder] [msgs] [-component f(CIfieldfP] [-text fPbodyfP]
   1.401  	[-append] [-date | -nodate] [-preserve | -nopreserve]
   1.402  	[-Version] [-help]
   1.403  
   1.404 -anno -delete [+folder] [msgs] [-component field] [-text
   1.405 -	body] [-number num | all ] [-preserve | -nopreserve]
   1.406 +anno -delete [+folder] [msgs] [-component fPfieldfP] [-text
   1.407 +	fPbodyfP] [-number fPnum fP| fPall fP] [-preserve | -nopreserve]
   1.408  	[-Version] [-help]
   1.409  
   1.410 -anno -list [+folder] [msgs] [-component field] [-number]
   1.411 +anno -list [+folder] [msgs] [-component fPfieldfP] [-number]
   1.412  	[-Version] [-help]
   1.413  VE
   1.414 -.\" XXX think about explaining the -preserve rework?
   1.415  
   1.416  
   1.417  
   1.418 @@ -3231,21 +3238,20 @@
   1.419  .Fn ./foo/bar .
   1.420  .LI 3
   1.421  Absolute MH folder paths, like
   1.422 -.Fn +friends/phil .
   1.423 +.Fn +projects/mmh .
   1.424  .LI 4
   1.425  Relative MH folder paths, like
   1.426  .Fn @subfolder .
   1.427  .LP
   1.428 -The last type, relative MH folder paths, are hardly documented.
   1.429 -Nonetheless, they are useful for large mail storages.
   1.430 +Relative MH folder paths, are hardly documented
   1.431 +although they are useful for large mail storages.
   1.432  The current mail folder is specified as `\c
   1.433  .Fn @ ',
   1.434  just like the current directory is specified as `\c
   1.435  .Fn . '.
   1.436  .P
   1.437  To allow MH tools to understand all four notations,
   1.438 -they need to convert between them.
   1.439 -.\" XXX between?
   1.440 +they need to be able to convert between them.
   1.441  In nmh, these path name conversion functions were located in the files
   1.442  .Fn sbr/path.c
   1.443  (``return a pathname'') and
   1.444 @@ -3253,19 +3259,23 @@
   1.445  (``get the path for the mail directory'').
   1.446  The seven functions in the two files were documented with no more
   1.447  than two comments, which described obvious information.
   1.448 -The function signatures were neither explaining:
   1.449 -.VS
   1.450 -char *path(char *, int);
   1.451 -char *pluspath(char *);
   1.452 -char *m_mailpath(char *);
   1.453 -char *m_maildir(char *);
   1.454 -VE
   1.455 +The signatures of the four exported functions did not explain their
   1.456 +semantics:
   1.457 +.LI 1
   1.458 +.CW "char *path(char *, int);
   1.459 +.LI 2
   1.460 +.CW "char *pluspath(char *);
   1.461 +.LI 3
   1.462 +.CW "char *m_mailpath(char *);
   1.463 +.LI 4
   1.464 +.CW "char *m_maildir(char *);
   1.465  .P
   1.466 -My investigation provides the following description:
   1.467 +My investigations provided the following descriptions:
   1.468  .LI 1
   1.469  The second parameter of
   1.470  .Fu path()
   1.471 -defines the type of path given as first parameter.
   1.472 +defines the type as which the path given in the first parameter should
   1.473 +be treated.
   1.474  Directory paths are converted to absolute directory paths.
   1.475  Folder paths are converted to absolute folder paths.
   1.476  Folder paths must not include a leading `\fL@\fP' character.
   1.477 @@ -3284,41 +3294,41 @@
   1.478  The characters `\fL+\fP' or `\fL@\fP' at the beginning of the path name are
   1.479  treated literal, i.e. as the first character of a relative directory path.
   1.480  Hence, this function can not be used for folder paths.
   1.481 -In any case, the result is an absolute directory path.
   1.482 -The result is a pointer to newly allocated memory.
   1.483 +In any case, the result is an absolute directory path,
   1.484 +returned as a pointer to newly allocated memory.
   1.485  .LI 4
   1.486  .Fu m_maildir()
   1.487  returns the parameter unchanged if it is an absolute directory path
   1.488  or begins with the entry `\fL.\fP' or `\fL..\fP'.
   1.489  All other strings are prepended with the current working directory.
   1.490 -Hence, this functions can not be used for folder paths.
   1.491 +Hence, this function can not be used for folder paths.
   1.492  The result is either an absolute directory path or a relative
   1.493 -directory path, starting with a dot.
   1.494 +directory path, starting with dot or dot-dot.
   1.495  In contrast to the other functions, the result is a pointer to
   1.496  static memory.
   1.497  .P
   1.498  The situation was obscure, irritating, error-prone, and non-orthogonal.
   1.499 -No clear terminology was used to name the different kinds of path names.
   1.500 -The first argument of
   1.501 +Additionally, no clear terminology was used to name the different
   1.502 +kinds of path names.
   1.503 +Sometimes, the names were even misleading, much as the first argument of
   1.504  .Fu m_mailpath() ,
   1.505 -for instance, was named
   1.506 -.Ar folder ,
   1.507 -though
   1.508 +which was named
   1.509 +.CW folder ,
   1.510 +although
   1.511  .Fu m_mailpath()
   1.512 -can not be used for MH folders.
   1.513 +could not be used with MH folder arguments.
   1.514  .P
   1.515 -I reworked the path name conversion completely, introducing clarity.
   1.516 +I clarified the path name conversion by complete rework.
   1.517  First of all, the terminology needed to be defined.
   1.518  A path name is either in the Unix domain, then it is called
   1.519 -\fIdirectory path\fP, `dirpath' for short, or it is in the MH domain,
   1.520 -then it is called \fIfolder path\fP, `folpath' for short.
   1.521 +\fIdirectory path\fP (\fIdirpath\fP for short) or it is in the MH domain,
   1.522 +then it is called \fIfolder path\fP (\fIfolpath\fP for short).
   1.523  The two terms need to be used with strict distinction.
   1.524 -Having a clear terminology is often an indicator of having understood
   1.525 -the problem itself.
   1.526 +Often a clear terminology indicates that the problem is understood.
   1.527  Second, I exploited the concept of path type indicators.
   1.528 -By requesting every path name to start with a clear type identifier,
   1.529 -conversion between the types can be fully automated.
   1.530 -Thus the tools can accept paths of any type from the user.
   1.531 +By requiring every path name to start with a distinct type identifier,
   1.532 +the conversion between the types could be fully automated.
   1.533 +This allows the tools to accept paths of any type from the user.
   1.534  Therefore, it was necessary to require relative directory paths to be
   1.535  prefixed with a dot character.
   1.536  In consequence, the dot character could no longer be an alias for the
   1.537 @@ -3327,8 +3337,7 @@
   1.538  Third, I created three new functions to replace the previous mess:
   1.539  .LI 1
   1.540  .Fu expandfol()
   1.541 -converts folder paths to absolute folder paths,
   1.542 -without the leading plus character.
   1.543 +converts folder paths to absolute folder paths.
   1.544  Directory paths are simply passed through.
   1.545  This function is to be used for folder paths only, thus the name.
   1.546  The result is a pointer to static memory.
   1.547 @@ -3353,10 +3362,11 @@
   1.548  The third function converts any path name type to the most general one,
   1.549  the absolute directory path.
   1.550  All of the functions return pointers to static memory.
   1.551 -All three functions are implemented in
   1.552 -.Fn sbr/path.c .
   1.553 +The file
   1.554 +.Fn sbr/path.c
   1.555 +contains the implementation of the functions;
   1.556  .Fn sbr/m_maildir.c
   1.557 -is removed.
   1.558 +was removed.
   1.559  .Ci d39e2c447b0d163a5a63f480b23d06edb7a73aa0
   1.560  .P
   1.561  Along with the path conversion rework, I also replaced
   1.562 @@ -3367,31 +3377,30 @@
   1.563  .Fu getfolder(FCUR)
   1.564  with
   1.565  .Fu getcurfol() ,
   1.566 -which is only a convenience wrapper for
   1.567 -.Fu expandfol("@") .
   1.568 +which only wraps
   1.569 +.Fu expandfol(""@"")
   1.570 +for convenience.
   1.571  This code was moved from
   1.572  .Fn sbr/getfolder.c
   1.573 -to
   1.574 -.Fn sbr/path.c .
   1.575 +into
   1.576 +.Fn sbr/path.c
   1.577 +as well.
   1.578  .Ci d39e2c447b0d163a5a63f480b23d06edb7a73aa0
   1.579  .P
   1.580  The related function
   1.581  .Fu etcpath()
   1.582 -was moved to
   1.583 +is now included in
   1.584  .Fn sbr/path.c ,
   1.585  too
   1.586  .Ci b4c29794c12099556151d93a860ee51badae2e35 .
   1.587  Previously, it had been located in
   1.588 -.Fn config/config.c ,
   1.589 -for whatever reasons.
   1.590 +.Fn config/config.c .
   1.591  .P
   1.592 +Now,
   1.593  .Fn sbr/path.c
   1.594 -now contains all path handling code.
   1.595 -.\" XXX naechste zeile weg?
   1.596 -Only 173 lines of code were needed to replace the previous 252 lines.
   1.597 -The readability of the code is highly improved.
   1.598 -Additionally, each of the six exported and one static functions
   1.599 -is introduced by an explaining comment.
   1.600 +contains all path handling code.
   1.601 +Besides being less code, its readability is highly improved.
   1.602 +The functions follow a common style and are well documented.
   1.603  
   1.604  
   1.605