Mercurial > docs > master
comparison 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 |
comparison
equal
deleted
inserted
replaced
218:8be9e84be526 | 219:8c537982d718 |
---|---|
2877 | 2877 |
2878 .\" -------------------------------------------------------------- | 2878 .\" -------------------------------------------------------------- |
2879 .H1 "Styling | 2879 .H1 "Styling |
2880 .P | 2880 .P |
2881 Kernighan and Pike have emphasized the importance of style in the | 2881 Kernighan and Pike have emphasized the importance of style in the |
2882 preface of their book: | 2882 preface of \fPThe Practice of Programming\fP: |
2883 .[ [ | 2883 .[ [ |
2884 kernighan pike practice of programming | 2884 kernighan pike practice of programming |
2885 .], p. x] | 2885 .], p. x] |
2886 .QS | 2886 .QS |
2887 Chapter 1 discusses programming style. | 2887 Chapter 1 discusses programming style. |
2888 Good style is so important to good programming that we have chose | 2888 Good style is so important to good programming that we have chosen |
2889 to cover it first. | 2889 to cover it first. |
2890 .QE | 2890 .QE |
2891 This section covers changes in mmh that were guided by the desire | 2891 This section covers changes in mmh that were guided by the desire |
2892 to improve on style. | 2892 to improve on style. |
2893 Many of them follow the rules given in the quoted book. | 2893 Many of them follow the advice given in the quoted book. |
2894 .[ | |
2895 kernighan pike practice of programming | |
2896 .] | |
2897 | 2894 |
2898 | 2895 |
2899 | 2896 |
2900 | 2897 |
2901 .H2 "Code Style | 2898 .H2 "Code Style |
2902 .Id code-style | 2899 .Id code-style |
2903 .P | 2900 .P |
2904 .U3 "Indentation Style | 2901 .U3 "Indentation Style |
2905 .P | 2902 .P |
2906 Indentation styles are the holy cow of programmers. | 2903 Indentation styles are the holy cow of programming. |
2907 Kernighan and Pike | 2904 Kernighan and Pike write: |
2908 .[ [ | 2905 .[ [ |
2909 kernighan pike practice of programming | 2906 kernighan pike practice of programming |
2910 .], p. 10] | 2907 .], p. 10] |
2911 wrote: | |
2912 .QS | 2908 .QS |
2913 Programmers have always argued about the layout of programs, | 2909 Programmers have always argued about the layout of programs, |
2914 but the specific style is much less important than its consistent | 2910 but the specific style is much less important than its consistent |
2915 application. | 2911 application. |
2916 Pick one style, preferably ours, use it consistently, and don't waste | 2912 Pick one style, preferably ours, use it consistently, and don't waste |
2918 .QE | 2914 .QE |
2919 .P | 2915 .P |
2920 I agree that the constant application is most important, | 2916 I agree that the constant application is most important, |
2921 but I believe that some styles have advantages over others. | 2917 but I believe that some styles have advantages over others. |
2922 For instance the indentation with tab characters only. | 2918 For instance the indentation with tab characters only. |
2923 Tab characters directly map to the nesting level \(en | 2919 The number of tabs corresponds to the nesting level \(en |
2924 one tab, one level. | 2920 one tab, one level. |
2925 Tab characters are flexible because developers can adjust them to | 2921 Tab characters provide flexible visual appearance because developers |
2926 whatever width they like to have. | 2922 can adjust their width as prefered. |
2927 There is no more need to run | 2923 There is no more need to check for the correct mixture of |
2928 .Pn unexpand | 2924 tabs and spaces. |
2929 or | 2925 Two simple rules ensure the integrity and flexibility of the visual |
2930 .Pn entab | 2926 appearance: |
2931 programs to ensure the correct mixture of leading tabs and spaces. | 2927 .LI 1 |
2932 The simple rules are: (1) Leading whitespace must consist of tabs only. | 2928 Leading whitespace must consist of tabs only. |
2933 (2) Any other whitespace should consist of spaces. | 2929 .LI 2 |
2934 These two rules ensure the integrity of the visual appearance. | 2930 All other whitespace should be spaces. |
2931 .LP | |
2935 Although reformatting existing code should be avoided, I did it. | 2932 Although reformatting existing code should be avoided, I did it. |
2936 I did not waste time arguing; I just reformatted the code. | 2933 I did not waste time arguing; I just reformatted the code. |
2937 .Ci a485ed478abbd599d8c9aab48934e7a26733ecb1 | 2934 .Ci a485ed478abbd599d8c9aab48934e7a26733ecb1 |
2938 | 2935 |
2939 .U3 "Comments | 2936 .U3 "Comments |
2940 .P | 2937 .P |
2941 Section 1.6 of | 2938 Kernighan and Pike demand: ``Don't belabor the obvious''. |
2942 .[ [ | 2939 .[ [ |
2943 kernighan pike practice of programming | 2940 kernighan pike practice of programming |
2944 .], p. 23] | 2941 .], p. 23] |
2945 demands: ``Don't belabor the obvious.'' | 2942 Following the advice, I removed unnecessary comments. |
2946 Hence, I simply removed all the comments in the following code excerpt: | 2943 For instance, I removed all comments in the following code excerpt |
2944 .Ci 426543622b377fc5d091455cba685e114b6df674 : | |
2947 .VS | 2945 .VS |
2948 context_replace(curfolder, folder); /* update current folder */ | 2946 context_replace(curfolder, folder); /* update current folder */ |
2949 seq_setcur(mp, mp->lowsel); /* update current message */ | 2947 seq_setcur(mp, mp->lowsel); /* update current message */ |
2950 seq_save(mp); /* synchronize message sequences */ | 2948 seq_save(mp); /* synchronize message sequences */ |
2951 folder_free(mp); /* free folder/message structure */ | 2949 folder_free(mp); /* free folder/message structure */ |
2959 [...] | 2957 [...] |
2960 | 2958 |
2961 /* NUL-terminate the field */ | 2959 /* NUL-terminate the field */ |
2962 *cp = '\0'; | 2960 *cp = '\0'; |
2963 VE | 2961 VE |
2964 .Ci 426543622b377fc5d091455cba685e114b6df674 | 2962 .P |
2965 .P | 2963 The information in each of the comments was present in the code |
2966 The program code explains enough itself, already. | 2964 statements already, except for the NUL-termination, which became |
2965 obvious from the context. | |
2967 | 2966 |
2968 | 2967 |
2969 .U3 "Names | 2968 .U3 "Names |
2970 .P | 2969 .P |
2971 Kernighan and Pike suggest: | 2970 Regarding this topic, Kernighan and Pike suggest: |
2972 ``Use active names for functions''. | 2971 ``Use active names for functions''. |
2973 .[ [ | 2972 .[ [ |
2974 kernighan pike practice of programming | 2973 kernighan pike practice of programming |
2975 .], p. 4] | 2974 .], p. 4] |
2976 One application of this rule was the rename of | 2975 One application of this rule was the rename of |
2977 .Fu check_charset() | 2976 .Fu check_charset() |
2978 to | 2977 to |
2979 .Fu is_native_charset() . | 2978 .Fu is_native_charset() |
2980 .Ci 8d77b48284c58c135a6b2787e721597346ab056d | 2979 .Ci 8d77b48284c58c135a6b2787e721597346ab056d . |
2981 The same change fixed a violation of ``Be accurate'' | 2980 The same change additionally fixed a violation of ``Be accurate'', |
2982 .[ [ | 2981 .[ [ |
2983 kernighan pike practice of programming | 2982 kernighan pike practice of programming |
2984 .], p. 4] | 2983 .], p. 4] |
2985 as well. | 2984 as the code did not match the expectation the function suggested. |
2986 The code did not match the expectation the function suggested, | 2985 It did not compare charset names but prefixes of them only. |
2987 as it, for whatever reason, only compared the first ten characters | 2986 In case the native charset was `ISO-8859-1', then |
2988 of the charset name. | 2987 .VS |
2988 check_charset("ISO-8859-11", strlen("ISO-8859-11")) | |
2989 VE | |
2990 had returned true although the upper halves of the code pages | |
2991 are different. | |
2989 .P | 2992 .P |
2990 More important than using active names is using descriptive names. | 2993 More important than using active names is using descriptive names. |
2991 .VS | 2994 .VS |
2992 m_unknown(in); /* the MAGIC invocation... */ | 2995 m_unknown(in); /* the MAGIC invocation... */ |
2993 VE | 2996 VE |
2994 Renaming the obscure | 2997 Renaming the obscure |
2995 .Fu m_unknown() | 2998 .Fu m_unknown() |
2996 function was a delightful event, although it made the code less funny. | 2999 function was a delightful event, although it made the code less funny |
2997 .Ci 611d68d19204d7cbf5bd585391249cb5bafca846 | 3000 .Ci 611d68d19204d7cbf5bd585391249cb5bafca846 . |
2998 .P | 3001 .P |
2999 Magic numbers are generally considered bad style. | 3002 Magic numbers are generally considered bad style. |
3000 Obviously, Kernighan and Pike agree: | 3003 Obviously, Kernighan and Pike agree: |
3001 ``Give names to magic numbers''. | 3004 ``Give names to magic numbers''. |
3002 .[ [ | 3005 .[ [ |
3003 kernighan pike practice of programming | 3006 kernighan pike practice of programming |
3004 .], p. 19] | 3007 .], p. 19] |
3005 One such change was naming the type of input \(en mbox or mail folder \(en | 3008 .P |
3006 to be scanned: | 3009 The argument |
3010 .CW outnum | |
3011 of the function | |
3012 .Fu scan() | |
3013 in | |
3014 .Fn uip/scansbr.c | |
3015 holds the number of the message to be created. | |
3016 As well it encodes program logic with negative numbers and zero. | |
3017 This led to obscure code. | |
3018 I clarified the code by introducing two variables that extracted | |
3019 the hidden information: | |
3020 .VS | |
3021 int incing = (outnum > 0); | |
3022 int ismbox = (outnum != 0); | |
3023 VE | |
3024 The readable names are thus used in conditions; | |
3025 the variable | |
3026 .CW outnum | |
3027 is used only to extract ordinary message numbers | |
3028 .Ci b8b075c77be7794f3ae9ff0e8cedb12b48fd139f . | |
3029 .P | |
3030 Through the clarity improvement of the change detours in the program | |
3031 logic of related code parts became apparent. | |
3032 The implementation was simplified. | |
3033 This possibility to improve had been invisible before | |
3034 .Ci aa60b0ab5e804f8befa890c0a6df0e3143ce0723 . | |
3035 .P | |
3036 The names just described were a first step, yet the situation | |
3037 was further improved by giving names to the magic values of | |
3038 .CW outnum : | |
3007 .VS | 3039 .VS |
3008 #define SCN_MBOX (-1) | 3040 #define SCN_MBOX (-1) |
3009 #define SCN_FOLD 0 | 3041 #define SCN_FOLD 0 |
3010 VE | 3042 VE |
3043 The two variables were updated thereafter as well: | |
3044 .VS | |
3045 int incing = (outnum != SCN_MBOX && outnum != SCN_FOLD); | |
3046 int scanfolder = (outnum == SCN_FOLD); | |
3047 VE | |
3048 Furthermore, | |
3049 .CW ismbox | |
3050 was replaced by | |
3051 .CW scanfolder | |
3052 because that matched better to the program logic. | |
3011 .Ci 7ffb36d28e517a6f3a10272056fc127592ab1c19 | 3053 .Ci 7ffb36d28e517a6f3a10272056fc127592ab1c19 |
3012 .P | 3054 |
3013 The argument | |
3014 .Ar outnum | |
3015 of the function | |
3016 .Fu scan() | |
3017 in | |
3018 .Fn uip/scansbr.c | |
3019 defines the number of the message to be created. | |
3020 If no message is to be created, the argument is misused to transport | |
3021 program logic. | |
3022 This lead to obscure code. | |
3023 I improved the clarity of the code by introducing two variables: | |
3024 .VS | |
3025 int incing = (outnum > 0); | |
3026 int ismbox = (outnum != 0); | |
3027 VE | |
3028 They cover the magic values and are used for conditions. | |
3029 The variable | |
3030 .Ar outnum | |
3031 is only used when it holds an ordinary message number. | |
3032 .Ci b8b075c77be7794f3ae9ff0e8cedb12b48fd139f | |
3033 The clarity improvement of the change showed detours in the program logic | |
3034 of related code parts. | |
3035 Having the new variables with descriptive names, a more | |
3036 straight forward implementation became apparent. | |
3037 Before the code was clarified, the possibility to improve had not be seen. | |
3038 .Ci aa60b0ab5e804f8befa890c0a6df0e3143ce0723 | |
3039 | 3055 |
3040 | 3056 |
3041 | 3057 |
3042 .H2 "Structural Rework | 3058 .H2 "Structural Rework |
3043 .P | 3059 .P |
3044 Although the stylistic changes described up to here improve the | 3060 Although the stylistic changes described already improve the |
3045 readability of the source code, all of them are changes ``in the small''. | 3061 readability of the source code, all of them were changes ``in the small''. |
3046 Structural changes affect a much larger area. | 3062 Structural changes, in contrast, affect much larger code areas. |
3047 They are more difficult to do but lead to larger improvements, | 3063 They are more difficult to accomplish but lead to larger improvements, |
3048 especially as they influence the outer shape of the tools as well. | 3064 especially as they often influence the outer shape of the tools as well. |
3049 .P | 3065 .P |
3050 At the end of their chapter on style, | 3066 At the end of their chapter on style, |
3051 Kernighan and Pike ask: ``But why worry about style?'' | 3067 Kernighan and Pike ask: ``But why worry about style?'' |
3052 .[ [ | 3068 .[ [ |
3053 kernighan pike practice of programming | 3069 kernighan pike practice of programming |
3054 .], p. 28] | 3070 .], p. 28]. |
3055 Following are two examples of structural rework that show | 3071 Following are two examples of structural rework that demonstrate |
3056 why style is important in the first place. | 3072 why style is important in the first place. |
3057 | 3073 |
3058 | 3074 |
3059 .U3 "Rework of \f(CWanno\fP | 3075 .U3 "Rework of \f(CWanno\fP |
3060 .P | 3076 .P |
3061 Until 2002, | 3077 Until 2002, |
3062 .Pn anno | 3078 .Pn anno |
3063 had six functional command line switches, | 3079 had six functional command line switches: |
3064 .Sw -component | 3080 .Sw -component |
3065 and | 3081 and |
3066 .Sw -text , | 3082 .Sw -text , |
3067 which have an argument each, | 3083 each with an argument, |
3068 and the two pairs of flags, | 3084 and the two pairs of flags, |
3069 .Sw -[no]date | 3085 .Sw -[no]date |
3070 and | 3086 and |
3071 .Sw -[no]inplace . | 3087 .Sw -[no]inplace . |
3072 Then Jon Steinhart introduced his attachment system. | 3088 Then Jon Steinhart introduced his attachment system. |
3077 .Sw -list , | 3093 .Sw -list , |
3078 .Sw -delete , | 3094 .Sw -delete , |
3079 .Sw -append , | 3095 .Sw -append , |
3080 and | 3096 and |
3081 .Sw -number , | 3097 .Sw -number , |
3082 the last one taking an argument. | 3098 the last one taking an argument |
3083 .Ci 7480dbc14bc90f2d872d434205c0784704213252 | 3099 .Ci 7480dbc14bc90f2d872d434205c0784704213252 . |
3084 Later, | 3100 Later, |
3085 .Sw -[no]preserve | 3101 .Sw -[no]preserve |
3086 was added. | 3102 was added as well |
3087 .Ci d9b1d57351d104d7ec1a5621f090657dcce8cb7f | 3103 .Ci d9b1d57351d104d7ec1a5621f090657dcce8cb7f . |
3088 Then, the Synopsis section of the man page | 3104 Then, the Synopsis section of the man page |
3089 .Mp anno (1) | 3105 .Mp anno (1) |
3090 read: | 3106 read: |
3091 .VS | 3107 .VS |
3092 anno [+folder] [msgs] [-component field] [-inplace | -noinplace] | 3108 anno [+folder] [msgs] [-component f(CIfieldfP] [-inplace | -noinplace] |
3093 [-date | -nodate] [-draft] [-append] [-list] [-delete] | 3109 [-date | -nodate] [-draft] [-append] [-list] [-delete] |
3094 [-number [num|all]] [-preserve | -nopreserve] [-version] | 3110 [-number [f(CInumfP|fPallfP]] [-preserve | -nopreserve] [-version] |
3095 [-help] [-text body] | 3111 [-help] [-text f(CIbodyfP] |
3096 VE | 3112 VE |
3097 .LP | 3113 .LP |
3098 The implementation followed the same structure. | 3114 The implementation followed the same structure. |
3099 Problems became visible when | 3115 Problems became visible when |
3100 .Cl "anno -list -number 42 | 3116 .Cl "anno -list -number 42 |
3101 worked on the current message instead on message number 42, | 3117 worked on the current message instead of on message number 42, |
3102 and | 3118 and |
3103 .Cl "anno -list -number l:5 | 3119 .Cl "anno -list -number l:5 |
3104 did not work on the last five messages but failed with the mysterious | 3120 did not work on the last five messages but failed with the mysterious |
3105 error message: ``anno: missing argument to -list''. | 3121 error message: ``anno: missing argument to -list''. |
3106 Yet, the invocation matched the specification in the man page. | 3122 Yet, the invocation matched the specification in the man page. |
3120 .Sw -number | 3136 .Sw -number |
3121 option is also used. | 3137 option is also used. |
3122 .QE | 3138 .QE |
3123 .LP | 3139 .LP |
3124 The problem was manifold. | 3140 The problem was manifold. |
3125 The code required a numeric argument to the | |
3126 .Sw -number | |
3127 switch. | |
3128 If it was missing or non-numeric, | |
3129 .Pn anno | |
3130 aborted with an error message that had an off-by-one error, | |
3131 printing the switch one before the failing one. | |
3132 Semantically, the argument to the | 3141 Semantically, the argument to the |
3133 .Sw -number | 3142 .Sw -number |
3134 switch is only necessary in combination with | 3143 switch is only necessary in combination with |
3135 .Sw -delete , | 3144 .Sw -delete , |
3136 but not with | 3145 but not with |
3137 .Sw -list . | 3146 .Sw -list . |
3138 .P | 3147 The code, however, required a numeric argument in any case. |
3139 Trying to fix these problems on the surface would not have solved | 3148 If the argument was missing or non-numeric, |
3140 them truly, as they originate from a discrepance between the | 3149 .Pn anno |
3150 aborted with an error message that additionally had an off-by-one error. | |
3151 It printed the name of the switch one before the concerned one. | |
3152 .P | |
3153 Trying to fix these problems on the surface would not have solved them. | |
3154 They originate from a discrepance between the | |
3141 structure of the problem and the structure implemented in the program. | 3155 structure of the problem and the structure implemented in the program. |
3142 Such structural differences can not be cured on the surface. | 3156 Such structural differences can only be solved by adjusting the |
3143 They need to be solved by adjusting the structure of the implementation | 3157 structure of the implementation to the structure of the problem. |
3144 to the structure of the problem. | 3158 .P |
3145 .P | 3159 Steinhart had added the new |
3146 In 2002, the new switches | |
3147 .Sw -list | 3160 .Sw -list |
3148 and | 3161 and |
3149 .Sw -delete | 3162 .Sw -delete |
3150 were added in the same way, the | 3163 switches in a style similar to the other switches though |
3151 .Sw -number | 3164 they are of structural different type. |
3152 switch for instance had been added. | |
3153 Yet, they are of structural different type. | |
3154 Semantically, | 3165 Semantically, |
3155 .Sw -list | 3166 .Sw -list |
3156 and | 3167 and |
3157 .Sw -delete | 3168 .Sw -delete |
3158 introduce modes of operation. | 3169 introduce operation modes. |
3159 Historically, | 3170 Historically, |
3160 .Pn anno | 3171 .Pn anno |
3161 had only one operation mode: adding header fields. | 3172 had only one operation mode: adding header fields. |
3162 With the extension it got two more modes: | 3173 With the extension, two more modes were added: |
3163 .\" XXX got | |
3164 listing and deleting header fields. | 3174 listing and deleting header fields. |
3165 The structure of the code changes did not pay respect to this | 3175 The structure of the code changes did not pay respect to this |
3166 fundamental change to | 3176 fundamental change. |
3167 .Pn anno 's | |
3168 behavior. | |
3169 Neither the implementation nor the documentation did clearly | 3177 Neither the implementation nor the documentation did clearly |
3170 define them as being exclusive modes of operation. | 3178 declare the exclusive operation modes as such. |
3171 Having identified the problem, I solved it by putting structure into | 3179 Having identified the problem, I solved it by putting structure into |
3172 .Pn anno | 3180 .Pn anno |
3173 and its documentation. | 3181 and its documentation |
3174 .Ci d54c8db8bdf01e8381890f7729bc0ef4a055ea11 | 3182 .Ci d54c8db8bdf01e8381890f7729bc0ef4a055ea11 . |
3175 .P | 3183 .P |
3176 The difference is visible in both the code and the documentation. | 3184 The difference is visible in both the code and the documentation. |
3177 The following code excerpt: | 3185 For instance in the following code excerpt: |
3178 .VS | 3186 .VS |
3179 int delete = -2; /* delete header element if set */ | 3187 int delete = -2; /* delete header element if set */ |
3180 int list = 0; /* list header elements if set */ | 3188 int list = 0; /* list header elements if set */ |
3181 [...] | 3189 [...] |
3182 case DELETESW: /* delete annotations */ | 3190 case DELETESW: /* delete annotations */ |
3185 case LISTSW: /* produce a listing */ | 3193 case LISTSW: /* produce a listing */ |
3186 list = 1; | 3194 list = 1; |
3187 continue; | 3195 continue; |
3188 VE | 3196 VE |
3189 .LP | 3197 .LP |
3190 was replaced by: | 3198 which was replaced by: |
3191 .VS | 3199 .VS |
3192 static enum { MODE_ADD, MODE_DEL, MODE_LIST } mode = MODE_ADD; | 3200 static enum { MODE_ADD, MODE_DEL, MODE_LIST } mode = MODE_ADD; |
3193 [...] | 3201 [...] |
3194 case DELETESW: /* delete annotations */ | 3202 case DELETESW: /* delete annotations */ |
3195 mode = MODE_DEL; | 3203 mode = MODE_DEL; |
3201 .LP | 3209 .LP |
3202 The replacement code does not only reflect the problem's structure better, | 3210 The replacement code does not only reflect the problem's structure better, |
3203 it is easier to understand as well. | 3211 it is easier to understand as well. |
3204 The same applies to the documentation. | 3212 The same applies to the documentation. |
3205 The man page was completely reorganized to propagate the same structure. | 3213 The man page was completely reorganized to propagate the same structure. |
3206 This is visible in the Synopsis section: | 3214 This is already visible in the Synopsis section: |
3207 .VS | 3215 .VS |
3208 anno [+folder] [msgs] [-component field] [-text body] | 3216 anno [+folder] [msgs] [-component f(CIfieldfP] [-text fPbodyfP] |
3209 [-append] [-date | -nodate] [-preserve | -nopreserve] | 3217 [-append] [-date | -nodate] [-preserve | -nopreserve] |
3210 [-Version] [-help] | 3218 [-Version] [-help] |
3211 | 3219 |
3212 anno -delete [+folder] [msgs] [-component field] [-text | 3220 anno -delete [+folder] [msgs] [-component fPfieldfP] [-text |
3213 body] [-number num | all ] [-preserve | -nopreserve] | 3221 fPbodyfP] [-number fPnum fP| fPall fP] [-preserve | -nopreserve] |
3214 [-Version] [-help] | 3222 [-Version] [-help] |
3215 | 3223 |
3216 anno -list [+folder] [msgs] [-component field] [-number] | 3224 anno -list [+folder] [msgs] [-component fPfieldfP] [-number] |
3217 [-Version] [-help] | 3225 [-Version] [-help] |
3218 VE | 3226 VE |
3219 .\" XXX think about explaining the -preserve rework? | |
3220 | 3227 |
3221 | 3228 |
3222 | 3229 |
3223 .U3 "Path Conversion | 3230 .U3 "Path Conversion |
3224 .P | 3231 .P |
3229 .LI 2 | 3236 .LI 2 |
3230 Relative Unix directory paths, like | 3237 Relative Unix directory paths, like |
3231 .Fn ./foo/bar . | 3238 .Fn ./foo/bar . |
3232 .LI 3 | 3239 .LI 3 |
3233 Absolute MH folder paths, like | 3240 Absolute MH folder paths, like |
3234 .Fn +friends/phil . | 3241 .Fn +projects/mmh . |
3235 .LI 4 | 3242 .LI 4 |
3236 Relative MH folder paths, like | 3243 Relative MH folder paths, like |
3237 .Fn @subfolder . | 3244 .Fn @subfolder . |
3238 .LP | 3245 .LP |
3239 The last type, relative MH folder paths, are hardly documented. | 3246 Relative MH folder paths, are hardly documented |
3240 Nonetheless, they are useful for large mail storages. | 3247 although they are useful for large mail storages. |
3241 The current mail folder is specified as `\c | 3248 The current mail folder is specified as `\c |
3242 .Fn @ ', | 3249 .Fn @ ', |
3243 just like the current directory is specified as `\c | 3250 just like the current directory is specified as `\c |
3244 .Fn . '. | 3251 .Fn . '. |
3245 .P | 3252 .P |
3246 To allow MH tools to understand all four notations, | 3253 To allow MH tools to understand all four notations, |
3247 they need to convert between them. | 3254 they need to be able to convert between them. |
3248 .\" XXX between? | |
3249 In nmh, these path name conversion functions were located in the files | 3255 In nmh, these path name conversion functions were located in the files |
3250 .Fn sbr/path.c | 3256 .Fn sbr/path.c |
3251 (``return a pathname'') and | 3257 (``return a pathname'') and |
3252 .Fn sbr/m_maildir.c | 3258 .Fn sbr/m_maildir.c |
3253 (``get the path for the mail directory''). | 3259 (``get the path for the mail directory''). |
3254 The seven functions in the two files were documented with no more | 3260 The seven functions in the two files were documented with no more |
3255 than two comments, which described obvious information. | 3261 than two comments, which described obvious information. |
3256 The function signatures were neither explaining: | 3262 The signatures of the four exported functions did not explain their |
3257 .VS | 3263 semantics: |
3258 char *path(char *, int); | 3264 .LI 1 |
3259 char *pluspath(char *); | 3265 .CW "char *path(char *, int); |
3260 char *m_mailpath(char *); | 3266 .LI 2 |
3261 char *m_maildir(char *); | 3267 .CW "char *pluspath(char *); |
3262 VE | 3268 .LI 3 |
3263 .P | 3269 .CW "char *m_mailpath(char *); |
3264 My investigation provides the following description: | 3270 .LI 4 |
3271 .CW "char *m_maildir(char *); | |
3272 .P | |
3273 My investigations provided the following descriptions: | |
3265 .LI 1 | 3274 .LI 1 |
3266 The second parameter of | 3275 The second parameter of |
3267 .Fu path() | 3276 .Fu path() |
3268 defines the type of path given as first parameter. | 3277 defines the type as which the path given in the first parameter should |
3278 be treated. | |
3269 Directory paths are converted to absolute directory paths. | 3279 Directory paths are converted to absolute directory paths. |
3270 Folder paths are converted to absolute folder paths. | 3280 Folder paths are converted to absolute folder paths. |
3271 Folder paths must not include a leading `\fL@\fP' character. | 3281 Folder paths must not include a leading `\fL@\fP' character. |
3272 Leading plus characters are preserved. | 3282 Leading plus characters are preserved. |
3273 The result is a pointer to newly allocated memory. | 3283 The result is a pointer to newly allocated memory. |
3282 .Fu m_mailpath() | 3292 .Fu m_mailpath() |
3283 converts directory paths to absolute directory paths. | 3293 converts directory paths to absolute directory paths. |
3284 The characters `\fL+\fP' or `\fL@\fP' at the beginning of the path name are | 3294 The characters `\fL+\fP' or `\fL@\fP' at the beginning of the path name are |
3285 treated literal, i.e. as the first character of a relative directory path. | 3295 treated literal, i.e. as the first character of a relative directory path. |
3286 Hence, this function can not be used for folder paths. | 3296 Hence, this function can not be used for folder paths. |
3287 In any case, the result is an absolute directory path. | 3297 In any case, the result is an absolute directory path, |
3288 The result is a pointer to newly allocated memory. | 3298 returned as a pointer to newly allocated memory. |
3289 .LI 4 | 3299 .LI 4 |
3290 .Fu m_maildir() | 3300 .Fu m_maildir() |
3291 returns the parameter unchanged if it is an absolute directory path | 3301 returns the parameter unchanged if it is an absolute directory path |
3292 or begins with the entry `\fL.\fP' or `\fL..\fP'. | 3302 or begins with the entry `\fL.\fP' or `\fL..\fP'. |
3293 All other strings are prepended with the current working directory. | 3303 All other strings are prepended with the current working directory. |
3294 Hence, this functions can not be used for folder paths. | 3304 Hence, this function can not be used for folder paths. |
3295 The result is either an absolute directory path or a relative | 3305 The result is either an absolute directory path or a relative |
3296 directory path, starting with a dot. | 3306 directory path, starting with dot or dot-dot. |
3297 In contrast to the other functions, the result is a pointer to | 3307 In contrast to the other functions, the result is a pointer to |
3298 static memory. | 3308 static memory. |
3299 .P | 3309 .P |
3300 The situation was obscure, irritating, error-prone, and non-orthogonal. | 3310 The situation was obscure, irritating, error-prone, and non-orthogonal. |
3301 No clear terminology was used to name the different kinds of path names. | 3311 Additionally, no clear terminology was used to name the different |
3302 The first argument of | 3312 kinds of path names. |
3313 Sometimes, the names were even misleading, much as the first argument of | |
3303 .Fu m_mailpath() , | 3314 .Fu m_mailpath() , |
3304 for instance, was named | 3315 which was named |
3305 .Ar folder , | 3316 .CW folder , |
3306 though | 3317 although |
3307 .Fu m_mailpath() | 3318 .Fu m_mailpath() |
3308 can not be used for MH folders. | 3319 could not be used with MH folder arguments. |
3309 .P | 3320 .P |
3310 I reworked the path name conversion completely, introducing clarity. | 3321 I clarified the path name conversion by complete rework. |
3311 First of all, the terminology needed to be defined. | 3322 First of all, the terminology needed to be defined. |
3312 A path name is either in the Unix domain, then it is called | 3323 A path name is either in the Unix domain, then it is called |
3313 \fIdirectory path\fP, `dirpath' for short, or it is in the MH domain, | 3324 \fIdirectory path\fP (\fIdirpath\fP for short) or it is in the MH domain, |
3314 then it is called \fIfolder path\fP, `folpath' for short. | 3325 then it is called \fIfolder path\fP (\fIfolpath\fP for short). |
3315 The two terms need to be used with strict distinction. | 3326 The two terms need to be used with strict distinction. |
3316 Having a clear terminology is often an indicator of having understood | 3327 Often a clear terminology indicates that the problem is understood. |
3317 the problem itself. | |
3318 Second, I exploited the concept of path type indicators. | 3328 Second, I exploited the concept of path type indicators. |
3319 By requesting every path name to start with a clear type identifier, | 3329 By requiring every path name to start with a distinct type identifier, |
3320 conversion between the types can be fully automated. | 3330 the conversion between the types could be fully automated. |
3321 Thus the tools can accept paths of any type from the user. | 3331 This allows the tools to accept paths of any type from the user. |
3322 Therefore, it was necessary to require relative directory paths to be | 3332 Therefore, it was necessary to require relative directory paths to be |
3323 prefixed with a dot character. | 3333 prefixed with a dot character. |
3324 In consequence, the dot character could no longer be an alias for the | 3334 In consequence, the dot character could no longer be an alias for the |
3325 current message. | 3335 current message. |
3326 .Ci cff0e16925e7edbd25b8b9d6d4fbdf03e0e60c01 | 3336 .Ci cff0e16925e7edbd25b8b9d6d4fbdf03e0e60c01 |
3327 Third, I created three new functions to replace the previous mess: | 3337 Third, I created three new functions to replace the previous mess: |
3328 .LI 1 | 3338 .LI 1 |
3329 .Fu expandfol() | 3339 .Fu expandfol() |
3330 converts folder paths to absolute folder paths, | 3340 converts folder paths to absolute folder paths. |
3331 without the leading plus character. | |
3332 Directory paths are simply passed through. | 3341 Directory paths are simply passed through. |
3333 This function is to be used for folder paths only, thus the name. | 3342 This function is to be used for folder paths only, thus the name. |
3334 The result is a pointer to static memory. | 3343 The result is a pointer to static memory. |
3335 .LI 2 | 3344 .LI 2 |
3336 .Fu expanddir() | 3345 .Fu expanddir() |
3351 Two of the functions convert relative to absolute path names of the | 3360 Two of the functions convert relative to absolute path names of the |
3352 same type. | 3361 same type. |
3353 The third function converts any path name type to the most general one, | 3362 The third function converts any path name type to the most general one, |
3354 the absolute directory path. | 3363 the absolute directory path. |
3355 All of the functions return pointers to static memory. | 3364 All of the functions return pointers to static memory. |
3356 All three functions are implemented in | 3365 The file |
3357 .Fn sbr/path.c . | 3366 .Fn sbr/path.c |
3367 contains the implementation of the functions; | |
3358 .Fn sbr/m_maildir.c | 3368 .Fn sbr/m_maildir.c |
3359 is removed. | 3369 was removed. |
3360 .Ci d39e2c447b0d163a5a63f480b23d06edb7a73aa0 | 3370 .Ci d39e2c447b0d163a5a63f480b23d06edb7a73aa0 |
3361 .P | 3371 .P |
3362 Along with the path conversion rework, I also replaced | 3372 Along with the path conversion rework, I also replaced |
3363 .Fu getfolder(FDEF) | 3373 .Fu getfolder(FDEF) |
3364 with | 3374 with |
3365 .Fu getdeffol() | 3375 .Fu getdeffol() |
3366 and | 3376 and |
3367 .Fu getfolder(FCUR) | 3377 .Fu getfolder(FCUR) |
3368 with | 3378 with |
3369 .Fu getcurfol() , | 3379 .Fu getcurfol() , |
3370 which is only a convenience wrapper for | 3380 which only wraps |
3371 .Fu expandfol("@") . | 3381 .Fu expandfol(""@"") |
3382 for convenience. | |
3372 This code was moved from | 3383 This code was moved from |
3373 .Fn sbr/getfolder.c | 3384 .Fn sbr/getfolder.c |
3374 to | 3385 into |
3375 .Fn sbr/path.c . | 3386 .Fn sbr/path.c |
3387 as well. | |
3376 .Ci d39e2c447b0d163a5a63f480b23d06edb7a73aa0 | 3388 .Ci d39e2c447b0d163a5a63f480b23d06edb7a73aa0 |
3377 .P | 3389 .P |
3378 The related function | 3390 The related function |
3379 .Fu etcpath() | 3391 .Fu etcpath() |
3380 was moved to | 3392 is now included in |
3381 .Fn sbr/path.c , | 3393 .Fn sbr/path.c , |
3382 too | 3394 too |
3383 .Ci b4c29794c12099556151d93a860ee51badae2e35 . | 3395 .Ci b4c29794c12099556151d93a860ee51badae2e35 . |
3384 Previously, it had been located in | 3396 Previously, it had been located in |
3385 .Fn config/config.c , | 3397 .Fn config/config.c . |
3386 for whatever reasons. | 3398 .P |
3387 .P | 3399 Now, |
3388 .Fn sbr/path.c | 3400 .Fn sbr/path.c |
3389 now contains all path handling code. | 3401 contains all path handling code. |
3390 .\" XXX naechste zeile weg? | 3402 Besides being less code, its readability is highly improved. |
3391 Only 173 lines of code were needed to replace the previous 252 lines. | 3403 The functions follow a common style and are well documented. |
3392 The readability of the code is highly improved. | |
3393 Additionally, each of the six exported and one static functions | |
3394 is introduced by an explaining comment. | |
3395 | 3404 |
3396 | 3405 |
3397 | 3406 |
3398 | 3407 |
3399 .H2 "Profile Reading | 3408 .H2 "Profile Reading |