You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/libkcal/libical/vzic-1.3/vzic-dump.c

410 lines
10 KiB

/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* These functions are for dumping all the parsed Zones and Rules to
* files, to be compared with the output of vzic-dump.pl to check our parsing
* code is OK. Some of the functions are also used for producing debugging
* output.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vzic.h"
#include "vzic-dump.h"
static void dump_add_rule (char *name,
GArray *rule_array,
GPtrArray *name_array);
static int dump_compare_strings (const void *arg1,
const void *arg2);
void
dump_zone_data (GArray *zone_data,
char *filename)
{
static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
FILE *fp;
ZoneData *zone;
ZoneLineData *zone_line;
int i, j;
gboolean output_month, output_day, output_time;
fp = fopen (filename, "w");
if (!fp) {
fprintf (stderr, "Couldn't create file: %s\n", filename);
exit (1);
}
for (i = 0; i < zone_data->len; i++) {
zone = &g_array_index (zone_data, ZoneData, i);
fprintf (fp, "Zone\t%s\t", zone->zone_name);
for (j = 0; j < zone->zone_line_data->len; j++) {
zone_line = &g_array_index (zone->zone_line_data, ZoneLineData, j);
if (j != 0)
fprintf (fp, "\t\t\t");
fprintf (fp, "%s\t", dump_time (zone_line->stdoff_seconds, TIME_WALL,
FALSE));
if (zone_line->rules)
fprintf (fp, "%s\t", zone_line->rules);
else if (zone_line->save_seconds != 0)
fprintf (fp, "%s\t", dump_time (zone_line->save_seconds, TIME_WALL,
FALSE));
else
fprintf (fp, "-\t");
fprintf (fp, "%s\t", zone_line->format ? zone_line->format : "-");
if (zone_line->until_set) {
fprintf (fp, "%s\t", dump_year (zone_line->until_year));
output_month = output_day = output_time = FALSE;
if (zone_line->until_time_code != TIME_WALL
|| zone_line->until_time_seconds != 0)
output_month = output_day = output_time = TRUE;
else if (zone_line->until_day_code != DAY_SIMPLE
|| zone_line->until_day_number != 1)
output_month = output_day = TRUE;
else if (zone_line->until_month != 0)
output_month = TRUE;
if (output_month)
fprintf (fp, "%s", months[zone_line->until_month]);
fprintf (fp, "\t");
if (output_day)
fprintf (fp, "%s", dump_day_coded (zone_line->until_day_code,
zone_line->until_day_number,
zone_line->until_day_weekday));
fprintf (fp, "\t");
if (output_time)
fprintf (fp, "%s", dump_time (zone_line->until_time_seconds,
zone_line->until_time_code, FALSE));
} else {
fprintf (fp, "\t\t\t");
}
fprintf (fp, "\n");
}
}
fclose (fp);
}
void
dump_rule_data (GHashTable *rule_data,
char *filename)
{
FILE *fp;
GPtrArray *name_array;
GArray *rule_array;
int i;
char *name;
fp = fopen (filename, "w");
if (!fp) {
fprintf (stderr, "Couldn't create file: %s\n", filename);
exit (1);
}
/* We need to sort the rules by their names, so they are in the same order
as the Perl output. So we place all the names in a temporary GPtrArray,
sort it, then output them. */
name_array = g_ptr_array_new ();
g_hash_table_foreach (rule_data, (GHFunc) dump_add_rule, name_array);
qsort (name_array->pdata, name_array->len, sizeof (char*),
dump_compare_strings);
for (i = 0; i < name_array->len; i++) {
name = g_ptr_array_index (name_array, i);
rule_array = g_hash_table_lookup (rule_data, name);
if (!rule_array) {
fprintf (stderr, "Couldn't access rules: %s\n", name);
exit (1);
}
dump_rule_array (name, rule_array, fp);
}
g_ptr_array_free (name_array, TRUE);
fclose (fp);
}
static void
dump_add_rule (char *name,
GArray *rule_array,
GPtrArray *name_array)
{
g_ptr_array_add (name_array, name);
}
static int
dump_compare_strings (const void *arg1,
const void *arg2)
{
char **a, **b;
a = (char**) arg1;
b = (char**) arg2;
return strcmp (*a, *b);
}
void
dump_rule_array (char *name,
GArray *rule_array,
FILE *fp)
{
static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
RuleData *rule;
int i;
#if 0
fprintf (fp, "\n# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S");
#endif
for (i = 0; i < rule_array->len; i++) {
rule = &g_array_index (rule_array, RuleData, i);
fprintf (fp, "Rule\t%s\t%s\t", name, dump_year (rule->from_year));
if (rule->to_year == rule->from_year)
fprintf (fp, "only\t");
else
fprintf (fp, "%s\t", dump_year (rule->to_year));
fprintf (fp, "%s\t", rule->type ? rule->type : "-");
fprintf (fp, "%s\t", months[rule->in_month]);
fprintf (fp, "%s\t",
dump_day_coded (rule->on_day_code, rule->on_day_number,
rule->on_day_weekday));
fprintf (fp, "%s\t", dump_time (rule->at_time_seconds, rule->at_time_code,
FALSE));
fprintf (fp, "%s\t", dump_time (rule->save_seconds, TIME_WALL, TRUE));
fprintf (fp, "%s", rule->letter_s ? rule->letter_s : "-");
fprintf (fp, "\n");
}
}
char*
dump_time (int seconds,
TimeCode time_code,
gboolean use_zero)
{
static char buffer[256], *sign;
int hours, minutes;
char *code;
if (time_code == TIME_STANDARD)
code = "s";
else if (time_code == TIME_UNIVERSAL)
code = "u";
else
code = "";
if (seconds < 0) {
seconds = -seconds;
sign = "-";
} else {
sign = "";
}
hours = seconds / 3600;
minutes = (seconds % 3600) / 60;
seconds = seconds % 60;
if (use_zero && hours == 0 && minutes == 0 && seconds == 0)
return "0";
else if (seconds == 0)
sprintf (buffer, "%s%i:%02i%s", sign, hours, minutes, code);
else
sprintf (buffer, "%s%i:%02i:%02i%s", sign, hours, minutes, seconds, code);
return buffer;
}
char*
dump_day_coded (DayCode day_code,
int day_number,
int day_weekday)
{
static char buffer[256];
static char *weekdays[] = { "Sun", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat" };
switch (day_code) {
case DAY_SIMPLE:
sprintf (buffer, "%i", day_number);
break;
case DAY_WEEKDAY_ON_OR_AFTER:
sprintf (buffer, "%s>=%i", weekdays[day_weekday], day_number);
break;
case DAY_WEEKDAY_ON_OR_BEFORE:
sprintf (buffer, "%s<=%i", weekdays[day_weekday], day_number);
break;
case DAY_LAST_WEEKDAY:
sprintf (buffer, "last%s", weekdays[day_weekday]);
break;
default:
fprintf (stderr, "Invalid day code: %i\n", day_code);
exit (1);
}
return buffer;
}
char*
dump_year (int year)
{
static char buffer[256];
if (year == YEAR_MINIMUM)
return "min";
if (year == YEAR_MAXIMUM)
return "max";
sprintf (buffer, "%i", year);
return buffer;
}
void
dump_time_zone_names (GList *names,
char *output_dir,
GHashTable *zones_hash)
{
char filename[PATHNAME_BUFFER_SIZE], *zone_name, *zone_name_in_hash = NULL;
char strings_filename[PATHNAME_BUFFER_SIZE];
FILE *fp, *strings_fp = NULL;
GList *elem;
ZoneDescription *zone_desc;
sprintf (filename, "%s/zones.tab", output_dir);
sprintf (strings_filename, "%s/zones.h", output_dir);
fp = fopen (filename, "w");
if (!fp) {
fprintf (stderr, "Couldn't create file: %s\n", filename);
exit (1);
}
if (VzicDumpZoneTranslatableStrings) {
strings_fp = fopen (strings_filename, "w");
if (!strings_fp) {
fprintf (stderr, "Couldn't create file: %s\n", strings_filename);
exit (1);
}
}
names = g_list_sort (names, (GCompareFunc) strcmp);
elem = names;
while (elem) {
zone_name = (char*) elem->data;
zone_desc = g_hash_table_lookup (zones_hash, zone_name);
/* SPECIAL CASES: These timezones are links from other zones and are
almost exactly the same - they are basically there so users can find
them a bit easier. But they don't have entries in the zone.tab file,
so we use the entry from the timezone linked from. */
if (!zone_desc) {
if (!strcmp (zone_name, "America/Indiana/Indianapolis"))
zone_name_in_hash = "America/Indianapolis";
else if (!strcmp (zone_name, "America/Kentucky/Louisville"))
zone_name_in_hash = "America/Louisville";
else if (!strcmp (zone_name, "Asia/Istanbul"))
zone_name_in_hash = "Europe/Istanbul";
else if (!strcmp (zone_name, "Europe/Nicosia"))
zone_name_in_hash = "Asia/Nicosia";
if (zone_name_in_hash)
zone_desc = g_hash_table_lookup (zones_hash, zone_name_in_hash);
}
if (zone_desc) {
fprintf (fp, "%+04i%02i%02i %+04i%02i%02i %s\n",
zone_desc->latitude[0], zone_desc->latitude[1],
zone_desc->latitude[2],
zone_desc->longitude[0], zone_desc->longitude[1],
zone_desc->longitude[2],
zone_name);
} else {
g_print ("Zone description not found for: %s\n", zone_name);
fprintf (fp, "%s\n", zone_name);
}
if (VzicDumpZoneTranslatableStrings) {
#if 0
char zone_name_buffer[1024], *src, *dest;
for (src = zone_name, dest = zone_name_buffer; *src; src++, dest++)
*dest = (*src == '_') ? ' ' : *src;
*dest = '\0';
#endif
fprintf (strings_fp, "N_(\"%s\");\n", zone_name);
}
elem = elem->next;
}
fclose (fp);
if (VzicDumpZoneTranslatableStrings)
fclose (strings_fp);
}