xref: /freebsd/contrib/pkgconf/libpkgconf/fileio.c (revision a3cefe7f2b4df0f70ff92d4570ce18e517af43ec)
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