xref: /freebsd/contrib/pkgconf/cli/renderer-msvc.c (revision f9bc005b8ef3b507a5ecbc2d7fe4411ef70eff38)
1 /*
2  * renderer-msvc.c
3  * MSVC library syntax renderer
4  *
5  * SPDX-License-Identifier: pkgconf
6  *
7  * Copyright (c) 2017 pkgconf authors (see AUTHORS).
8  *
9  * Permission to use, copy, modify, and/or distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * This software is provided 'as is' and without any warranty, express or
14  * implied.  In no event shall the authors be liable for any damages arising
15  * from the use of this software.
16  */
17 
18 #include <string.h>
19 #include <stdlib.h>
20 
21 #include <libpkgconf/libpkgconf.h>
22 #include "renderer-msvc.h"
23 
24 static inline bool
25 should_quote(const pkgconf_buffer_t *buf)
26 {
27 	const char *src;
28 
29 	for (src = buf->base; *src && src < buf->end; src++)
30 	{
31 		if (((*src < ' ') ||
32 		    (*src >= (' ') && *src < '$') ||
33 		    (*src > '$' && *src < '(') ||
34 		    (*src > ')' && *src < '+') ||
35 		    (*src > ':' && *src < '=') ||
36 		    (*src > '=' && *src < '@') ||
37 		    (*src > 'Z' && *src < '^') ||
38 		    (*src == '`') ||
39 		    (*src > 'z' && *src < '~') ||
40 		    (*src > '~')))
41 			return true;
42 	}
43 
44 	return false;
45 }
46 
47 static inline bool
48 allowed_fragment(const pkgconf_fragment_t *frag)
49 {
50 	return !(!frag->type || frag->data == NULL || strchr("DILl", frag->type) == NULL);
51 }
52 
53 static void
54 msvc_renderer_render(const pkgconf_fragment_render_ctx_t *ctx, const pkgconf_fragment_t *frag, pkgconf_buffer_t *buf)
55 {
56 	pkgconf_buffer_t tmpbuf = PKGCONF_BUFFER_INITIALIZER;
57 	bool escape = ctx->escape;
58 
59 	if (!allowed_fragment(frag))
60 		return;
61 
62 	switch(frag->type) {
63 	case 'D':
64 	case 'I':
65 		pkgconf_buffer_append_fmt(buf, "/%c", frag->type);
66 		break;
67 	case 'L':
68 		pkgconf_buffer_append(buf, "/libpath:");
69 		break;
70 	}
71 
72 	pkgconf_buffer_append(&tmpbuf, frag->data);
73 
74 	if (frag->type == 'l')
75 		pkgconf_buffer_append(&tmpbuf, ".lib");
76 
77 	escape = should_quote(&tmpbuf);
78 
79 	if (escape)
80 		pkgconf_buffer_push_byte(buf, '"');
81 
82 	pkgconf_buffer_append(buf, pkgconf_buffer_str_or_empty(&tmpbuf));
83 
84 	if (escape)
85 		pkgconf_buffer_push_byte(buf, '"');
86 
87 	pkgconf_buffer_finalize(&tmpbuf);
88 }
89 
90 static pkgconf_fragment_render_ops_t msvc_renderer_ops = {
91 	.render = msvc_renderer_render
92 };
93 
94 pkgconf_fragment_render_ops_t *
95 msvc_renderer_get(void)
96 {
97 	return &msvc_renderer_ops;
98 }
99