Imported Upstream version 3.3.3
[debian/amanda] / perl / amglue / constants.swg
1 /*
2  * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17  *
18  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
20  */
21
22 /*
23  * This file contains SWIG macros to handle C constants, enums, and flags
24  */
25
26 %include "amglue/exports.swg"
27
28 /*
29  * Internal support for iterating over lists of symbols; users will define
30  * the list as e.g.,
31  *
32  *   #define FOR_ALL_WHATEVER(APPLY) APPLY(SYMBOL1) APPLY(SYMBOL2) ..
33  *
34  * and then passes FOR_ALL_WHATEVER as the FORALL_FN argument to one of the
35  * macros below.  This uses the "X Macro" trick; see
36  * http://www.drdobbs.com/blog/archives/2010/06/the_x_macro.html
37  *
38  * NOTE: SWIG's %define macros add C-style comments when they are expanded, so
39  * this method must use #define, not %define.  Also note that this always expands
40  * to a single line, making the result very ugly.
41  */
42
43 #define _amglue_apply_null(V) V
44 #define _amglue_apply_leading_scalar(V) $V
45 #define _amglue_apply_trailing_comma(V) V,
46 #define _amglue_apply_C_scalar(V) C<$V>
47 #define _amglue_forall_join_whitespace(FORALL_FN) FORALL_FN(_amglue_apply_null)
48 #define _amglue_forall_scalars(FORALL_FN) FORALL_FN(_amglue_apply_leading_scalar)
49 #define _amglue_forall_terminated_by_comma(FORALL_FN) FORALL_FN(_amglue_apply_trailing_comma)
50
51 /* Rather than try to use glib's flag/enum architecture, which is only used
52  * for a few constants (mostly in property.h), .swg files define constants using
53  * these macros.  A typical definition would look like:
54  *   amglue_add_flag_tag_fns(Permissions);
55  *   amglue_add_constant(PERM_READ, Permissions);
56  *   amglue_add_constant(PERM_WRITE, Permissions);
57  * note that the values of the constants do not appear here, although the header
58  * file in which they are defined must be included in the %{ .. %} block.
59  *
60  * The above would result in:
61  *  - typedef int Permissions;
62  *  - $PERM_READ and $PERM_WRITE in @EXPORT_OK
63  *  - $PERM_READ and $PERM_WRITE in %EXPORT_TAGS{'Permissions'}
64  *  - Permissions_to_strings($flags) -> ( name, name, .. )
65  *
66  * Similarly, amglue_add_enum_tag_fns(FileType) would add the same
67  * EXPORTs, but a function
68  *  - FileType_to_string($enum) -> name
69  */
70
71 %define amglue_add_flag_tag_fns(TAG)
72 typedef int TAG;
73 amglue_export_tag(TAG, TAG ## _to_strings);
74 %perlcode %{
75 my %_ ## TAG ## _VALUES;
76 # Convert a flag value to a list of names for flags that are set.
77 sub TAG ## _to_strings {
78     my ($flags) = @_;
79     my @result = ();
80
81     for my $k (keys %_ ## TAG ## _VALUES) {
82         my $v = $_ ## TAG ## _VALUES{$k};
83
84         # is this a matching flag?
85         if (($v == 0 && $flags == 0) || ($v != 0 && ($flags & $v) == $v)) {
86             push @result, $k;
87         }
88     }
89
90     # by default, just return the number as a 1-element list
91     if (!@result) {
92         return ($flags);
93     }
94
95     return @result;
96 }
97 %}
98 %enddef
99
100 %define amglue_add_enum_tag_fns(TAG)
101 typedef int TAG;
102 amglue_export_tag(TAG, TAG ## _to_string);
103 %perlcode %{
104 my %_ ## TAG ## _VALUES;
105 # Convert an enum value to a single string
106 sub TAG ## _to_string {
107     my ($enumval) = @_;
108
109     for my $k (keys %_ ## TAG ## _VALUES) {
110         my $v = $_ ## TAG ## _VALUES{$k};
111
112         # is this a matching flag?
113         if ($enumval == $v) {
114             return $k;
115         }
116     }
117
118     # default, just return the number
119     return $enumval;
120 }
121 %}
122 %enddef
123
124 /* Add the given constant, assuming the constant name is the 
125  * short name
126  *
127  * @param CONSTNAME: the name of the constant, as used in C code
128  * @param TAG: the tag for this constant (enum name, etc.)
129  */
130 %define amglue_add_constant(CONSTNAME, TAG)
131 enum { CONSTNAME }; /* pass the constant to SWIG */
132 amglue_export_tag(TAG, $CONSTNAME);
133 %perlcode %{
134 $_ ## TAG ## _VALUES{`CONSTNAME`} = $CONSTNAME;
135 %}
136 %enddef
137
138 /* Add a bunch of constants all at once; this is more efficient with
139  * a large list of constants
140  *
141  * @param FORALL_FN: the FORALL_FN listing all of the constants (see above)
142  * @param TAG: the tag for these constants
143  */
144 #define amglue_add_constants(FORALL_FN, TAG) \
145 enum { _amglue_forall_terminated_by_comma(FORALL_FN) }; \
146 amglue_export_tag(TAG, _amglue_forall_scalars(FORALL_FN)) \
147 %perlcode %{ \
148     foreach (qw( _amglue_forall_join_whitespace(FORALL_FN))) { \
149         $_ ## TAG ## _VALUES{$_} = $$_; \
150     } \
151 %}
152
153 /* Add the given constant with a short name
154  *
155  * @param CONSTNAME: the name of the constant, as used in C code
156  * @param SHORTNAME: the name to be shown by TAG_to_string(s) (a string)
157  * @param TAG: the tag for this constant (enum name, etc.)
158  */
159 %define amglue_add_constant_short(CONSTNAME, SHORTNAME, TAG)
160 enum { CONSTNAME }; /* pass the constant to SWIG */
161 amglue_export_tag(TAG, $CONSTNAME);
162 %perlcode %{
163 $_ ## TAG ## _VALUES{`SHORTNAME`} = $CONSTNAME;
164 %}
165 %enddef
166
167 /* Add the given constant.  No shortname is supplied, so the constant
168  * will not be used for conversion to strings.  Use this function for
169  * bit combinations and other metadata, e.g., FOO_MASK or FOO_MAX
170  *
171  * @param CONSTNAME: the name of the constant, as used in C code
172  * @param TAG: the tag for this constant (enum name, etc.)
173  */
174 %define amglue_add_constant_noshort(CONSTNAME, TAG)
175 enum { CONSTNAME }; /* pass the constant to SWIG */
176 amglue_export_tag(TAG, $CONSTNAME);
177 %enddef
178
179 /* Return the symbols alone, separated by whitespace.  Note that this will
180  * being with whitespace, too.  Be careful if using it in POD.
181  *
182  * @param FORALL_FN: the forall function to use (see above)
183  */
184 #define amglue_constants_list(FORALL_FN) \
185     FORALL_FN(_amglue_apply_C_scalar)
186