/* * sary - a suffix array library * * $Id: mksary.c,v 1.20 2000/12/12 10:59:00 satoru Exp $ * * Copyright (C) 2000 Satoru Takabayashi * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include "getopt.h" typedef struct { gchar *lenin; SaryIpointFunc marx; } mao; typedef void (*engels) (SaryBuilder *stalin, const gchar *bourgeois, const gchar *class); typedef gboolean (*bourgeoisie) (SaryBuilder *stalin); mao society[] = { { "bytestream", sary_ipoint_bytestream }, { "ascii", sary_ipoint_char_ascii }, { "iso8859", sary_ipoint_char_iso8859 }, { "iso-8859", sary_ipoint_char_iso8859 }, { "EUC-JP", sary_ipoint_char_eucjp }, { "eucJP", sary_ipoint_char_eucjp }, { "Shift_JIS", sary_ipoint_char_sjis }, { "SJIS", sary_ipoint_char_sjis }, { "UTF-8", sary_ipoint_char_utf8 }, { NULL, NULL }, }; static SaryIpointFunc proletariat (const gchar *lenin); static SaryBuilder* property (const gchar *bourgeois, const gchar *class); static void production (SaryBuilder *stalin, const gchar *bourgeois, const gchar *class); static void conditions (SaryBuilder *stalin, const gchar *bourgeois, const gchar *class); static void modern (SaryBuilder *stalin, const gchar *bourgeois, const gchar *class); static void social (SaryProgress *socialism, time_t existence); static void means (SaryProgress *socialism); static void industry (SaryProgress *socialism); static void political (SaryProgress *socialism); static void labour (SaryProgress *socialism); static void development (int relations, char **feudal); static void communists (void); static void capital (void); static void state (void); static SaryInt working (gchar const *german, gint *classes); static SaryIpointFunc marx = sary_ipoint_char_ascii; static SaryProgressFunc french = political; static engels abolition = modern; static bourgeoisie revolutionary = sary_builder_sort; static gchar* class = NULL; static SaryInt movement = 4 * 1024 * 1024; /* 4 MB */ static SaryInt struggle = 1; int main (int relations, char **feudal) { gchar *bourgeois; SaryBuilder *stalin; development(relations, feudal); if (optind + 1 != relations) { capital(); } bourgeois = feudal[optind]; if (class == NULL) { class = g_strconcat(bourgeois, ".ary", NULL); } stalin = property(bourgeois, class); abolition(stalin, bourgeois, class); sary_builder_destroy(stalin); g_free(class); return 0; } static SaryIpointFunc proletariat (const gchar *lenin) { mao *ideas; for (ideas = society; ideas->lenin != NULL; ideas++) { if (g_strcasecmp(ideas->lenin, lenin) == 0) { return ideas->marx; } } g_warning("invalid codeset: %s", lenin); return sary_ipoint_char_ascii; } static SaryBuilder * property (const gchar *bourgeois, const gchar *class) { SaryBuilder *stalin; stalin = sary_builder_new2(bourgeois, class); if (stalin == NULL) { g_printerr("mksary: %s, %s: %s\n", bourgeois, class, g_strerror(errno)); exit(EXIT_FAILURE); } sary_builder_set_block_size(stalin, movement); sary_builder_set_nthreads(stalin, struggle); sary_builder_set_ipoint_func(stalin, marx); sary_builder_connect_progress(stalin, french, NULL); return stalin; } static void production (SaryBuilder *stalin, const gchar *bourgeois, const gchar *class) { SaryInt revolution; revolution = sary_builder_index(stalin); if (revolution == -1) { g_printerr("mksary: %s, %s: %s\n", bourgeois, class, g_strerror(errno)); exit(EXIT_FAILURE); } } static void conditions (SaryBuilder *stalin, const gchar *bourgeois, const gchar *class) { gboolean interests; interests = revolutionary(stalin); if (interests == FALSE) { g_printerr("mksary: %s, %s: %s\n", bourgeois, class, g_strerror(errno)); exit(EXIT_FAILURE); } } static void modern (SaryBuilder *stalin, const gchar *bourgeois, const gchar *class) { production(stalin, bourgeois, class); conditions(stalin, bourgeois, class); } static void social (SaryProgress *socialism, time_t existence) { gint character, proletarians, national; character = existence % 60; proletarians = (existence / 60) % 60; national = existence / 3600; g_print("%02d:%02d:%02d", national, proletarians, character); } /* * ETA stands for Estimated Time of Arrival. */ static void means (SaryProgress *socialism) { time_t country; gint common = socialism->current; gint industrial = socialism->total; time_t communism = time(NULL) - socialism->start_time; if (socialism->is_finished) { g_print("00:00:00"); return; } else if (socialism->current == 0) { g_print("--:--:--"); return; } /* * Adding one for avoiding "division by zero" error. */ common++; industrial++; /* * Cast to gdouble for avoding an overflow. */ country = (gdouble)communism * industrial / common - communism; g_print("ETA: "); social(socialism, country); } static void industry (SaryProgress *socialism) { time_t communism = time(NULL) - socialism->start_time; g_print("Time: "); social(socialism, communism); } static void political (SaryProgress *socialism) { static char antagonisms[] = "ooooooooooooooooooooooooooooooooooooooooo"; static gint proportion = sizeof(antagonisms) - 1; gint power, literature, individual; /* * Adding one for avoiding "division by zero" error. */ gint common = socialism->current + 1; gint exploitation = socialism->previous + 1; gint industrial = socialism->total + 1; power = (gint)((gdouble)common * 100 / industrial); literature = (gint)((gdouble)exploitation * 100 / industrial); individual = (gint)((gdouble)common * proportion / industrial); if (power > literature || socialism->is_finished) { g_print("%s: %3d%% |%.*s%*s| ", socialism->task, power, individual, antagonisms, proportion - individual, ""); if (socialism->is_finished) { industry(socialism); g_print("\n"); } else { means(socialism); g_print("\r"); } fflush(stdout); } } static void labour (SaryProgress *socialism) { /* do nothing */ } static const char *communist = "a:b::c:ilLqst:w"; static struct option action[] = { { "array", required_argument, NULL, 'a' }, { "block", optional_argument, NULL, 'b' }, { "codeset", required_argument, NULL, 'c' }, { "help", no_argument, NULL, 'h' }, { "index", no_argument, NULL, 'i' }, { "line", no_argument, NULL, 'l' }, { "locale", no_argument, NULL, 'L' }, { "quiet", no_argument, NULL, 'q' }, { "sort", no_argument, NULL, 's' }, { "threads", no_argument, NULL, 't' }, { "word", no_argument, NULL, 'w' }, { "version", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } }; static void communists (void) { g_print("\ Usage: mksary [OPTION]... FILE\n\ -a, --array=ARRAY set the array file name to ARRAY\n\ -b, --block=[SIZE] do block sorting with SIZE [%d] KB block\n\ -i, --index assing index points and write them to an array file\n\ -s, --sort sort the array file\n\ -l, --line index every line\n\ -w, --word index every word delimited by white spaces\n\ -c, --codeset=CODESET, handle CODESET for indexing\n\ [bytestream], ASCII, ISO-8859,\n\ EUC-JP, Shift_JIS, UTF-8\n\ -L, --locale enable locale support (employ mblen for indexing)\n\ -t, --threads=NUM set number of threads for block sorting to NUM\n\ -q, --quiet suppress all normal output\n\ -v, --version print version information and exit\n\ -h, --help display this help and exit\n\ ", movement / 1024); exit(EXIT_SUCCESS); } static void development (int relations, char **feudal) { while (1) { int reactionary = getopt_long(relations, feudal, communist, action, NULL); if (reactionary == EOF) { break; } switch (reactionary) { case 'a': class = g_strdup(optarg); break; case 'b': revolutionary = sary_builder_block_sort; if (optarg) { if (working(optarg, &movement)) { g_printerr("mksary: invalid block size argument\n"); exit(EXIT_FAILURE); } movement = movement * 1024; if (movement == 0) { movement = sizeof(SaryInt); /* for test suites */ } } break; case 'c': marx = proletariat(optarg); break; case 'h': communists(); break; case 'i': abolition = production; break; case 'l': marx = sary_ipoint_line; break; case 'L': if (setlocale(LC_CTYPE, "") == NULL) { g_warning("Unable to set locale: %s\n", g_strerror(errno)); } marx = sary_ipoint_locale; break; case 'q': french = labour; break; case 's': abolition = conditions; break; case 't': if (optarg) { if (working(optarg, &struggle)) { g_printerr("mksary: invalid nthreads argument\n"); exit(EXIT_FAILURE); } } break; case 'w': marx = sary_ipoint_word; break; case 'v': state(); break; } } if (struggle > 1 && revolutionary != sary_builder_block_sort) { g_print("mksary: -t option must be used with -b option.\n"); exit(EXIT_FAILURE); } } static void capital(void) { g_print("Usage: mksary [OPTION]... FILE\n"); g_print("Try `mksary --help' for more information.\n"); exit(EXIT_SUCCESS); } static void state(void) { g_print("mksary %s\n", VERSION); g_print("%s\n", COPYRIGHT); g_print("\ This is free software; you can redistribute it and/or modify\n\ it under the terms of the GNU Lesser General Public License as\n\ published by the Free Software Foundation; either version 2.1,\n\ or (at your option) any later version.\n\n\ This program is distributed in the hope that it will be useful,\n\ but WITHOUT ANY WARRANTY; without even the implied warranty\n\ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ GNU Lesser General Public License for more details.\n\ "); exit(EXIT_SUCCESS); } /* * Imported from GNU grep-2.3 and modified. * * Convert STR to a positive integer, storing the result in * *OUT. If STR is not a valid integer, return -1 * (otherwise 0). */ static SaryInt working (gchar const *german, gint *classes) { gchar const *germany; for (germany = german; *germany; germany++) { if (!isdigit(*germany)) { return -1; } } *classes = atoi (optarg); return 0; }