source: git/src/sorterr.c @ 9fcc81a

RELEASE/1.2debug-cidebug-ci-sanitiserswalls-datawalls-data-hanging-as-warning
Last change on this file since 9fcc81a was ffee37e, checked in by Olly Betts <olly@…>, 10 years ago

src/extend.c,src/mainfrm.cc,src/sorterr.c: Fix message references
which I failed to update.

  • Property mode set to 100644
File size: 6.8 KB
RevLine 
[d06141c]1/* sorterr.c */
2/* Sort a survex .err file */
[736f7df]3/* Copyright (C) 2001,2002,2005,2010,2011,2014 Olly Betts
[d06141c]4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
[ecbc6c18]17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[d06141c]18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <ctype.h>
25#include <math.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include "cmdline.h"
[fa42426]31#include "filename.h"
[bfe1242]32#include "message.h"
[d06141c]33#include "osalloc.h"
[5baea35]34#include "whichos.h"
[d06141c]35
36static const struct option long_opts[] = {
37   /* const char *name; int has_arg (0 no_argument, 1 required_*, 2 optional_*); int *flag; int val; */
38   {"horizontal", no_argument, 0, 'h'},
39   {"vertical", no_argument, 0, 'v'},
40   {"percentage", no_argument, 0, 'p'},
41   {"per-leg", no_argument, 0, 'l'},
[059d065]42   {"replace", no_argument, 0, 'r'},
[d06141c]43   {"help", no_argument, 0, HLP_HELP},
44   {"version", no_argument, 0, HLP_VERSION},
45   {0, 0, 0, 0}
46};
47
[059d065]48#define short_opts "hvplr"
[d06141c]49
50static struct help_msg help[] = {
51/*                              <-- */
[736f7df]52   /* TRANSLATORS: --help output for sorterr --horizontal option */
[45af761]53   {HLP_ENCODELONG(0),        /*sort by horizontal error factor*/179, 0},
[736f7df]54   /* TRANSLATORS: --help output for sorterr --vertical option */
[45af761]55   {HLP_ENCODELONG(1),        /*sort by vertical error factor*/180, 0},
[736f7df]56   /* TRANSLATORS: --help output for sorterr --percentage option */
[45af761]57   {HLP_ENCODELONG(2),        /*sort by percentage error*/181, 0},
[736f7df]58   /* TRANSLATORS: --help output for sorterr --per-leg option */
[45af761]59   {HLP_ENCODELONG(3),        /*sort by error per leg*/182, 0},
[736f7df]60   /* TRANSLATORS: --help output for sorterr --replace option */
[45af761]61   {HLP_ENCODELONG(4),        /*replace .err file with resorted version*/183, 0},
62   {0, 0, 0}
[d06141c]63};
64
65typedef struct {
66   double err;
67   long fpos;
68} trav;
69
70static void
[dcf6125]71skipline(const char *fnm, FILE *fh)
[d06141c]72{
73   int ch;
74   do {
[e02a6a6]75      ch = GETC(fh);
[d06141c]76   } while (ch != '\n' && ch != EOF);
[dcf6125]77
[d06141c]78   if (ch == EOF) {
[dcf6125]79      if (ferror(fh))
80         fatalerror_in_file(fnm, 0, /*Error reading file*/18);
[ee7511a]81      fatalerror_in_file(fnm, 0, /*Couldn’t parse .err file*/112);
[d06141c]82   }
83}
84
85static void
[dcf6125]86printline(const char *fnm, FILE *fh, FILE *fh_out)
[d06141c]87{
88   int ch;
89   do {
[e02a6a6]90      ch = GETC(fh);
91      if (ch != EOF && ch != '\r' && ch != '\n') PUTC(ch, fh_out);
[d06141c]92   } while (ch != '\n' && ch != EOF);
[e02a6a6]93   PUTC('\n', fh_out);
[dcf6125]94
[d06141c]95   if (ch == EOF) {
[dcf6125]96      if (ferror(fh))
97         fatalerror_in_file(fnm, 0, /*Error reading file*/18);
[ee7511a]98      fatalerror_in_file(fnm, 0, /*Couldn’t parse .err file*/112);
[d06141c]99   }
100}
101
102static int
103cmp_trav(const void *a, const void *b)
104{
105   double diff = ((const trav *)a)->err - ((const trav *)b)->err;
106   if (diff < 0) return -1;
107   if (diff > 0) return 1;
108   return 0;
109}
110
111int
112main(int argc, char **argv)
113{
114   char *fnm;
115   FILE *fh;
116   char sortby = 'A';
117   size_t len = 1024;
118   trav *blk = osmalloc(1024 * sizeof(trav));
119   size_t next = 0;
120   size_t howmany = 0;
[059d065]121   FILE *fh_out = stdout;
122   char *fnm_out = NULL;
[d06141c]123
[bdfe97f]124   msg_init(argv);
[d06141c]125
[736f7df]126   /* TRANSLATORS: Part of sorterr --help */
[a7b5554]127   cmdline_set_syntax_message(/*ERR_FILE [HOW_MANY]*/268, 0, NULL);
[d06141c]128   cmdline_init(argc, argv, short_opts, long_opts, NULL, help, 1, 2);
129   while (1) {
130      int opt = cmdline_getopt();
131      if (opt == EOF) break;
132      switch (opt) {
133       case 'h': case 'v': case 'p': case 'l':
134         sortby = toupper(opt);
135         break;
[059d065]136       case 'r':
137         fh_out = NULL;
138         break;
[d06141c]139      }
140   }
141
142   fnm = argv[optind++];
143   if (argv[optind]) howmany = atoi(argv[optind]);
144
145   fh = fopen(fnm, "rb");
[ffee37e]146   if (!fh) fatalerror(/*Couldn’t open file “%s”*/24, fnm);
[d06141c]147
148   /* 4 line paragraphs, separated by blank lines...
149    * 041.verhall.12 - 041.verhall.13
150    * Original length   2.97m (  1 legs), moved   0.04m ( 0.04m/leg). Error   1.19%
151    * 0.222332
152    * H: 0.224749 V: 0.215352
153    *
154    */
155   while (1) {
156      int ch;
157      if (next == len) {
158         len += len;
[dd5a89c]159         blk = osrealloc(blk, len * ossizeof(trav));
[d06141c]160      }
[e03662e]161      blk[next].fpos = ftell(fh);
[e02a6a6]162      ch = GETC(fh);
[d06141c]163      if (ch == EOF) break;
[dcf6125]164      skipline(fnm, fh);
[d06141c]165      switch (sortby) {
166       case 'A':
[dcf6125]167         skipline(fnm, fh);
[d06141c]168         if (fscanf(fh, "%lf", &blk[next].err) != 1) {
169            baderrfile:
[4340dae]170            fatalerror_in_file(fnm, 0, /*Couldn’t parse .err file*/112);
[d06141c]171         }
[dcf6125]172         skipline(fnm, fh);
173         skipline(fnm, fh);
[d06141c]174         break;
175       case 'H': case 'V':
[dcf6125]176         skipline(fnm, fh);
177         skipline(fnm, fh);
[d06141c]178         do {
[e02a6a6]179            ch = GETC(fh);
[d06141c]180            if (ch == '\n' || ch == EOF) goto baderrfile;
181         } while (ch != sortby);
182         if (fscanf(fh, ":%lf", &blk[next].err) != 1) goto baderrfile;
[dcf6125]183         skipline(fnm, fh);
[d06141c]184         break;
185       case 'P':
186         do {
[e02a6a6]187            ch = GETC(fh);
[d06141c]188            if (ch == '\n' || ch == EOF) goto baderrfile;
189         } while (ch != ')');
190         do {
[e02a6a6]191            ch = GETC(fh);
[d06141c]192            if (ch == '\n' || ch == EOF) goto baderrfile;
193         } while (ch != ')');
194         do {
[e02a6a6]195            ch = GETC(fh);
[d06141c]196            if (ch == '\n' || ch == EOF) goto baderrfile;
197         } while (!isdigit(ch));
198         ungetc(ch, fh);
199         if (fscanf(fh, "%lf", &blk[next].err) != 1) goto baderrfile;
[dcf6125]200         skipline(fnm, fh);
201         skipline(fnm, fh);
202         skipline(fnm, fh);
[d06141c]203         break;
204       case 'L':
205         do {
[e02a6a6]206            ch = GETC(fh);
[d06141c]207            if (ch == '\n' || ch == EOF) goto baderrfile;
208         } while (ch != ')');
209         do {
[e02a6a6]210            ch = GETC(fh);
[d06141c]211            if (ch == '\n' || ch == EOF) goto baderrfile;
212         } while (ch != '(');
213         if (fscanf(fh, "%lf", &blk[next].err) != 1) goto baderrfile;
[dcf6125]214         skipline(fnm, fh);
215         skipline(fnm, fh);
216         skipline(fnm, fh);
[d06141c]217         break;
218      }
[dcf6125]219      skipline(fnm, fh);
[d06141c]220      next++;
221   }
222
[5baea35]223   if (next == 0) {
224      /* no entries - nothing more to do whether -r is specified or not */
225      exit(EXIT_SUCCESS);
226   }
227
[d06141c]228   qsort(blk, next, sizeof(trav), cmp_trav);
229
[059d065]230   if (fh_out == NULL) {
231      char *base = base_from_fnm(fnm);
232      fnm_out = add_ext(base, "tmp");
233      osfree(base);
[893cc20]234      fh_out = safe_fopen(fnm_out, "w");
[059d065]235   }
236
[d06141c]237   do {
238      --next;
[908298d]239      if (fseek(fh, blk[next].fpos, SEEK_SET) == -1)
240         fatalerror_in_file(fnm, 0, /*Error reading file*/18);
241
[dcf6125]242      printline(fnm, fh, fh_out);
243      printline(fnm, fh, fh_out);
244      printline(fnm, fh, fh_out);
245      printline(fnm, fh, fh_out);
[e02a6a6]246      PUTC('\n', fh_out);
[d06141c]247      if (howmany && --howmany == 0) break;
248   } while (next);
[e5d7e205]249   fclose(fh);
[d06141c]250
[059d065]251   if (fnm_out) {
[f1067a2]252      safe_fclose(fh_out);
[affaeee]253#if OS_WIN32
[1d89197]254      /* UNIX rename atomically replaces, so doesn't need this.
255       * WIN32 won't overwrite (from tests) so needs this code.
256       */
[893cc20]257      remove(fnm);
258#endif
[059d065]259      rename(fnm_out, fnm);
260   }
261
[d06141c]262   return 0;
263}
Note: See TracBrowser for help on using the repository browser.