2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) any later version.
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) 2008 Liam Girdwood
19 #define _GNU_SOURCE /* needed for strndup */
27 #include <libastrodb/astrodb.h>
28 #include <libastrodb/readme.h>
29 #include <libastrodb/adbstdio.h>
31 #define README_LINE_SIZE 80 + 2
33 /*! \fn static int get_int (char* line, int pos, int line_size)
34 * \brief Get int in string at pos
36 static int get_int(char *line
, int pos
, int line_size
)
38 char *item_start
= NULL
;
39 char *line_end
= line
+ line_size
;
42 while (*line
== ' ' && line
< line_end
)
46 while (*line
!= ' ' && line
< line_end
)
49 return strtol(item_start
, NULL
, 10);
52 /*! \fn static char* get_string (char* line, int pos, int line_size, int all)
53 * \brief Get space delimated string at position.
55 static char *get_string(char *line
, int pos
, int line_size
, int all
)
57 char *item_start
= NULL
;
58 char *line_end
= line
+ line_size
;
62 while (*line
== ' ' && line
< line_end
)
68 while (*line
!= ' ' && line
< line_end
) {
75 return strdup(item_start
);
77 return strndup(item_start
, item_size
);
80 /*! \fn static void skip_lines (int lines, FILE* f)
81 * \brief Read a line of text from F
83 static void skip_lines(int lines
, FILE *f
)
85 char line
[README_LINE_SIZE
];
88 fgets(line
, README_LINE_SIZE
, f
);
93 /*! \fn static int find_header(char* header, int num, FILE* f, char* data)
94 * \brief Find section header <num>
96 static int find_header(char *header
, int num
, FILE *f
, char *data
)
98 char line
[README_LINE_SIZE
];
104 eof
= fgets(line
, README_LINE_SIZE
, f
);
106 if (!strncmp(header
, line
, strlen(header
))) {
109 strncpy(data
, line
+ strlen(header
) + 1, 80);
110 *(data
+ strlen(data
) - 1) = 0; /* remove cr */
116 } while (eof
!= NULL
);
121 /*! \fn static int get_designation(astrodb_readme_info* info, FILE* f)
122 * \brief Get catalog designation
124 static int get_designation(struct astrodb_readme_info
*info
, FILE *f
)
126 info
->designation
= calloc(1, README_LINE_SIZE
);
130 /* designation is always first line of ReadMe */
132 fgets(info
->designation
, README_LINE_SIZE
, f
);
136 static int get_titles(struct astrodb_readme_info
*info
, FILE *f
)
142 static int get_keywords(struct astrodb_readme_info
*info
, FILE *f
)
149 static int get_description(struct astrodb_readme_info
*info
, FILE *f
)
155 static int get_files(struct astrodb_readme_info
*info
, FILE *f
)
157 char line
[README_LINE_SIZE
];
158 struct astrodb_table_info
*file
;
161 ret
= find_header("File Summary:", 0, f
, NULL
);
163 astrodb_error("failed to find File Summary\n");
167 /* read and skip in 3 lines of header */
169 bzero(line
, README_LINE_SIZE
);
170 fgets(line
, README_LINE_SIZE
, f
);
172 while (*line
!= '-') {
173 file
= calloc(1, sizeof(struct astrodb_table_info
));
176 bzero(file
, sizeof(struct astrodb_table_info
));
179 fgets(line
, README_LINE_SIZE
, f
);
181 file
->name
= get_string(line
, 0, 80, 0);
182 if (file
->name
== NULL
)
185 file
->records
= get_int(line
, 2, 80);
186 file
->length
= get_int(line
, 1, 80);
187 file
->title
= get_string(line
, 3, 80, 1);
188 if (file
->title
== NULL
)
191 info
->files
= astrodb_dlist_append(info
->files
, (char *)file
);
192 fgets(line
, README_LINE_SIZE
, f
);
194 info
->files
= astrodb_dlist_head(info
->files
);
203 /*! \fn static astrodb_dlist* get_byte_desc(FILE* f)
204 * \brief Parse a byte by byte description
206 static struct astrodb_dlist
*get_byte_desc(FILE *f
)
208 char line
[README_LINE_SIZE
];
209 char *line_adj
= NULL
;
210 struct astrodb_table_column_info
*desc
= NULL
;
211 struct astrodb_dlist
*byte_list
= NULL
;
213 /* read in 3 line header */
217 while (*line
!= '-') {
218 desc
= calloc(1, sizeof(struct astrodb_table_column_info
));
222 /* check for line continuation */
224 fgets(line
, README_LINE_SIZE
, f
);
229 desc
->start
= get_int(line
, 0, 80);
230 /* get the end, no space ! */
231 desc
->end
= get_int(&line
[5], 0, 75);
233 } while (desc
->start
== 0 && desc
->end
== 0);
235 /* subtract 1 from start and end to align */
239 /* readjust ptr after data positions */
241 desc
->type
= get_string(line_adj
, 0, 80, 0);
242 desc
->units
= get_string(line_adj
, 1, 80, 0);
243 desc
->label
= get_string(line_adj
, 2, 80, 0);
244 desc
->explanation
= get_string(line_adj
, 3, 80, 1);
245 byte_list
= astrodb_dlist_append(byte_list
, (char *) desc
);
250 /*! \fn static astrodb_table_info* get_file_data(astrodb_readme_info* info, char* names, int pos)
251 * \brief Get a astrodb_table_info* from a file name
253 static struct astrodb_table_info
*
254 get_file_data(struct astrodb_readme_info
*info
, char *names
, int pos
)
257 struct astrodb_dlist
*node
= info
->files
;
260 name
= get_string(names
, pos
, 80, 0);
261 if (strlen(name
) == 0) {
268 if (!strcmp(((struct astrodb_table_info
*) node
->data
)->name
, name
)) {
270 return (struct astrodb_table_info
*) node
->data
;
279 static int get_byte_description(struct astrodb_readme_info
* read_me_info
, FILE * f
)
283 char files
[README_LINE_SIZE
];
284 struct astrodb_table_info
*read_me_file
;
285 struct astrodb_dlist
*desc
;
287 for (i
= 0; !find_header("Byte-by-byte Description of file:", i
, f
, files
); i
++) {
289 desc
= get_byte_desc(f
);
290 desc
= astrodb_dlist_head(desc
);
292 read_me_info
->byte_desc
=
293 astrodb_dlist_append(read_me_info
->byte_desc
, desc
);
295 for (j
= 0; (read_me_file
= get_file_data(read_me_info
, files
, j
)) != NULL
; j
++) {
296 read_me_file
->byte_description
= desc
;
300 for (i
= 0; !find_header("Byte-per-byte Description of file:", i
, f
, files
); i
++) {
302 desc
= get_byte_desc(f
);
303 desc
= astrodb_dlist_head(desc
);
305 read_me_info
->byte_desc
=
306 astrodb_dlist_append(read_me_info
->byte_desc
, desc
);
308 for (j
= 0; (read_me_file
= get_file_data(read_me_info
, files
, j
)) != NULL
; j
++) {
309 read_me_file
->byte_description
= desc
;
316 struct astrodb_readme_info
*parse_readme(char *file
)
318 struct astrodb_readme_info
*info
;
321 f
= fopen(file
, "r");
323 astrodb_error("failed to open %s\n", file
);
327 info
= (struct astrodb_readme_info
*)
328 calloc(1, sizeof(struct astrodb_readme_info
));
333 bzero(info
, sizeof(struct astrodb_readme_info
));
335 get_designation(info
, f
);
337 get_keywords(info
, f
);
338 get_description(info
, f
);
340 get_byte_description(info
, f
);
345 static void free_byte_desc(struct astrodb_table_column_info
*b
)
350 free(b
->explanation
);
354 static void free_byte_descs(struct astrodb_dlist
*list
)
356 list
= astrodb_dlist_head(list
);
359 struct astrodb_dlist
*o
;
360 struct astrodb_dlist
*s
= list
->data
;
362 free_byte_desc(s
->data
);
373 static void free_file(void *data
, void *user
)
375 struct astrodb_table_info
*file
= (struct astrodb_table_info
*)data
;
381 static void free_note(void *data
, void *user
)
386 static void free_keyword(void *data
, void *user
)
391 void free_readme(struct astrodb_readme_info
*info
)
393 struct astrodb_dlist
*head
;
395 if (info
->designation
)
396 free(info
->designation
);
399 if (info
->description
)
400 free(info
->description
);
402 if ((head
= info
->files
) != NULL
)
403 astrodb_dlist_foreach_free(head
, free_file
, NULL
);
405 if ((head
= info
->keywords
) != NULL
)
406 astrodb_dlist_foreach_free(head
, free_keyword
, NULL
);
408 if ((head
= info
->notes
) != NULL
)
409 astrodb_dlist_foreach_free(head
, free_note
, NULL
);
412 free_byte_descs(info
->byte_desc
);