table: fixed bug when field length > 128.
[libastrodb.git] / src / readme.c
blobbe5a99b47ac8dbb44fa18fbf03b5870cfca843b7
1 /*
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 */
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include <errno.h>
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;
41 while (pos-- >= 0) {
42 while (*line == ' ' && line < line_end)
43 line++;
45 item_start = line;
46 while (*line != ' ' && line < line_end)
47 line++;
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;
59 int item_size = 0;
61 while (pos-- >= 0) {
62 while (*line == ' ' && line < line_end)
63 line++;
65 item_size = 0;
66 item_start = line;
68 while (*line != ' ' && line < line_end) {
69 line++;
70 item_size++;
74 if (all)
75 return strdup(item_start);
76 else
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];
87 while (lines) {
88 fgets(line, README_LINE_SIZE, f);
89 lines--;
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];
99 char *eof;
100 int i = 0;
102 rewind(f);
103 do {
104 eof = fgets(line, README_LINE_SIZE, f);
106 if (!strncmp(header, line, strlen(header))) {
107 if (i == num) {
108 if (data) {
109 strncpy(data, line + strlen(header) + 1, 80);
110 *(data + strlen(data) - 1) = 0; /* remove cr */
112 return 0;
114 i++;
116 } while (eof != NULL);
118 return -1;
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);
127 if (info == NULL)
128 return -ENOMEM;
130 /* designation is always first line of ReadMe */
131 rewind(f);
132 fgets(info->designation, README_LINE_SIZE, f);
133 return 0;
136 static int get_titles(struct astrodb_readme_info *info, FILE *f)
139 return 0;
142 static int get_keywords(struct astrodb_readme_info *info, FILE *f)
145 return 0;
149 static int get_description(struct astrodb_readme_info *info, FILE *f)
152 return 0;
155 static int get_files(struct astrodb_readme_info *info, FILE *f)
157 char line[README_LINE_SIZE];
158 struct astrodb_table_info *file;
159 int ret;
161 ret = find_header("File Summary:", 0, f, NULL);
162 if (ret < 0) {
163 astrodb_error("failed to find File Summary\n");
164 return -ENODATA;
167 /* read and skip in 3 lines of header */
168 skip_lines(3, f);
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));
174 if (file == NULL)
175 return -ENOMEM;
176 bzero(file, sizeof(struct astrodb_table_info));
178 while (*line == ' ')
179 fgets(line, README_LINE_SIZE, f);
181 file->name = get_string(line, 0, 80, 0);
182 if (file->name == NULL)
183 goto err;
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)
189 goto err;
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);
195 return 0;
196 err:
197 free(file->name);
198 free(file->title);
199 free(file);
200 return -ENOMEM;
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 */
214 skip_lines(3, f);
216 line[0] = 0;
217 while (*line != '-') {
218 desc = calloc(1, sizeof(struct astrodb_table_column_info));
219 if (desc == NULL)
220 return NULL;
222 /* check for line continuation */
223 do {
224 fgets(line, README_LINE_SIZE, f);
225 if (*line == '-') {
226 free(desc);
227 return byte_list;
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 */
236 desc->start -= 1;
237 desc->end -= 1;
239 /* readjust ptr after data positions */
240 line_adj = &line[9];
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);
247 return byte_list;
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)
256 char *name;
257 struct astrodb_dlist *node = info->files;
259 /* find ops entry */
260 name = get_string(names, pos, 80, 0);
261 if (strlen(name) == 0) {
262 free(name);
263 return NULL;
266 /* find pos file */
267 while (node) {
268 if (!strcmp(((struct astrodb_table_info *) node->data)->name, name)) {
269 free(name);
270 return (struct astrodb_table_info *) node->data;
272 node = node->tail;
275 free(name);
276 return NULL;
279 static int get_byte_description(struct astrodb_readme_info * read_me_info, FILE * f)
282 int i = 0, j = 0;
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;
312 //#error match desc
313 return 0;
316 struct astrodb_readme_info *parse_readme(char *file)
318 struct astrodb_readme_info *info;
319 FILE *f;
321 f = fopen(file, "r");
322 if (f == NULL) {
323 astrodb_error("failed to open %s\n", file);
324 return NULL;
327 info = (struct astrodb_readme_info *)
328 calloc(1, sizeof(struct astrodb_readme_info));
329 if (info == NULL) {
330 fclose(f);
331 return NULL;
333 bzero(info, sizeof(struct astrodb_readme_info));
335 get_designation(info, f);
336 get_titles(info, f);
337 get_keywords(info, f);
338 get_description(info, f);
339 get_files(info, f);
340 get_byte_description(info, f);
341 fclose(f);
342 return info;
345 static void free_byte_desc(struct astrodb_table_column_info *b)
347 free(b->type);
348 free(b->units);
349 free(b->label);
350 free(b->explanation);
351 free(b);
354 static void free_byte_descs(struct astrodb_dlist *list)
356 list = astrodb_dlist_head(list);
358 while (list) {
359 struct astrodb_dlist *o;
360 struct astrodb_dlist *s = list->data;
361 while (s) {
362 free_byte_desc(s->data);
363 o = s;
364 s = s->tail;
365 free(o);
367 o = list;
368 list = list->tail;
369 free(o);
373 static void free_file(void *data, void *user)
375 struct astrodb_table_info *file = (struct astrodb_table_info *)data;
377 free(file->name);
378 free(file->title);
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);
397 if (info->titles)
398 free(info->titles);
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);
411 if (info->byte_desc)
412 free_byte_descs(info->byte_desc);
414 free(info);