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