1 /*
2 * fileio.c
3 * File reading utilities
4 *
5 * Copyright (c) 2012, 2025 pkgconf authors (see AUTHORS).
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * This software is provided 'as is' and without any warranty, express or
12 * implied. In no event shall the authors be liable for any damages arising
13 * from the use of this software.
14 */
15
16 #include <libpkgconf/stdinc.h>
17 #include <libpkgconf/libpkgconf.h>
18
19 bool
pkgconf_fgetline(pkgconf_buffer_t * buffer,FILE * stream)20 pkgconf_fgetline(pkgconf_buffer_t *buffer, FILE *stream)
21 {
22 bool quoted = false;
23 int c = '\0', c2;
24
25 while ((c = getc(stream)) != EOF)
26 {
27 if (c == '\\' && !quoted)
28 {
29 quoted = true;
30 continue;
31 }
32 else if (c == '#')
33 {
34 if (!quoted) {
35 /* Skip the rest of the line */
36 do {
37 c = getc(stream);
38 } while (c != '\n' && c != EOF);
39 pkgconf_buffer_push_byte(buffer, c);
40 break;
41 }
42 else
43 pkgconf_buffer_push_byte(buffer, c);
44
45 quoted = false;
46 continue;
47 }
48 else if (c == '\n')
49 {
50 if (quoted)
51 {
52 /* Trim spaces */
53 do {
54 c2 = getc(stream);
55 } while (c2 == '\t' || c2 == ' ');
56
57 ungetc(c2, stream);
58
59 quoted = false;
60 continue;
61 }
62 else
63 {
64 pkgconf_buffer_push_byte(buffer, c);
65 }
66
67 break;
68 }
69 else if (c == '\r')
70 {
71 pkgconf_buffer_push_byte(buffer, '\n');
72
73 if ((c2 = getc(stream)) == '\n')
74 {
75 if (quoted)
76 {
77 quoted = false;
78 continue;
79 }
80
81 break;
82 }
83
84 ungetc(c2, stream);
85
86 if (quoted)
87 {
88 quoted = false;
89 continue;
90 }
91
92 break;
93 }
94 else
95 {
96 if (quoted) {
97 pkgconf_buffer_push_byte(buffer, '\\');
98 quoted = false;
99 }
100 pkgconf_buffer_push_byte(buffer, c);
101 }
102
103 }
104
105 /* Remove newline character. */
106 if (pkgconf_buffer_lastc(buffer) == '\n')
107 pkgconf_buffer_trim_byte(buffer);
108
109 if (pkgconf_buffer_lastc(buffer) == '\r')
110 pkgconf_buffer_trim_byte(buffer);
111
112 return !(c == EOF || ferror(stream));
113 }
114