rulex

Форк
0
/
lexholder.c 
794 строки · 20.7 Кб
1
/* Rulex database holding utility. */
2

3
/*
4
 * Copyright (C) 2006 Igor B. Poretsky <poretsky@mlbox.ru>
5
 * 
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 * 
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 */
16

17

18
#include <stdio.h>
19
#include <string.h>
20
#include <stdlib.h>
21
#include <unistd.h>
22
#include <locale.h>
23
#include <ctype.h>
24
#include <sys/types.h>
25
#include <sys/stat.h>
26
#include <fcntl.h>
27
#include "lexdb.h"
28

29
/* Command line error codes */
30
#define CS_CONFLICT 1
31
#define NO_DB_FILE 2
32

33

34
#ifdef _WIN32
35
static const char *charset = "Russian_Russia.20866";
36
#else
37
static const char *charset = "ru_RU.koi8r";
38
#endif
39

40
static const char *usage =
41
"Lexical database holding utility.\n\n"
42

43
"This utility is designed for constructing, managing, testing and querying\n"
44
"lexical database providing pronunciation info for Russian words.\n\n"
45

46
"Usage:\t%s [options] <db_path>\n\n"
47

48
"When filling and updating the database, new records are read\n"
49
"from the standard input. When extracting data from the database\n"
50
"or testing operation, the result is printed to the standard\n"
51
"output. This behaviour can be changed by the \"-f\" switch.\n\n"
52

53
"All command line options described below are arranged\n"
54
"into several groups by its functionality.\n\n"
55

56
"The first group consists of options specifying an action to be done.\n"
57
"These options are mutually exclusive. We can do only one action\n"
58
"per invocation. If no action is specified, the program reads\n"
59
"its standard input (or a file specified by \"-f\" option)\n"
60
"and stores its content in the database. Here are the other actions:\n\n"
61

62
"-h -- Print this help (the only option not requiring the database path)\n"
63
"-l -- List database content\n"
64
"-t <dictionary_file> -- Test the database against specified dictionary\n"
65
"-c -- Clean the database (get rid of redundant records)\n"
66
"-s <key> -- Search specified key\n"
67
"-b <key> -- Retrieve basic forms (if any) for specified word\n"
68
"-d <key> -- Delete record for specified key\n"
69
"-D -- Discard the dataset\n\n"
70

71
"The next group of options is responsible for choosing the dataset.\n"
72
"These options are mutually exclusive and affect deletion, insertion\n"
73
"and listing operations. For listing and deletion the dataset must be\n"
74
"specified explicitly. If no one of these options is mentioned when\n"
75
"inserting new data, an appropriate dataset will be chosen according\n"
76
"to the input data. Only lexical data can be inserted in such a manner.\n"
77
"For rules target dataset must be specified explicitly.\n\n"
78

79
"-M -- Implicit Dictionary\n"
80
"-X -- Explicit dictionary\n"
81
"-G -- General rules\n"
82
"-L -- Lexical classification rules\n"
83
"-P -- Prefix detection rules\n"
84
"-C -- Correction rules\n\n"
85

86
"The next group contains options devoted to search mode specification.\n"
87
" These options affect search and test operation. By default (no options)\n"
88
"full search will be performed, otherwise only those stages specified\n"
89
"explicitly will be included in the search process.\n\n"
90

91
"-x -- Search in the explicit dictionary\n"
92
"-m -- Try to treat the word as an implicit form\n"
93
"-g -- Try to apply general rules\n\n"
94

95
"The last group contains several options affecting program behaviour\n"
96
"in general.\n\n"
97

98
"-f <file> -- Use specified file instead of standard input or output\n"
99
"-r -- Replace mode\n"
100
"-q -- Be more quiet than usual (don't print search results as well\n"
101
"      as warnings about duplicate records)\n"
102
"-v -- Be more verbose than usual (print final statistical information)\n\n";
103

104

