1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2013 David Chisnall
5 * All rights reserved.
6 *
7 * This software was developed by SRI International and the University of
8 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9 * ("CTSRD"), as part of the DARPA CRASH research programme.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <string>
34#include <functional>
35#include <cstdio>
36#include <cstdlib>
37#include <cstring>
38#include <ctype.h>
39#include <libgen.h>
40
41#include "util.hh"
42
43using std::string;
44
45namespace dtc
46{
47
48void
49push_string(byte_buffer &buffer, const string &s, bool escapes)
50{
51	size_t length = s.size();
52	for (size_t i=0 ; i<length ; ++i)
53	{
54		uint8_t c = s[i];
55		if (escapes && c == '\\' && i+1 < length)
56		{
57			c = s[++i];
58			switch (c)
59			{
60				// For now, we just ignore invalid escape sequences.
61				default:
62				case '"':
63				case '\'':
64				case '\\':
65					break;
66				case 'a':
67					c = '\a';
68					break;
69				case 'b':
70					c = '\b';
71					break;
72				case 't':
73					c = '\t';
74					break;
75				case 'n':
76					c = '\n';
77					break;
78				case 'v':
79					c = '\v';
80					break;
81				case 'f':
82					c = '\f';
83					break;
84				case 'r':
85					c = '\r';
86					break;
87				case '0'...'7':
88				{
89					int v = digittoint(c);
90					if (i+1 < length && s[i+1] <= '7' && s[i+1] >= '0')
91					{
92						v <<= 3;
93						v |= digittoint(s[i+1]);
94						i++;
95						if (i+1 < length && s[i+1] <= '7' && s[i+1] >= '0')
96						{
97							v <<= 3;
98							v |= digittoint(s[i+1]);
99						}
100					}
101					c = (uint8_t)v;
102					break;
103				}
104				case 'x':
105				{
106					++i;
107					if (i >= length)
108					{
109						break;
110					}
111					int v = digittoint(s[i]);
112					if (i+1 < length && ishexdigit(s[i+1]))
113					{
114						v <<= 4;
115						v |= digittoint(s[++i]);
116					}
117					c = (uint8_t)v;
118					break;
119				}
120			}
121		}
122		buffer.push_back(c);
123	}
124}
125
126namespace {
127string
128dirbasename(std::function<char*(char*)> fn, const string &s)
129{
130	if (s == string())
131	{
132		return string();
133	}
134	std::unique_ptr<char, decltype(free)*> str = {strdup(s.c_str()), free};
135	string dn(fn(str.get()));
136	return dn;
137}
138}
139
140string dirname(const string &s)
141{
142	return dirbasename(::dirname, s);
143}
144
145string basename(const string &s)
146{
147	return dirbasename(::basename, s);
148}
149} // namespace dtc
150
151