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