aboutsummaryrefslogtreecommitdiff
path: root/vendor/voclient/libvotable/examples/votcopy.c
blob: f88087521a631791effda3095689bb16bc2b4271 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/**
 *  VOTCOPY -- Copy a VOTable to a different format. 
 *
 *    Usage:
 *		votcopp [-f <fmt>] [-o <fname>] <votable>
 *    Where
 *	    -f <fmt>	    Output format (XML, CSV, TSV, HTML, etc)
 *	    -h 	    	    Print help summary
 *	    -i <N>     	    Indention at each level for VOTable output
 *	    -o <fname>	    Name of output file
 *
 *	    --noheader	    Don't write a header
 *	    --help 	    Print help summary
 *
 *	    <votable>	    Name of input file to compress
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include "votParse.h"


int 	votcopy (int argc, char **argv);

/**
 *  Program Main.  This is just a wrapper around the interface routine.
 */
int
main (int argc, char **argv)
{
    return votcopy (argc, argv);
}



/************************************************************************ 
 *									*
 *  VOTCOPY -- Copy a votable to a new format, converting format if 	*
 *  needed.								*
 *									*
 ************************************************************************/

#define	FORMATS "|vot|asv|bsv|csv|tsv|html|shtml|fits|xml"

#define	VOT	0			/* A new VOTable		*/
#define	ASV	1			/* ascii separated values	*/
#define	BSV	2			/* bar separated values		*/
#define	CSV	3			/* comma separated values	*/
#define	TSV	4			/* tab separated values		*/
#define	HTML	5			/* standalone HTML document	*/
#define	SHTML	6			/* single HTML <table>		*/
#define	FITS	7			/* FITS binary table		*/
#define	XML	8			/* VOTable alias		*/

#define	SZ_FORMAT	32


char   *fmt	= NULL;			/* format string		*/
int	vot	= 0;			/* VOTable root handle		*/
int	indent	= 0;			/* indention at each level	*/
int	ofmt	= CSV;			/* format			*/
int	hdr	= TRUE;


static int strdic (char *in_str, char *out_str, int maxchars, char *dict);


/**
 *  Application entry point.
 */
int
votcopy (int argc, char **argv)
{
    register int i;
    int  stat = OK;
    char   *ifname = NULL, *name = NULL, *ofname = NULL, format[SZ_FORMAT];


    /*  Parse the argument list.
     */
    if (argc < 2) {
	fprintf (stderr, "Usage:  votcopy [-o <fname>] [-f <fmt>] <votable>\n");
	return (1);

    } else if (argc >= 2) {
	for (i=1; i < argc; i++) {
	    if (argv[i][0] == '-' && strlen (argv[i]) > 1) {
		switch (argv[i][1]) {
		case 'f':    fmt    = argv[++i];   		break;
		case 'i':    indent = atoi (argv[++i]);		break;
		case 'o':    name  = argv[++i];   		break;
		default:
		    fprintf (stderr, "Invalid argument '%c'\n", argv[i][1]);
		    return (1);
		}
	    } else
		ifname = argv[i];
	}
    }
    ofname = (name ? name : "stdout");


    /* Open and parse the input table.
    */
    if ( (vot = vot_openVOTABLE (ifname) ) <= 0) {
	fprintf (stderr, "Error opening VOTable '%s'\n", ifname);
	return (ERR);
    }

    /*  Output the new format.
     */
    switch (strdic (fmt, format, SZ_FORMAT, FORMATS)) {
    case VOT:   vot_writeVOTable (vot, ofname, indent);     break;
    case ASV:   vot_writeASV (vot, ofname);      	    break;
    case BSV:   vot_writeBSV (vot, ofname);      	    break;
    case CSV:   vot_writeCSV (vot, ofname);      	    break;
    case TSV:   vot_writeTSV (vot, ofname);      	    break;
    case HTML:  vot_writeHTML (vot, ifname, ofname);   	    break;
    case SHTML: vot_writeSHTML (vot, ifname, ofname);  	    break;
    case FITS:  vot_writeFITS (vot, ofname);    	    break;
    case XML:   vot_writeVOTable (vot, ofname, indent);     break;
    default:
	fprintf (stderr, "Unknown output format '%s'\n", format);
	stat = ERR;
    }
    vot_closeVOTABLE (vot);		/* close the table  	*/

    return (stat);
}


/**
 *  STRDIC -- Search a dictionary string for a match with an input string.
 *  The input string may be an abbreviation of a dictionary entry, however,
 *  it is an error if the abbreviation is not unique.  The entries in the
 *  dictionary string are separated by a delimiter character which is the
 *  first character of the dictionary string.  The full name of the matched 
 *  dictionary entry found is returned in out_str; the function value is 
 *  the word index of the dictionary entry.  The output string may be the 
 *  same as the input string.
 */

#include <ctype.h>

static int strdic (
  char	*in_str,		/* Input string, always lower case	*/
  char	*out_str,		/* Output string as found in dictionary */
  int	 maxchars,		/* Maximum length of output string	*/
  char	*dict 			/* Dictionary string			*/
)
{
    char  ch, fch;
    int	  start, len, ip, i, match, entry;


    if (dict == NULL || dict[0] == '\0')
	return (0);

    for (i=0; isspace(in_str[i]); i++)
	;

    start = i;
    match = 0;
    ip    = 1;
    len   = strlen (&in_str[start]);
    fch   = in_str[start];


    /*  Search the dictionary string.  If the input string matches a
     *  dictionary entry it is either an exact match (len = dictionary
     *  entry length) or a legal abbreviation.  If an abbreviation
     *  matches two entries it is ambiguous and an error.
     */
    for (entry=0;  dict[ip] != '\0';  entry=entry+1) {
	if (dict[ip] == fch) {
	    if (strncmp (&dict[ip], &in_str[start], len) == 0) {
		for (i=0;  i < maxchars;  i++) {
		    ch = dict[ip+i-1];
		    if ((ch == dict[0]) || (ch == '\0'))
			break;
		    out_str[i] = ch;
		}
		out_str[i] = '\0';

		if ((dict[ip+len] == dict[0]) || (dict[ip+len] == '\0'))
		    return (entry);		/* exact match		*/
		else {
		    /* If we already have a match and the new match is not
		     * exact, then the abbreviation is ambiguous.
		     */
		    if (match != 0)
		        return (0);
		    else
		        match = entry;
		}
	    }
	}

	do {
	    ip = ip + 1;
	} while (dict[ip-1] != dict[0] && dict[ip] != '\0');
    }

    return (match);
}