5
5
#include <sys/mman.h>
6
6
#include <sys/stat.h>
7
7
8
+ #define MIN (x ,y ) ((x) < (y) ? (x) : (y))
9
+
8
10
#define PAGE_SIZE 512
9
11
10
12
typedef enum
11
13
{
12
- NONE ,
13
- HEADER ,
14
-
15
- BOLD ,
16
- UNDERLINE ,
17
- ITALIC ,
18
-
19
- LIST_ITEM ,
20
- UNORDERED_LIST_ITEM ,
21
-
22
- HEADING_1 ,
23
- HEADING_2 ,
24
- HEADING_3 ,
25
- HEADING_4 ,
26
- HEADING_5 ,
27
- HEADING_6 ,
14
+ NONE = 0 ,
15
+ HEADER = 1 ,
16
+
17
+ BOLD = 2 ,
18
+ UNDERLINE = 3 ,
19
+ ITALIC = 4 ,
20
+
21
+ LIST_ITEM_1 = 5 ,
22
+ LIST_ITEM_2 = 6 ,
23
+ LIST_ITEM_3 = 7 ,
24
+ LIST_ITEM_4 = 8 ,
25
+ UNORDERED_LIST_ITEM_1 = 9 ,
26
+ UNORDERED_LIST_ITEM_2 = 10 ,
27
+ UNORDERED_LIST_ITEM_3 = 11 ,
28
+ UNORDERED_LIST_ITEM_4 = 12 ,
29
+
30
+ HEADING_1 = 13 ,
31
+ HEADING_2 = 14 ,
32
+ HEADING_3 = 15 ,
33
+ HEADING_4 = 16 ,
34
+ HEADING_5 = 17 ,
35
+ HEADING_6 = 18 ,
28
36
29
37
LINK ,
30
38
CODE ,
@@ -41,6 +49,7 @@ typedef struct {
41
49
typedef struct
42
50
{
43
51
char * author ;
52
+ char * matriculation_number ;
44
53
char * date ;
45
54
} DocInfo ;
46
55
@@ -104,6 +113,9 @@ parse_header (Element *header_element, DocInfo *info)
104
113
} else if (strncmp (c , "author" , 6 ) == 0 ) {
105
114
dest = & info -> author ;
106
115
c += 6 ;
116
+ } else if (strncmp (c , "matriculation_number" , 20 )) {
117
+ dest = & info -> matriculation_number ;
118
+ c += 20 ;
107
119
}
108
120
109
121
if (* c != '"' )
@@ -148,21 +160,48 @@ parse_header (Element *header_element, DocInfo *info)
148
160
return 1 ;
149
161
}
150
162
163
+ /**
164
+ * Checks if only whitespaces preceed that character by returning
165
+ * the number of whitespace characters before \n + 1, so you can check
166
+ * for truthiness, but have to subtract 1 if you need the number of
167
+ * whitespaces
168
+ *
169
+ * @param start Start of the char buffer
170
+ * @param c Current character
171
+ */
172
+ int
173
+ is_start_of_line (char * start , char * c )
174
+ {
175
+ int index = 0 ;
176
+
177
+ while ((c - index ) != start ) {
178
+ index ++ ;
179
+
180
+ if (* (c - index ) == '\n' )
181
+ return index ;
182
+
183
+ if (* (c - index ) != ' ' && * (c - index ) != '\t' )
184
+ return 0 ;
185
+ }
186
+
187
+ return index ;
188
+ }
189
+
151
190
int
152
- parse (int fd , int len , const char * error )
191
+ parse (int fd , int len , const char * * error )
153
192
{
154
193
char * c , * file ;
155
194
DocInfo doc_info ;
156
195
Token current_token ;
157
196
Element * list ;
158
197
Element * current_element ;
159
- int is_start_of_line = 1 , row , col ;
198
+ int row , col ;
160
199
161
200
#define next_element () \
162
201
current_element++; \
163
202
current_element->data = c; \
164
203
if (!current_element) { \
165
- error = "Max elements exceeded"; \
204
+ * error = "Max elements exceeded"; \
166
205
return 0; \
167
206
}
168
207
@@ -176,6 +215,7 @@ parse (int fd, int len, const char *error)
176
215
}
177
216
178
217
#define next_char () advance_char (&c, &col, &row)
218
+ #define is_start () is_start_of_line (file, c)
179
219
180
220
list = (Element * ) calloc (PAGE_SIZE , sizeof (Element ));
181
221
current_element = list ;
@@ -188,9 +228,6 @@ parse (int fd, int len, const char *error)
188
228
return 0 ;
189
229
190
230
do {
191
- if (is_start_of_line )
192
- skip_whitespaces ();
193
-
194
231
switch (* c ) {
195
232
case '{' :
196
233
// only parse if it's the very first element
@@ -204,7 +241,7 @@ parse (int fd, int len, const char *error)
204
241
205
242
while (next_char () != '}' ) {
206
243
if (* c == '\0' ) {
207
- error = "Header not terminated" ;
244
+ * error = "Header not terminated" ;
208
245
return 0 ;
209
246
}
210
247
@@ -220,7 +257,7 @@ parse (int fd, int len, const char *error)
220
257
char * linebreak , * cur , * ret , * prev ;
221
258
int prev_len ;
222
259
223
- if (!is_start_of_line )
260
+ if (!is_start () )
224
261
break ;
225
262
226
263
if (current_element -> len < 1 )
@@ -255,30 +292,35 @@ parse (int fd, int len, const char *error)
255
292
}
256
293
break ;
257
294
case '*' :
258
- finish_none_element ();
295
+ {
296
+ int whitespaces ;
259
297
260
- if (is_start_of_line ) {
261
- current_element -> type = LIST_ITEM ;
262
- next_char ();
263
- skip_whitespaces ();
264
- next_element ();
265
- } else {
266
- current_element -> type = BOLD ;
267
- current_element -> data = c + 1 ;
298
+ finish_none_element ();
268
299
269
- while (next_char () != '*' ) {
270
- if (!* c ) {
271
- error = "Bold not terminated" ;
272
- return 0 ;
300
+ if ((whitespaces = is_start ())) {
301
+ int index = 0 ;
302
+
303
+ current_element -> type = LIST_ITEM_1 + MIN (whitespaces - 1 , 3 );
304
+ next_char ();
305
+ skip_whitespaces ();
306
+ next_element ();
307
+ } else {
308
+ current_element -> type = BOLD ;
309
+ current_element -> data = c + 1 ;
310
+
311
+ while (next_char () != '*' ) {
312
+ if (!* c ) {
313
+ * error = "Bold not terminated" ;
314
+ return 0 ;
315
+ }
316
+
317
+ current_element -> len ++ ;
273
318
}
274
319
275
- current_element -> len ++ ;
320
+ next_char ();
321
+ next_element ();
276
322
}
277
-
278
- next_char ();
279
- next_element ();
280
323
}
281
-
282
324
break ;
283
325
case '`' :
284
326
finish_none_element ();
@@ -297,7 +339,7 @@ parse (int fd, int len, const char *error)
297
339
298
340
while (next_char () != '`' ) {
299
341
if (!* c ) {
300
- error = "Code literal not terminated" ;
342
+ * error = "Code literal not terminated" ;
301
343
return 0 ;
302
344
}
303
345
@@ -315,7 +357,7 @@ parse (int fd, int len, const char *error)
315
357
316
358
while (next_char () != '$' ) {
317
359
if (!* c ) {
318
- error = "Math literal not terminated" ;
360
+ * error = "Math literal not terminated" ;
319
361
return 0 ;
320
362
}
321
363
@@ -329,7 +371,7 @@ parse (int fd, int len, const char *error)
329
371
case '#' :
330
372
finish_none_element ();
331
373
332
- if (is_start_of_line ) {
374
+ if (is_start () ) {
333
375
current_element -> type = HEADING_1 ;
334
376
while (next_char () == '#' )
335
377
(* (int * ) (& current_element -> type ))++ ;
@@ -353,7 +395,7 @@ parse (int fd, int len, const char *error)
353
395
354
396
while (next_char () != '_' ) {
355
397
if (!* c ) {
356
- error = "Italic not terminated" ;
398
+ * error = "Italic not terminated" ;
357
399
return 0 ;
358
400
}
359
401
@@ -367,16 +409,14 @@ parse (int fd, int len, const char *error)
367
409
current_element -> len ++ ;
368
410
break ;
369
411
}
370
-
371
- is_start_of_line = * c == '\n' ;
372
412
} while (next_char ());
373
413
374
414
finish_none_element ();
375
415
376
416
// if first element is header parse it and fill our doc info
377
417
if (list -> type == HEADER ) {
378
418
if (!parse_header (list , & doc_info )) {
379
- error = "Malformed document header" ;
419
+ * error = "Malformed document header" ;
380
420
return 0 ;
381
421
}
382
422
}
@@ -400,8 +440,11 @@ main (int argc, char **argv)
400
440
char * path ;
401
441
int fd ;
402
442
struct stat st ;
403
- char error [512 ];
404
-
443
+ // const char error[512];
444
+ const char * error ;
445
+
446
+ error = malloc (512 );
447
+
405
448
path = argv [1 ];
406
449
407
450
if (!path )
@@ -419,7 +462,7 @@ main (int argc, char **argv)
419
462
exit (1 );
420
463
}
421
464
422
- if (!parse (fd , st .st_size , error )) {
465
+ if (!parse (fd , st .st_size , & error )) {
423
466
fprintf (stderr , "Parsing failed: %s\n" , error );
424
467
exit (1 );
425
468
}
0 commit comments