xref: /freebsd/contrib/pkgconf/cli/renderer-msvc.c (revision a3cefe7f2b4df0f70ff92d4570ce18e517af43ec)
1*a3cefe7fSPierre Pronchery /*
2*a3cefe7fSPierre Pronchery  * renderer-msvc.c
3*a3cefe7fSPierre Pronchery  * MSVC library syntax renderer
4*a3cefe7fSPierre Pronchery  *
5*a3cefe7fSPierre Pronchery  * Copyright (c) 2017 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 <string.h>
17*a3cefe7fSPierre Pronchery #include <stdlib.h>
18*a3cefe7fSPierre Pronchery 
19*a3cefe7fSPierre Pronchery #include <libpkgconf/libpkgconf.h>
20*a3cefe7fSPierre Pronchery #include "renderer-msvc.h"
21*a3cefe7fSPierre Pronchery 
22*a3cefe7fSPierre Pronchery static inline bool
fragment_should_quote(const pkgconf_fragment_t * frag)23*a3cefe7fSPierre Pronchery fragment_should_quote(const pkgconf_fragment_t *frag)
24*a3cefe7fSPierre Pronchery {
25*a3cefe7fSPierre Pronchery 	const char *src;
26*a3cefe7fSPierre Pronchery 
27*a3cefe7fSPierre Pronchery 	if (frag->data == NULL)
28*a3cefe7fSPierre Pronchery 		return false;
29*a3cefe7fSPierre Pronchery 
30*a3cefe7fSPierre Pronchery 	for (src = frag->data; *src; src++)
31*a3cefe7fSPierre Pronchery 	{
32*a3cefe7fSPierre Pronchery 		if (((*src < ' ') ||
33*a3cefe7fSPierre Pronchery 		    (*src >= (' ' + (frag->children.head != NULL ? 1 : 0)) && *src < '$') ||
34*a3cefe7fSPierre Pronchery 		    (*src > '$' && *src < '(') ||
35*a3cefe7fSPierre Pronchery 		    (*src > ')' && *src < '+') ||
36*a3cefe7fSPierre Pronchery 		    (*src > ':' && *src < '=') ||
37*a3cefe7fSPierre Pronchery 		    (*src > '=' && *src < '@') ||
38*a3cefe7fSPierre Pronchery 		    (*src > 'Z' && *src < '^') ||
39*a3cefe7fSPierre Pronchery 		    (*src == '`') ||
40*a3cefe7fSPierre Pronchery 		    (*src > 'z' && *src < '~') ||
41*a3cefe7fSPierre Pronchery 		    (*src > '~')))
42*a3cefe7fSPierre Pronchery 			return true;
43*a3cefe7fSPierre Pronchery 	}
44*a3cefe7fSPierre Pronchery 
45*a3cefe7fSPierre Pronchery 	return false;
46*a3cefe7fSPierre Pronchery }
47*a3cefe7fSPierre Pronchery 
48*a3cefe7fSPierre Pronchery static inline size_t
fragment_len(const pkgconf_fragment_t * frag)49*a3cefe7fSPierre Pronchery fragment_len(const pkgconf_fragment_t *frag)
50*a3cefe7fSPierre Pronchery {
51*a3cefe7fSPierre Pronchery 	size_t len = 1;
52*a3cefe7fSPierre Pronchery 
53*a3cefe7fSPierre Pronchery 	if (frag->type)
54*a3cefe7fSPierre Pronchery 		len += 2;
55*a3cefe7fSPierre Pronchery 
56*a3cefe7fSPierre Pronchery 	if (frag->data != NULL)
57*a3cefe7fSPierre Pronchery 	{
58*a3cefe7fSPierre Pronchery 		len += strlen(frag->data);
59*a3cefe7fSPierre Pronchery 
60*a3cefe7fSPierre Pronchery 		if (fragment_should_quote(frag))
61*a3cefe7fSPierre Pronchery 			len += 2;
62*a3cefe7fSPierre Pronchery 	}
63*a3cefe7fSPierre Pronchery 
64*a3cefe7fSPierre Pronchery 	return len;
65*a3cefe7fSPierre Pronchery }
66*a3cefe7fSPierre Pronchery 
67*a3cefe7fSPierre Pronchery static inline bool
allowed_fragment(const pkgconf_fragment_t * frag)68*a3cefe7fSPierre Pronchery allowed_fragment(const pkgconf_fragment_t *frag)
69*a3cefe7fSPierre Pronchery {
70*a3cefe7fSPierre Pronchery 	return !(!frag->type || frag->data == NULL || strchr("DILl", frag->type) == NULL);
71*a3cefe7fSPierre Pronchery }
72*a3cefe7fSPierre Pronchery 
73*a3cefe7fSPierre Pronchery static size_t
msvc_renderer_render_len(const pkgconf_list_t * list,bool escape)74*a3cefe7fSPierre Pronchery msvc_renderer_render_len(const pkgconf_list_t *list, bool escape)
75*a3cefe7fSPierre Pronchery {
76*a3cefe7fSPierre Pronchery 	(void) escape;
77*a3cefe7fSPierre Pronchery 
78*a3cefe7fSPierre Pronchery 	size_t out = 1;		/* trailing nul */
79*a3cefe7fSPierre Pronchery 	pkgconf_node_t *node;
80*a3cefe7fSPierre Pronchery 
81*a3cefe7fSPierre Pronchery 	PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
82*a3cefe7fSPierre Pronchery 	{
83*a3cefe7fSPierre Pronchery 		const pkgconf_fragment_t *frag = node->data;
84*a3cefe7fSPierre Pronchery 
85*a3cefe7fSPierre Pronchery 		if (!allowed_fragment(frag))
86*a3cefe7fSPierre Pronchery 			continue;
87*a3cefe7fSPierre Pronchery 
88*a3cefe7fSPierre Pronchery 		switch (frag->type)
89*a3cefe7fSPierre Pronchery 		{
90*a3cefe7fSPierre Pronchery 			case 'L':
91*a3cefe7fSPierre Pronchery 				out += 9; /* "/libpath:" */
92*a3cefe7fSPierre Pronchery 				break;
93*a3cefe7fSPierre Pronchery 			case 'l':
94*a3cefe7fSPierre Pronchery 				out += 4; /* ".lib" */
95*a3cefe7fSPierre Pronchery 				break;
96*a3cefe7fSPierre Pronchery 			default:
97*a3cefe7fSPierre Pronchery 				break;
98*a3cefe7fSPierre Pronchery 		}
99*a3cefe7fSPierre Pronchery 
100*a3cefe7fSPierre Pronchery 		out += fragment_len(frag);
101*a3cefe7fSPierre Pronchery 	}
102*a3cefe7fSPierre Pronchery 
103*a3cefe7fSPierre Pronchery 	return out;
104*a3cefe7fSPierre Pronchery }
105*a3cefe7fSPierre Pronchery 
106*a3cefe7fSPierre Pronchery static void
msvc_renderer_render_buf(const pkgconf_list_t * list,char * buf,size_t buflen,bool escape)107*a3cefe7fSPierre Pronchery msvc_renderer_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape)
108*a3cefe7fSPierre Pronchery {
109*a3cefe7fSPierre Pronchery 	pkgconf_node_t *node;
110*a3cefe7fSPierre Pronchery 	char *bptr = buf;
111*a3cefe7fSPierre Pronchery 
112*a3cefe7fSPierre Pronchery 	memset(buf, 0, buflen);
113*a3cefe7fSPierre Pronchery 
114*a3cefe7fSPierre Pronchery 	PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
115*a3cefe7fSPierre Pronchery 	{
116*a3cefe7fSPierre Pronchery 		const pkgconf_fragment_t *frag = node->data;
117*a3cefe7fSPierre Pronchery 		size_t buf_remaining = buflen - (bptr - buf);
118*a3cefe7fSPierre Pronchery 		size_t cnt;
119*a3cefe7fSPierre Pronchery 
120*a3cefe7fSPierre Pronchery 		if (!allowed_fragment(frag))
121*a3cefe7fSPierre Pronchery 			continue;
122*a3cefe7fSPierre Pronchery 
123*a3cefe7fSPierre Pronchery 		if (fragment_len(frag) > buf_remaining)
124*a3cefe7fSPierre Pronchery 			break;
125*a3cefe7fSPierre Pronchery 
126*a3cefe7fSPierre Pronchery 		switch(frag->type) {
127*a3cefe7fSPierre Pronchery 		case 'D':
128*a3cefe7fSPierre Pronchery 		case 'I':
129*a3cefe7fSPierre Pronchery 			*bptr++ = '/';
130*a3cefe7fSPierre Pronchery 			*bptr++ = frag->type;
131*a3cefe7fSPierre Pronchery 			break;
132*a3cefe7fSPierre Pronchery 		case 'L':
133*a3cefe7fSPierre Pronchery 			cnt = pkgconf_strlcpy(bptr, "/libpath:", buf_remaining);
134*a3cefe7fSPierre Pronchery 			bptr += cnt;
135*a3cefe7fSPierre Pronchery 			buf_remaining -= cnt;
136*a3cefe7fSPierre Pronchery 			break;
137*a3cefe7fSPierre Pronchery 		}
138*a3cefe7fSPierre Pronchery 
139*a3cefe7fSPierre Pronchery 		escape = fragment_should_quote(frag);
140*a3cefe7fSPierre Pronchery 
141*a3cefe7fSPierre Pronchery 		if (escape)
142*a3cefe7fSPierre Pronchery 			*bptr++ = '"';
143*a3cefe7fSPierre Pronchery 
144*a3cefe7fSPierre Pronchery 		cnt = pkgconf_strlcpy(bptr, frag->data, buf_remaining);
145*a3cefe7fSPierre Pronchery 		bptr += cnt;
146*a3cefe7fSPierre Pronchery 		buf_remaining -= cnt;
147*a3cefe7fSPierre Pronchery 
148*a3cefe7fSPierre Pronchery 		if (frag->type == 'l')
149*a3cefe7fSPierre Pronchery 		{
150*a3cefe7fSPierre Pronchery 			cnt = pkgconf_strlcpy(bptr, ".lib", buf_remaining);
151*a3cefe7fSPierre Pronchery 			bptr += cnt;
152*a3cefe7fSPierre Pronchery 		}
153*a3cefe7fSPierre Pronchery 
154*a3cefe7fSPierre Pronchery 		if (escape)
155*a3cefe7fSPierre Pronchery 			*bptr++ = '"';
156*a3cefe7fSPierre Pronchery 
157*a3cefe7fSPierre Pronchery 		*bptr++ = ' ';
158*a3cefe7fSPierre Pronchery 	}
159*a3cefe7fSPierre Pronchery 
160*a3cefe7fSPierre Pronchery 	*bptr = '\0';
161*a3cefe7fSPierre Pronchery }
162*a3cefe7fSPierre Pronchery 
163*a3cefe7fSPierre Pronchery static const pkgconf_fragment_render_ops_t msvc_renderer_ops = {
164*a3cefe7fSPierre Pronchery 	.render_len = msvc_renderer_render_len,
165*a3cefe7fSPierre Pronchery 	.render_buf = msvc_renderer_render_buf
166*a3cefe7fSPierre Pronchery };
167*a3cefe7fSPierre Pronchery 
168*a3cefe7fSPierre Pronchery const pkgconf_fragment_render_ops_t *
msvc_renderer_get(void)169*a3cefe7fSPierre Pronchery msvc_renderer_get(void)
170*a3cefe7fSPierre Pronchery {
171*a3cefe7fSPierre Pronchery 	return &msvc_renderer_ops;
172*a3cefe7fSPierre Pronchery }
173