1#!/usr/bin/env perl
2
3### START ###
4# Copied from readvaluesfile.pl as a temporary fix due to perl problems (Bug 1259090).
5###
6sub read_values_file {
7
8  my $path = shift;
9  my %h;
10
11  open(F,$path) || die "Can't open values file $path";
12
13  while(<F>){
14
15    chop;
16
17    s/#.*$//g;
18    s/\"//g;
19    s/\r//g;
20
21    next if ! $_;
22
23    @column = split(/,/,$_);
24
25    my $value_name = $column[0];
26
27    my $c_type_str =  $column[1];
28    my $c_autogen = ($c_type_str =~ /\(a\)/);
29
30    my $c_type = $c_type_str;
31    $c_type =~ s/\(.\)//;
32
33    my $python_type =  $column[2];
34    my $components = $column[3];
35    my $enum_values = $column[4];
36
37    my @components;
38    if($components ne "unitary"){
39      @components = split(/;/,$components);
40    } else {
41      @components = ();
42    }
43
44    my @enums;
45    if($enum_values) {
46      @enums  = split(/;/,$enum_values);
47
48    } else {
49      @enums = ();
50    }
51
52    $h{$value_name} = { C => [$c_autogen,$c_type],
53      perl => $perl_type,
54      python => $python_type,
55      components=>[@components],
56      enums=>[@enums]
57    };
58  }
59
60  return %h;
61}
62
63sub read_properties_file {
64
65  my $path = shift;
66  my %h;
67
68  open(F,$path) || die "Can't open properties file $path";
69
70  while(<F>){
71
72    chop;
73
74    s/#.*$//g;
75    s/\"//g;
76    s/\r//g;
77
78    next if ! $_;
79
80    @column = split(/,/,$_);
81
82    my $property_name = $column[0];
83
84    my $lic_value = $column[1];
85    my $default_value = $column[2];
86
87    $h{$property_name} = { lic_value => $lic_value,
88       default_value => $default_value
89    };
90  }
91
92  return %h;
93}
94### END ###
95# End of temporary fix.
96###
97
98use Getopt::Std;
99getopts('chspmi:');
100
101# ARG 0 is properties.csv
102%propmap  = read_properties_file($ARGV[0]);
103
104# ARG 1 is value-types.txt
105%valuemap  = read_values_file($ARGV[1]);
106
107
108$include_vanew = 1;
109
110# Write the file inline by copying everything before a demarcation
111# line, and putting the generated data after the demarcation
112
113if ($opt_i) {
114
115  open(IN,$opt_i) || die "Can't open input file $opt_i";
116
117  while(<IN>){
118
119    if (/<insert_code_here>/){
120      insert_code();
121    } else {
122      print;
123   }
124
125  }
126
127}
128
129sub fudge_data {
130  my $prop = shift;
131
132  my $value = $propmap{$prop}->{'lic_value'};
133
134  if (!$value){
135    die "Can't find value for property \"$prop\"\n";
136  }
137  my $ucf = join("",map {ucfirst(lc($_));}  split(/-/,$prop));
138  my $lc = lc($ucf);
139  my $uc = uc($lc);
140
141  my $ucfvalue = join("",map {ucfirst(lc($_));}  split(/-/,$value));
142  my $lcvalue = lc($ucfvalue);
143  my $ucvalue = uc($lcvalue);
144
145  my $type = $valuemap{$value}->{C}->[1];
146
147  return ($uc,$lc,$lcvalue,$ucvalue,$type);
148
149}
150
151sub insert_code {
152
153# Create the property map data
154if($opt_c){
155
156
157  my @props = sort keys %propmap;
158  my $count = scalar(@props);
159
160
161  print "static const struct icalproperty_map property_map[$count] = {\n";
162
163  foreach $prop (@props) {
164
165    next if !$prop;
166
167    next if $prop eq 'NO';
168
169    my ($uc,$lc,$lcvalue,$ucvalue,$type) = fudge_data($prop);
170
171    print "{ICAL_${uc}_PROPERTY,\"$prop\",ICAL_${ucvalue}_VALUE},\n";
172
173  }
174
175  $prop = "NO";
176
177  my ($uc,$lc,$lcvalue,$ucvalue,$type) = fudge_data($prop);
178
179  print "{ICAL_${uc}_PROPERTY,\"\",ICAL_NO_VALUE}};\n\n";
180
181  $idx = 10000;
182  $count = 1;
183  my $out = "";
184
185  foreach $value (sort keys %valuemap) {
186
187    next if !$value;
188    next if $value eq 'NO' or $prop eq 'ANY';
189
190    my $ucv = join("",map {uc(lc($_));}  split(/-/,$value));
191    my @enums = @{$valuemap{$value}->{'enums'}};
192
193    if(@enums){
194
195      my ($c_autogen,$c_type) = @{$valuemap{$value}->{'C'}};
196
197      unshift(@enums,"X");
198      push(@enums,"NONE");
199
200      foreach $e (@enums) {
201
202	my $uce = join("",map {uc(lc($_));}  split(/-/,$e));
203
204	if($e ne "X" and $e ne "NONE"){
205	  $str = $e;
206	} else {
207	  $str = "";
208	}
209
210	$out.="    {ICAL_${ucv}_PROPERTY,ICAL_${ucv}_${uce},\"$str\" }, /*$idx*/\n";
211
212	$idx++;
213	$count++;
214      }
215
216    }
217  }
218
219  $count++;
220  print "static const struct icalproperty_enum_map enum_map[$count] = {\n";
221  print $out;
222  print "    {ICAL_NO_PROPERTY,0,\"\"}\n};\n\n";
223
224
225
226}
227
228
229if($opt_h){
230
231  # Create the property enumerations list
232  print "typedef enum icalproperty_kind {\n    ICAL_ANY_PROPERTY = 0,\n";
233  foreach $prop (sort keys %propmap) {
234
235    next if !$prop;
236
237    next if $prop eq 'NO' or $prop eq 'ANY';
238
239    my ($uc,$lc,$lcvalue,$ucvalue,$type) = fudge_data($prop);
240
241    print "    ICAL_${uc}_PROPERTY, \n";
242
243  }
244  print "    ICAL_NO_PROPERTY\n} icalproperty_kind;\n\n";
245
246
247}
248
249
250foreach $prop (sort keys %propmap) {
251
252  next if !$prop;
253
254  next if $prop eq 'NO' or $prop eq 'ANY';
255
256  my ($uc,$lc,$lcvalue,$ucvalue,$type) = fudge_data($prop);
257
258
259  my $pointer_check;
260  if ($type =~ /\*/){
261    $pointer_check = "icalerror_check_arg_rz( (v!=0),\"v\");\n" if $type =~ /\*/;
262  } elsif ( $type eq "void" ){
263    $pointer_check = "icalerror_check_arg_rv( (v!=0),\"v\");\n" if $type =~ /\*/;
264
265  }
266
267  my $set_pointer_check = "icalerror_check_arg_rv( (v!=0),\"v\");\n" if $type =~ /\*/;
268
269  if($opt_c) { # Generate C source
270
271   if ($include_vanew) {
272     print<<EOM;
273icalproperty* icalproperty_vanew_${lc}($type v, ...){
274   va_list args;
275   struct icalproperty_impl *impl;
276   $pointer_check
277   impl= icalproperty_new_impl(ICAL_${uc}_PROPERTY);
278   icalproperty_set_${lc}((icalproperty*)impl,v);
279   va_start(args,v);
280   icalproperty_add_parameters(impl, args);
281   va_end(args);
282   return (icalproperty*)impl;
283}
284EOM
285}
286	print<<EOM;
287
288/* $prop */
289icalproperty* icalproperty_new_${lc}($type v) {
290   struct icalproperty_impl *impl;
291   $pointer_check
292   impl = icalproperty_new_impl(ICAL_${uc}_PROPERTY);
293   icalproperty_set_${lc}((icalproperty*)impl,v);
294   return (icalproperty*)impl;
295}
296
297EOM
298    # Allow DTSTART, DTEND, DUE, EXDATE and RECURRENCE-ID to take DATE values.
299    if ($lc eq "dtstart" || $lc eq "dtend" || $lc eq "due" || $lc eq "exdate"
300	|| $lc eq "recurrenceid") {
301	print<<EOM;
302void icalproperty_set_${lc}(icalproperty* prop, $type v){
303    icalvalue *value;
304    $set_pointer_check
305    icalerror_check_arg_rv( (prop!=0),"prop");
306    if (v.is_date)
307        value = icalvalue_new_date(v);
308    else
309        value = icalvalue_new_datetime(v);
310    icalproperty_set_value(prop,value);
311}
312EOM
313    } else {
314
315	print<<EOM;
316void icalproperty_set_${lc}(icalproperty* prop, $type v){
317    $set_pointer_check
318    icalerror_check_arg_rv( (prop!=0),"prop");
319    icalproperty_set_value(prop,icalvalue_new_${lcvalue}(v));
320}
321EOM
322	}
323# Dirk Theisen pointed out, exdate needs to match TZID parameters in EXDATE
324    if ($lc eq "exdate") {
325	print<<EOM;
326$type icalproperty_get_${lc}(const icalproperty* prop){
327	icalerror_check_arg( (prop!=0),"prop");
328#ifndef _MSC_VER
329        /*
330	 * Code by dirk\@objectpark.net:
331	 * Set the time zone manually. I am really puzzled that
332	 * it doesnot work automatically like in the other functions
333	 * like icalproperty_get_dtstart().
334	 */
335	struct icaltimetype itt =
336		icalvalue_get_datetime(icalproperty_get_value(prop));
337	icalparameter* param = icalproperty_get_first_parameter(prop,
338								ICAL_TZID_PARAMETER);
339	if (param) {
340	        const icaltimezone *zone =
341		        icaltimezone_get_builtin_timezone(icalparameter_get_tzid(param));
342		icaltime_set_timezone(&itt, zone);
343        }
344	return itt;
345#else
346    return icalvalue_get_datetime(icalproperty_get_value(prop));
347#endif
348}
349EOM
350    } else {
351	print<<EOM;
352$type icalproperty_get_${lc}(const icalproperty* prop){
353    icalerror_check_arg( (prop!=0),"prop");
354    return icalvalue_get_${lcvalue}(icalproperty_get_value(prop));
355}
356EOM
357    }
358  } elsif ($opt_h) { # Generate C Header file
359
360
361 print "\
362/* $prop */\
363icalproperty* icalproperty_new_${lc}($type v);\
364void icalproperty_set_${lc}(icalproperty* prop, $type v);\
365$type icalproperty_get_${lc}(const icalproperty* prop);";
366
367
368if ($include_vanew){
369  print "icalproperty* icalproperty_vanew_${lc}($type v, ...);\n";
370}
371
372}
373
374
375} # This brace terminates the main loop
376
377
378
379if ($opt_h){
380
381print "\n\n#endif /*ICALPROPERTY_H*/\n"
382}
383
384}
385