diff options
Diffstat (limited to 'libkcal/libical/vzic-1.3/vzic.c')
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/libkcal/libical/vzic-1.3/vzic.c b/libkcal/libical/vzic-1.3/vzic.c new file mode 100644 index 000000000..1108d8777 --- /dev/null +++ b/libkcal/libical/vzic-1.3/vzic.c @@ -0,0 +1,320 @@ +/* + * Vzic - a program to convert Olson timezone database files into VZTIMEZONE + * files compatible with the iCalendar specification (RFC2445). + * + * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2003 Damon Chaplin. + * + * Author: Damon Chaplin <damon@gnome.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <string.h> + +#include "vzic.h" +#include "vzic-parse.h" +#include "vzic-dump.h" +#include "vzic-output.h" + + +/* + * Global command-line options. + */ + +/* By default we output Outlook-compatible output. If --pure is used we + output pure output, with no changes to be compatible with Outlook. */ +gboolean VzicPureOutput = FALSE; + +gboolean VzicDumpOutput = FALSE; +gboolean VzicDumpChanges = FALSE; +gboolean VzicDumpZoneNamesAndCoords = TRUE; +gboolean VzicDumpZoneTranslatableStrings= TRUE; +gboolean VzicNoRRules = FALSE; +gboolean VzicNoRDates = FALSE; +char* VzicOutputDir = "zoneinfo"; +char* VzicUrlPrefix = NULL; +char* VzicOlsonDir = OLSON_DIR; + +GList* VzicTimeZoneNames = NULL; + +static void convert_olson_file (char *olson_file); + +static void usage (void); + +static void free_zone_data (GArray *zone_data); +static void free_rule_array (gpointer key, + gpointer value, + gpointer data); +static void free_link_data (gpointer key, + gpointer value, + gpointer data); + + +int +main (int argc, + char *argv[]) +{ + int i; + char directory[PATHNAME_BUFFER_SIZE]; + char filename[PATHNAME_BUFFER_SIZE]; + GHashTable *zones_hash; + + /* + * Command-Line Option Parsing. + */ + for (i = 1; i < argc; i++) { + /* + * User Options. + */ + + /* --pure: Output the perfect VCALENDAR data, which Outlook won't parse + as it has problems with certain iCalendar constructs. */ + if (!strcmp (argv[i], "--pure")) + VzicPureOutput = TRUE; + + /* --output-dir: specify where to output all the files beneath. The + default is the current directory. */ + else if (argc > i + 1 && !strcmp (argv[i], "--output-dir")) + VzicOutputDir = argv[++i]; + + /* --url-prefix: Used as the base for the TZURL property in each + VTIMEZONE. The default is to not output TZURL properties. */ + else if (argc > i + 1 && !strcmp (argv[i], "--url-prefix")) { + int length; + VzicUrlPrefix = argv[++i]; + /* remove the trailing '/' if there is one */ + length = strlen (VzicUrlPrefix); + if (VzicUrlPrefix[length - 1] == '/') + VzicUrlPrefix[length - 1] = '\0'; + } + + else if (argc > i + 1 && !strcmp (argv[i], "--olson-dir")) { + VzicOlsonDir = argv[++i]; + } + + /* + * Debugging Options. + */ + + /* --dump: Dump the Rule and Zone data that we parsed from the Olson + timezone files. This is used to test the parsing code. */ + else if (!strcmp (argv[i], "--dump")) + VzicDumpOutput = TRUE; + + /* --dump-changes: Dumps a list of times when each timezone changed, + and the new local time offset from UTC. */ + else if (!strcmp (argv[i], "--dump-changes")) + VzicDumpChanges = TRUE; + + /* --no-rrules: Don't output RRULE properties in the VTIMEZONEs. Instead + it will just output RDATEs for each year up to a certain year. */ + else if (!strcmp (argv[i], "--no-rrules")) + VzicNoRRules = TRUE; + + /* --no-rdates: Don't output multiple RDATEs in a single VTIMEZONE + component. Instead they will be output separately. */ + else if (!strcmp (argv[i], "--no-rdates")) + VzicNoRDates = TRUE; + + else + usage (); + } + + /* + * Create any necessary directories. + */ + ensure_directory_exists (VzicOutputDir); + + if (VzicDumpOutput) { + /* Create the directories for the dump output, if they don't exist. */ + sprintf (directory, "%s/ZonesVzic", VzicOutputDir); + ensure_directory_exists (directory); + sprintf (directory, "%s/RulesVzic", VzicOutputDir); + ensure_directory_exists (directory); + } + + if (VzicDumpChanges) { + /* Create the directory for the changes output, if it doesn't exist. */ + sprintf (directory, "%s/ChangesVzic", VzicOutputDir); + ensure_directory_exists (directory); + } + + /* + * Convert the Olson timezone files. + */ + convert_olson_file ("africa"); + convert_olson_file ("antarctica"); + convert_olson_file ("asia"); + convert_olson_file ("australasia"); + convert_olson_file ("europe"); + convert_olson_file ("northamerica"); + convert_olson_file ("southamerica"); + + /* These are backwards-compatability and weird stuff. */ +#if 0 + convert_olson_file ("backward"); + convert_olson_file ("etcetera"); + convert_olson_file ("leapseconds"); + convert_olson_file ("pacificnew"); + convert_olson_file ("solar87"); + convert_olson_file ("solar88"); + convert_olson_file ("solar89"); +#endif + + /* This doesn't really do anything and it messes up vzic-dump.pl so we + don't bother. */ +#if 0 + convert_olson_file ("factory"); +#endif + + /* This is old System V stuff, which we don't currently support since it + uses 'min' as a Rule FROM value which messes up our algorithm, making + it too slow and use too much memory. */ +#if 0 + convert_olson_file ("systemv"); +#endif + + /* Output the timezone names and coordinates in a zone.tab file, and + the translatable strings to feed to gettext. */ + if (VzicDumpZoneNamesAndCoords) { + sprintf (filename, "%s/zone.tab", VzicOlsonDir); + zones_hash = parse_zone_tab (filename); + + dump_time_zone_names (VzicTimeZoneNames, VzicOutputDir, zones_hash); + } + + return 0; +} + + +static void +convert_olson_file (char *olson_file) +{ + char input_filename[PATHNAME_BUFFER_SIZE]; + GArray *zone_data; + GHashTable *rule_data, *link_data; + char dump_filename[PATHNAME_BUFFER_SIZE]; + ZoneData *zone; + int i, max_until_year; + + sprintf (input_filename, "%s/%s", VzicOlsonDir, olson_file); + + parse_olson_file (input_filename, &zone_data, &rule_data, &link_data, + &max_until_year); + + if (VzicDumpOutput) { + sprintf (dump_filename, "%s/ZonesVzic/%s", VzicOutputDir, olson_file); + dump_zone_data (zone_data, dump_filename); + + sprintf (dump_filename, "%s/RulesVzic/%s", VzicOutputDir, olson_file); + dump_rule_data (rule_data, dump_filename); + } + + output_vtimezone_files (VzicOutputDir, zone_data, rule_data, link_data, + max_until_year); + + free_zone_data (zone_data); + g_hash_table_foreach (rule_data, free_rule_array, NULL); + g_hash_table_destroy (rule_data); + g_hash_table_foreach (link_data, free_link_data, NULL); + g_hash_table_destroy (link_data); +} + + +static void +usage (void) +{ + fprintf (stderr, "Usage: vzic [--dump] [--dump-changes] [--no-rrules] [--no-rdates] [--pure] [--output-dir <directory>] [--url-prefix <url>] [--olson-dir <directory>]\n"); + + exit (1); +} + + + + +/* + * Functions to free the data structures. + */ + +static void +free_zone_data (GArray *zone_data) +{ + ZoneData *zone; + ZoneLineData *zone_line; + int i, j; + + for (i = 0; i < zone_data->len; i++) { + zone = &g_array_index (zone_data, ZoneData, i); + + g_free (zone->zone_name); + + for (j = 0; j < zone->zone_line_data->len; j++) { + zone_line = &g_array_index (zone->zone_line_data, ZoneLineData, j); + + g_free (zone_line->rules); + g_free (zone_line->format); + } + + g_array_free (zone->zone_line_data, TRUE); + } + + g_array_free (zone_data, TRUE); +} + + +static void +free_rule_array (gpointer key, + gpointer value, + gpointer data) +{ + char *name = key; + GArray *rule_array = value; + RuleData *rule; + int i; + + for (i = 0; i < rule_array->len; i++) { + rule = &g_array_index (rule_array, RuleData, i); + + if (!rule->is_shallow_copy) { + g_free (rule->type); + g_free (rule->letter_s); + } + } + + g_array_free (rule_array, TRUE); + + g_free (name); +} + + +static void +free_link_data (gpointer key, + gpointer value, + gpointer data) +{ + GList *link = data; + + g_free (key); + + while (link) { + g_free (link->data); + link = link->next; + } + + g_list_free (data); +} + |