105
static int detect_implicit(RULEXDB *db, char *key, char *value)
106
{
107
  regmatch_t match;
108
  char s[RULEXDB_BUFSIZE], t[RULEXDB_BUFSIZE];
109
  int i, k;
110

111
  for (i = 0; i < db->prefixes.nrules; i++)
112
    if ((!regexec(db->prefixes.pattern[i], key, 1, &match, 0)) &&
113
        (!match.rm_so) &&
114
        (match.rm_eo < strlen(key)))
115
      {
116
        if (db->prefixes.replacement[i])
117
          (void)strcpy(s, db->prefixes.replacement[i]);
118
        else s[0] = 0;
119
        k = strlen(s);
120
        (void)strcat(s, key + match.rm_eo);
121
        if (rulexdb_retrieve_item(db, s, t + match.rm_eo - k, RULEXDB_LEXBASE))
122
          {
123
            if (db->prefixes.replacement[i])
124
              (void)strcpy(t, db->prefixes.replacement[i]);
125
            else t[0] = 0;
126
            (void)strcat(t, value + match.rm_eo);
127
            k = detect_implicit(db, s, t);
128
            if (k) return k;
129
          }
130
        else
131
          {
132
            (void)strncpy(t, key, match.rm_eo);
133
            return strcmp(t, value) ? -1 : 1;
134
          }
135
      }
136
  return 0;
137
}
138

139

