file_reader.c 4 KB
Newer Older
Michel Henry's avatar
Michel Henry committed
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
#include "file_reader.h"
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

struct FileReaderStruct {
  FILE *f;
  char *file_name;
  char line[4096];
  char *pos;
  char *prev;
  long int iline;
};

void file_reader_delete(FileReader *r) {
  fclose(r->f);
  free(r->file_name);
  free(r);
}

void file_reader_error(FileReader *r, const char *msg, ...) {
  printf("Error in file  '%s' : ", r->file_name);
  va_list args;
  va_start(args, msg);
  vprintf(msg,args);
  printf("\n");
  file_reader_delete(r);
  exit(1);
}

void file_reader_error_at(FileReader *r, const char *msg,...) {
  printf("Error in file '%s' line %lu column %lu : ", r->file_name, r->iline+1, r->prev-r->line+1);
  va_list args;
  va_start(args, msg);
  vprintf(msg,args);
  printf("\n");
  printf("%s", r->line);
  while(isblank(*r->prev))r->prev++;
  for (int i = 0; i < (r->prev-r->line);++i) printf(" ");
  printf("^\n");
  file_reader_delete(r);
  exit(1);
}

int file_reader_next_line_or_eof(FileReader *r) {
  r->prev = r->pos;
  if (r->pos){
    while(isblank(*r->pos))r->pos++;
    if (*r->pos != 0 && *r->pos != '\n')
      file_reader_error_at(r,"end of line expected");
  }

  r->iline += 1;
  char *l = fgets(r->line, 4096, r->f);
  if (l == NULL) {
    return 0;
  }
  r->pos = r->line;
  return 1;
}

void file_reader_next_line_skip(FileReader *r) {
  r->prev = r->pos;
  r->iline += 1;
  char *l = fgets(r->line, 4096, r->f);
  if (l == NULL) {
    file_reader_error(r, "Unexpected end of file.");
  }
  r->pos = r->line;
}

void file_reader_next_line(FileReader *r) {
  r->prev = r->pos;
  if (r->pos){
    while(isblank(*r->pos))r->pos++;
    if (*r->pos != 0 && *r->pos != '\n')
      file_reader_error_at(r,"end of line expected");
  }

  r->iline += 1;
  char *l = fgets(r->line, 4096, r->f);
  if (l == NULL) {
    file_reader_error(r, "Unexpected end of file.");
  }
  r->pos = r->line;
}

double file_reader_get_double(FileReader *r) {
  r->prev = r->pos;
  errno = 0;
  double d = strtod(r->pos,&r->pos);
  if (errno != 0)
    file_reader_error_at(r,"expecting a double precision number");
  return d;
}

long file_reader_get_int(FileReader *r) {
  r->prev = r->pos;
  errno = 0;
  long d = strtol(r->pos,&r->pos,0);
  if (errno != 0)
    file_reader_error_at(r,"expecting an integer");
  return d;
}

unsigned long file_reader_get_unsigned_int(FileReader *r) {
  r->prev = r->pos;
  errno = 0;
  unsigned long d = strtoul(r->pos,&r->pos,0);
  if (errno != 0)
    file_reader_error_at(r,"expecting an unsigned integer");
  return d;
}

void file_reader_get_word(FileReader *r, char *txt, int maxl) {
  r->prev = r->pos;
  char *next = r->pos;
  while (isblank(*next)) next += 1;
  int p = 0;
  if (isspace(*next))
    file_reader_error_at(r,"expecting a string");
  while (!isspace(*next)) {
    if (*next == 0)break;
    txt[p++] = *next;
    if(p+1 >= maxl) file_reader_error_at(r,"string is longer than expected");
    next++;
  }
  txt[p] = '\0';
  r->pos = next;
}


void file_reader_get_quoted_string(FileReader *r, char *txt, int maxl) {
  r->prev = r->pos;
  char *next = r->pos;
  while (isblank(*next)) next += 1;
  if (*next != '"') file_reader_error_at(r,"expecting a quoted string");
  int p = 0;
  next++;
  while (*next != '"') {
    if (*next == '\n' || *next == 0) file_reader_error_at(r,"expecting a quoted string");
    txt[p++] = *next;
    if(p+1 >= maxl) file_reader_error_at(r,"quoted string is longer than expected");
    next++;
  }
  next++;
  txt[p] = '\0';
  r->pos = next;
}

void file_reader_assert(FileReader *r, const char *txt) {
  r->prev = r->pos;
  size_t l = strlen(txt);
  if (strncmp(txt, r->pos, l) == 0) {
    r->pos += l;
    return;
  }
  file_reader_error_at(r,"expecting '%s'",txt);
}

FileReader *file_reader_new(const char *file_name) {
  FileReader *r = malloc(sizeof(FileReader));
  r->file_name = strdup(file_name);
  r->f = fopen(file_name,"r");
  if (!r->f) file_reader_error(r,"Cannot open file.");
  r->iline = -1;
  r->pos = NULL;
  file_reader_next_line(r);
  return r;
}