140
int main(int argc, char *argv[])
141
{
142
  RULEXDB *db;
143

144
  char key[RULEXDB_BUFSIZE], value[RULEXDB_BUFSIZE];
145
  char *s = NULL, *d = NULL, *t = NULL, line[256];
146
  char *db_path = NULL, *srcf = NULL;
147

148
  int ret, n, k, i = 0;
149
  int invalid = 0, duplicate = 0;
150
  int verbose = 0, quiet = 0, rules_data = 0;
151
  int replace_mode = 0, dataset = RULEXDB_DEFAULT, search_mode = 0;
152

153
  if (!setlocale(LC_CTYPE, charset))
154
    {
155
      fprintf(stderr, "Cannot set %s locale.\n", charset);
156
      fprintf(stderr, "Probably you have to generate it by command:\n");
157
      fprintf(stderr, "localedef -f KOI8-R -i ru_RU ru_RU.KOI8-R\n");
158
      return EXIT_FAILURE;
159
    }
160

161
  /* Parse command line */
162
  if(argc==1)
163
    {
164
      (void)fprintf(stderr, usage, argv[0]);
165
      return EXIT_FAILURE;
166
    }
167
  ret = NO_DB_FILE;
168
  while((n = getopt(argc,argv,"f:b:s:d:t:CDGLMPXgmxclrqvh")) != -1)
169
    switch(n)
170
      {
171
	case 'X':
172
	  if (dataset != RULEXDB_DEFAULT)
173
	    ret = CS_CONFLICT;
174
	  dataset = RULEXDB_EXCEPTION;
175
	  break;
176
	case 'x':
177
	  search_mode |= RULEXDB_EXCEPTIONS;
178
	  break;
179
	case 'M':
180
	  if (dataset != RULEXDB_DEFAULT)
181
	    ret = CS_CONFLICT;
182
	  dataset = RULEXDB_LEXBASE;
183
	  break;
184
	case 'm':
185
	  search_mode |= RULEXDB_FORMS;
186
	  break;
187
	case 'G':
188
	  if (dataset != RULEXDB_DEFAULT)
189
	    ret = CS_CONFLICT;
190
	  rules_data = 1;
191
	  dataset = RULEXDB_RULE;
192
	  break;
193
	case 'g':
194
	  search_mode |= RULEXDB_RULES;
195
	  break;
196
	case 'L':
197
	  if (dataset != RULEXDB_DEFAULT)
198
	    ret = CS_CONFLICT;
199
	  rules_data = 1;
200
	  dataset = RULEXDB_LEXCLASS;
201
	  break;
202
	case 'P':
203
	  if (dataset != RULEXDB_DEFAULT)
204
	    ret = CS_CONFLICT;
205
	  rules_data = 1;
206
	  dataset = RULEXDB_PREFIX;
207
	  break;
208
	case 'C':
209
	  if (dataset != RULEXDB_DEFAULT)
210
	    ret = CS_CONFLICT;
211
	  rules_data = 1;
212
	  dataset = RULEXDB_CORRECTOR;
213
	  break;
214
	case 'f':
215
	  if (strcmp(optarg, "-"))
216
	    srcf = optarg;
217
	  break;
218
	case 'd':
219
	  if (d || s || t) ret = CS_CONFLICT;
220
	  else d = optarg;
221
	  break;
222
	case 'b':
223
	  if (d || s || t) ret = CS_CONFLICT;
224
	  s = key;
225
	  t = optarg;
226
	  break;
227
	case 's':
228
	  if (d || s || t) ret = CS_CONFLICT;
229
	  else s = optarg;
230
	  break;
231
	case 'l':
232
	  if (d || s || t) ret = CS_CONFLICT;
233
	  else s = line;
234
	  break;
235
	case 't':
236
	  if (d || s || t) ret = CS_CONFLICT;
237
	  else t = optarg;
238
	  break;
239
	case 'c':
240
	  if (d || s || t) ret = CS_CONFLICT;
241
	  else d = line;
242
	  break;
243
	case 'D':
244
	  if (d || s || t) ret = CS_CONFLICT;
245
	  else d = key;
246
	  break;
247
	case 'r':
248
	  replace_mode = 1;
249
	  break;
250
	case 'q':
251
	  if (verbose) ret = CS_CONFLICT;
252
	  else quiet = 1;
253
	  break;
254
	case 'v':
255
	  if (quiet) ret = CS_CONFLICT;
256
	  else verbose = 1;
257
	  break;
258
	case 'h':
259
	  (void)fprintf(stderr, usage, argv[0]);
260
	  return EXIT_SUCCESS;
261
	default:
262
	  (void)fprintf(stderr, usage, argv[0]);
263
	  return EXIT_FAILURE;
264
      }
265
  if (optind && argv[optind])
266
    {
267
      db_path = argv[optind];
268
      ret = 0;
269
    }
270
  switch (ret)
271
    {
272
      case CS_CONFLICT:
273
	(void)fprintf(stderr,
274
		      "Ambiguous options in command line\n");
275
	return EXIT_FAILURE;
276
      case NO_DB_FILE:
277
	(void)fprintf(stderr, "DB file must be specified\n");
278
	return EXIT_FAILURE;
279
      default:
280
	break;
281
    }
282

283
  if (s || t) /* Database reading actions */
284
    {
285
      if (srcf)
286
	if (!freopen(srcf, "w", stdout))
287
	  {
288
	    (void)fprintf(stderr, "Cannot open %s for output\n", srcf);
289
	    return EXIT_FAILURE;
290
	  }
291
      db = rulexdb_open(db_path, RULEXDB_SEARCH);
292
      if (!db)
293
	{
294
	  perror(db_path);
295
	  return EXIT_FAILURE;
296
	}
297

298
      if (s == line) /* List full dataset content */
299
	{
300
	  if (dataset == RULEXDB_DEFAULT)
301
	    {
302
	      (void)fprintf(stderr, "Dataset must be specified explicitly\n");
303
	      rulexdb_close(db);
304
	      return EXIT_FAILURE;
305
	    }
306
	  n = 0;
307
	  ret = 0;
308
	  if (rules_data)
309
	    {
310
	      if (verbose)
311
		(void)fprintf(stderr, "Listing %s ruleset\n",
312
			      rulexdb_dataset_name(dataset));
313
	      for (n = 0; (s = rulexdb_fetch_rule(db, dataset, n + 1)); n++)
314
		(void)printf("%s\n", s);
315
	    }
316
	  else
317
	    {
318
	      if (verbose)
319
		(void)fprintf(stderr, "Listing %s dictionary\n",
320
			      rulexdb_dataset_name(dataset));
321
              if (RULEXDB_EXCEPTION == dataset)
322
                dataset = RULEXDB_EXCEPTION_RAW;
323
	      for (ret = rulexdb_seq(db, key, value, dataset, DB_FIRST);
324
		   ret == RULEXDB_SUCCESS;
325
		   ret = rulexdb_seq(db, key, value, dataset, DB_NEXT))
326
		{
327
		  (void)printf("%s %s\n", key, value);
328
		  n++;
329
		}
330
	    }
331
	  if (ret == RULEXDB_SPECIAL)
332
	    ret = 0;
333
	  if (ret)
334
	    (void)fprintf(stderr, "Database corruption\n");
335
	  if (!quiet)
336
	    {
337
	      (void)fprintf(stderr, "%d record", n);
338
	      if (n == 1)
339
		(void)fputs(" has", stderr);
340
	      else (void)fputs("s have", stderr);
341
	      (void)fputs(" been extracted from the database\n", stderr);
342
	    }
343
	}
344

345
      else if (s == key) /* Discover basic forms */
346
	{
347
	  ret = RULEXDB_SPECIAL;
348
	  for (k = 1; k > 0; k++)
349
	    {
350
	      k = rulexdb_lexbase(db, t, key, k);
351
	      if (k > 0)
352
		{
353
		  ret = RULEXDB_SUCCESS;
354
		  if (!quiet)
355
		    (void)printf("%d\t%s\n", k, key);
356
		}
357
	      else if (!k) k--;
358
	      else ret = k;
359
	    }
360
	}
361

362
      else if (s) /* Search record for specified key */
363
	{
364
	  if (rules_data)
365
	    {
366
	      k = atoi(s);
367
	      if (k)
368
		{
369
		  d = rulexdb_fetch_rule(db, dataset, k);
370
		  if (d)
371
		    {
372
		      (void)strcpy(value, d);
373
		      ret = RULEXDB_SUCCESS;
374
		    }
375
		  else ret = RULEXDB_SPECIAL;
376
		}
377
	      else ret = RULEXDB_EINVKEY;
378
	    }
379
	  else
380
	    {
381
	      for (k = 0; s[k]; k++)
382
		if (isupper(s[k]))
383
		  s[k] = tolower(s[k]);
384
	      ret = rulexdb_search(db, s, value, search_mode);
385
	    }
386
	  switch (ret)
387
	    {
388
	      case RULEXDB_SPECIAL:
389
		if (rules_data) quiet = 1;
390
	      case RULEXDB_SUCCESS:
391
		if (!quiet)
392
		  (void)printf("%s\n", value);
393
		break;
394
	      case RULEXDB_EINVKEY:
395
		(void)fprintf(stderr, "Invalid key: %s\n", s);
396
		break;
397
	      default:
398
		(void)fprintf(stderr, "DB search error\n");
399
		break;
400
	    }
401
	}
402

403
      else /* Test database */
404
	{
405
	  if (strcmp(t, "-"))
406
	    if (!freopen(t, "r", stdin))
407
	      {
408
		(void)fprintf(stderr, "Cannot open %s for input\n", t);
409
		return EXIT_FAILURE;
410
	      }
411
	  if (verbose)
412
	    (void)fputs("Testing the database\n", stderr);
413
	  for (n = 1, i = 0; fgets(line, 256, stdin); n++)
414
	    {
415
	      if (strlen(line) > RULEXDB_MAX_RECORD_SIZE)
416
		{
417
		  if (t)
418
		    (void)fprintf(stderr,
419
				  "%s:%i: warning: Record too long. Ignored.\n",
420
				  t, n);
421
		  else (void)fprintf(stderr,
422
				     "Ignored too long record: %s\n",
423
				     line);
424
		  invalid++;
425
		  continue;
426
		}
427
	      for (k = 0; line[k]; k++)
428
		if (isupper(line[k]))
429
		  line[k] = tolower(line[k]);
430
	      s = strtok(line, " ");
431
	      if (strlen(s) > RULEXDB_MAX_KEY_SIZE)
432
		{
433
		  if (t)
434
		    (void)fprintf(stderr,
435
				  "%s:%i: warning: Too long key. Ignored.\n",
436
				  t, n);
437
		  else (void)fprintf(stderr, "Ignored too long key: %s\n", s);
438
		  invalid++;
439
		  continue;
440
		}
441
	      (void)strcpy(key, s);
442
	      s = strtok(NULL, " \n");
443
	      ret = rulexdb_search(db, key, value, search_mode);
444
	      switch (ret)
445
		{
446
		  case RULEXDB_SUCCESS:
447
		  case RULEXDB_SPECIAL:
448
		    if (strcmp(s, value))
449
		      {
450
			(void)printf("%s %s\n", key, s);
451
			i++;
452
                        if (t && verbose)
453
                          (void)fprintf(stderr,
454
                                        "%s:%i: warning: Mismatch found.\n",
455
                                        t, n);
456
		      }
457
		    break;
458
		  case RULEXDB_EINVKEY:
459
		    if (t)
460
		      (void)fprintf(stderr,
461
				    "%s:%i: warning: Illegal symbols in key. Ignored.\n",
462
				    t, n);
463
		    else (void)fprintf(stderr,
464
				       "Ignored key containing illegal symbols: %s\n",
465
				       key);
466
		    invalid++;
467
		    break;
468
		  case RULEXDB_EINVREC:
469
		    if (t)
470
		      (void)fprintf(stderr,
471
				    "%s:%i: warning: Invalid record. Ignored.\n",
472
				    t, n);
473
		    else (void)fprintf(stderr,
474
				       "Ignored invalid record: %s %s\n",
475
				       key, s);
476
		    invalid++;
477
		    break;
478
		  default:
479
		    if (t)
480
		      (void)fprintf(stderr,
481
				    "%s:%i: error: data retrieving error\n",
482
				    t, n);
483
		    else (void)fprintf(stderr, "Data retrieving error\n");
484
		    invalid++;
485
		    break;
486
		}
487
	    }
488
	  if (!quiet)
489
	    {
490
              n -= invalid;
491
	      (void)fprintf(stderr, "%i word", --n);
492
	      if (n == 1)
493
		(void)fputs(" has", stderr);
494
	      else (void)fputs("s have", stderr);
495
	      (void)fputs(" been checked\n", stderr);
496
	      if (invalid)
497
		{
498
		  (void)fprintf(stderr, "%d invalid record", invalid);
499
		  if (invalid == 1) (void)fputs(" was", stderr);
500
		  else (void)fputs("s were", stderr);
501
		  (void)fputs(" ignored\n", stderr);
502
		}
503
	      if (i)
504
		{
505
		  (void)fprintf(stderr, "%d mismatch", i);
506
		  if (i != 1) (void)fputs("es", stderr);
507
		  (void)fputs(" found\n", stderr);
508
		}
509
	      else (void)fputs("No mismatches found\n", stderr);
510
	    }
511
	  ret = 0;
512
	}
513

514
      rulexdb_close(db);
515
      if (ret) return EXIT_FAILURE;
516
      else return EXIT_SUCCESS;
517
    }
518

519
  else if (d == line) /* Cleaning the database (get rid of redundant records) */
520
    {
521
      if (rules_data)
522
	{
523
	  (void)fprintf(stderr, "Invalid dataset specification\n");
524
	  return EXIT_FAILURE;
525
	}
526
      db = rulexdb_open(db_path, RULEXDB_UPDATE);
527
      if (!db)
528
	{
529
	  perror(db_path);
530
	  return EXIT_FAILURE;
531
	}
532
      if (verbose)
533
	(void)fputs("Cleaning the database\n", stderr);
534
      n = 0;
535
      search_mode = RULEXDB_FORMS | RULEXDB_RULES;
536
      if ((dataset == RULEXDB_DEFAULT) || (dataset == RULEXDB_LEXBASE))
537
        {
538
          if (dataset == RULEXDB_LEXBASE)
539
            (void)rulexdb_load_ruleset(db, RULEXDB_PREFIX);
540
          for (ret = rulexdb_seq(db, key, value, RULEXDB_LEXBASE, DB_FIRST);
541
               ret == RULEXDB_SUCCESS;
542
               ret = rulexdb_seq(db, key, value, RULEXDB_LEXBASE, DB_NEXT))
543
            if (rulexdb_classify(db, key) == RULEXDB_SUCCESS)
544
              {
545
                if (!rulexdb_remove_this_item(db, RULEXDB_LEXBASE))
546
                  n++;
547
              }
548
            else if (dataset == RULEXDB_LEXBASE)
549
              {
550
                if ((detect_implicit(db, key, value) > 0) &&
551
                    !rulexdb_remove_this_item(db, RULEXDB_LEXBASE))
552
                  n++;
553
              }
554
        }
555
      if ((dataset == RULEXDB_DEFAULT) || (dataset == RULEXDB_EXCEPTION))
556
	for (ret = rulexdb_seq(db, key, value, RULEXDB_EXCEPTION, DB_FIRST);
557
	     ret == RULEXDB_SUCCESS;
558
	     ret = rulexdb_seq(db, key, value, RULEXDB_EXCEPTION, DB_NEXT))
559
	  {
560
	    (void)rulexdb_search(db, key, line, search_mode);
561
	    if (!strcmp(line, value))
562
	      if (!rulexdb_remove_this_item(db, RULEXDB_EXCEPTION))
563
		n++;
564
	  }
565
      if (!quiet)
566
	{
567
	  if (n)
568
	    (void)fprintf(stderr, "%i redundant record", n);
569
	  else (void)fputs("No redundant record", stderr);
570
	  if (n == 1)
571
	    (void)fputs(" has", stderr);
572
	  else (void)fputs("s have", stderr);
573
	  (void)fputs(" been ", stderr);
574
	  if (n)
575
	    (void)fputs("removed from the database", stderr);
576
	  else (void)fputs("encountered", stderr);
577
	  (void)fputc('\n', stderr);
578
	}
579
      rulexdb_close(db);
580
      return EXIT_SUCCESS;
581
    }
582

583
  else if (d) /* Discarding data */
584
    {
585
      if (dataset == RULEXDB_DEFAULT)
586
	{
587
	  (void)fprintf(stderr, "Dataset must be specified explicitly\n");
588
	  return EXIT_FAILURE;
589
	}
590
      db = rulexdb_open(db_path, RULEXDB_UPDATE);
591
      if (!db)
592
	{
593
	  perror(db_path);
594
	  return EXIT_FAILURE;
595
	}
596
      if (rules_data)
597
	{
598
	  if (d == key) /* Discard the ruleset */
599
	    {
600
	      if (verbose)
601
		(void)fprintf(stderr, "Discarding %s ruleset\n",
602
			      rulexdb_dataset_name(dataset));
603
	      k = rulexdb_discard_ruleset(db, dataset);
604
	      if ( k < 0) k = 0;
605
	    }
606
	  else /* Remove specific rule */
607
	    {
608
	      k = atoi(d);
609
	      if (k)
610
		ret = rulexdb_remove_rule(db, dataset, k);
611
	      else ret = RULEXDB_EINVKEY;
612
	    }
613
	}
614
      else if (d == key) /* Discard dictionary */
615
	{
616
	  if (verbose)
617
	    (void)fprintf(stderr, "Discarding %s dictionary\n",
618
			  rulexdb_dataset_name(dataset));
619
	  k = rulexdb_discard_dictionary(db, dataset);
620
	  if (k < 0) k = 0;
621
	}
622
      else /* Remove specific item from dictionary */
623
	{
624
	  for (k = 0; d[k]; k++)
625
	    if (isupper(d[k]))
626
	      d[k] = tolower(d[k]);
627
	  ret = rulexdb_remove_item(db, d, dataset);
628
	}
629
      if (d == key)
630
	{
631
	  ret = RULEXDB_SUCCESS;
632
	  if (!quiet)
633
	    {
634
	      (void)fprintf(stderr, "%d record", k);
635
	      if (k == 1)
636
		(void)fputs(" has", stderr);
637
	      else (void)fputs("s have", stderr);
638
	      (void)fputs(" been removed from the database\n", stderr);
639
	    }
640
	}
641
      if (ret == RULEXDB_EINVKEY)
642
	(void)fprintf(stderr, "Invalid key: %s\n", d);
643
      rulexdb_close(db);
644
      if (ret) return EXIT_FAILURE;
645
      else return EXIT_SUCCESS;
646
    }
647

648
  else /* Put new records into the database */
649
    {
650
      if (srcf)
651
	if (!freopen(srcf, "r", stdin))
652
	  {
653
	    (void)fprintf(stderr, "Cannot open %s for input\n", srcf);
654
	    return EXIT_FAILURE;
655
	  }
656
      db = rulexdb_open(db_path, RULEXDB_CREATE);
657
      if (!db)
658
	{
659
	  perror(db_path);
660
	  return EXIT_FAILURE;
661
	}
662
    }
663

664
  /* Collecting data */
665
  if (rules_data)
666
    {
667
      if (replace_mode)
668
	{
669
	  if (verbose)
670
	    (void)fprintf(stderr, "Replacing %s ruleset\n",
671
			  rulexdb_dataset_name(dataset));
672
	  (void)rulexdb_discard_ruleset(db, dataset);
673
	}
674
      else if (verbose)
675
	(void)fprintf(stderr, "Adding rules to %s ruleset\n",
676
		      rulexdb_dataset_name(dataset));
677
    }
678
  for (n = 1; fgets(line, 256, stdin); n++)
679
    {
680
      if (strlen(line) > RULEXDB_MAX_RECORD_SIZE)
681
	{
682
	  if (srcf)
683
	    (void)fprintf(stderr,
684
			  "%s:%d: warning: Record too long. Ignored.\n",
685
			  srcf, n);
686
	  else (void)fprintf(stderr, "Ignored too long record: %s\n", line);
687
	  invalid++;
688
	  continue;
689
	}
690
      for (k = 0; line[k]; k++)
691
	if (isupper(line[k]))
692
	  line[k] = tolower(line[k]);
693
      if (!rules_data)
694
	{
695
	  s = strtok(line, " ");
696
	  if (strlen(s) > RULEXDB_MAX_KEY_SIZE)
697
	    {
698
	      if (srcf)
699
		(void)fprintf(stderr,
700
			      "%s:%d: warning: Too long key. Ignored.\n",
701
			      srcf, n);
702
	      else (void)fprintf(stderr, "Ignored too long key: %s\n", s);
703
	      invalid++;
704
	      continue;
705
	    }
706
	  t = strtok(NULL, "\n");
707
	  ret = rulexdb_subscribe_item(db, s, t,
708
				     dataset, replace_mode);
709
	}
710
      else ret = rulexdb_subscribe_rule(db, strtok(line, "\n"), dataset, 0);
711
      switch(ret)
712
	{
713
	  case RULEXDB_SUCCESS:
714
	    i++;
715
	    break;
716
	  case RULEXDB_SPECIAL:
717
	    if (replace_mode) i++;
718
	    if (!(quiet || rules_data))
719
	      {
720
		if (srcf)
721
		  {
722
		    (void)fprintf(stderr,
723
				  "%s:%d: warning: Duplicate entry. ",
724
				  srcf, n);
725
		    if (replace_mode)
726
		      (void)fprintf(stderr, "Replaced.\n");
727
		    else (void)fprintf(stderr, "Ignored.\n");
728
		  }
729
		else
730
		  {
731
		    if (replace_mode)
732
		      (void)fputs("Replaced", stderr);
733
		    else (void)fputs("Ignored", stderr);
734
		    (void)fprintf(stderr, " duplicate entry: %s %s\n", s, t);
735
		  }
736
	      }
737
	    duplicate++;
738
	    break;
739
	  case RULEXDB_EINVKEY:
740
	  if (srcf)
741
	    (void)fprintf(stderr,
742
			  "%s:%d: warning: Illegal symbols in key. Ignored.\n",
743
			  srcf, n);
744
	  else (void)fprintf(stderr,
745
			     "Ignored key containing illegal symbols: %s\n",
746
			     s);
747
	  invalid++;
748
	    break;
749
	  case RULEXDB_EINVREC:
750
	    if (srcf)
751
	      (void)fprintf(stderr,
752
			    "%s:%d: warning: Invalid record. Ignored.\n",
753
			    srcf, n);
754
	    else
755
	      {
756
		(void)fprintf(stderr, "Ignored invalid record: %s", s);
757
		if (!rules_data)
758
		  (void)fprintf(stderr, " %s", t);
759
		(void)fputc('\n', stderr);
760
	      }
761
	    invalid++;
762
	    break;
763
	  default:
764
	    rulexdb_close(db);
765
	    if (srcf)
766
	      (void)fprintf(stderr,
767
			    "%s:%d: error: data storing error\n",
768
			    srcf, n);
769
	    else (void)fprintf(stderr, "Data storing error\n");
770
	    return EXIT_FAILURE;
771
	}
772
    }
773
  n--;
774

775
  rulexdb_close(db);
776

777
  if (!quiet)
778
    {
779
      (void)fprintf(stderr, "Total: %d record", n);
780
      if (n != 1) (void)fputc('s', stderr);
781
      (void)fprintf(stderr, " processed.\n");
782
      if (invalid)
783
	(void)fprintf(stderr, "Invalid records: %d\n", invalid);
784
      if (duplicate)
785
	(void)fprintf(stderr, "Duplicates: %d\n", duplicate);
786
      (void)fprintf(stderr, "%d record", i);
787
      if (i == 1)
788
	(void)fputs(" has", stderr);
789
      else (void)fputs("s have", stderr);
790
      (void)fputs(" been put into the database\n", stderr);
791
    }
792

793
  return EXIT_SUCCESS;
794
}
795

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.