]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/string.cc
MFC r326276:
[FreeBSD/FreeBSD.git] / usr.bin / dtc / string.cc
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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  * $FreeBSD$
33  */
34
35 #include <string>
36 #include <functional>
37 #include <cstdio>
38 #include <cstdlib>
39 #include <ctype.h>
40 #include <libgen.h>
41
42 #include "util.hh"
43
44 using std::string;
45
46 namespace dtc
47 {
48
49 void
50 push_string(byte_buffer &buffer, const string &s, bool escapes)
51 {
52         size_t length = s.size();
53         for (size_t i=0 ; i<length ; ++i)
54         {
55                 uint8_t c = s[i];
56                 if (escapes && c == '\\' && i+1 < length)
57                 {
58                         c = s[++i];
59                         switch (c)
60                         {
61                                 // For now, we just ignore invalid escape sequences.
62                                 default:
63                                 case '"':
64                                 case '\'':
65                                 case '\\':
66                                         break;
67                                 case 'a':
68                                         c = '\a';
69                                         break;
70                                 case 'b':
71                                         c = '\b';
72                                         break;
73                                 case 't':
74                                         c = '\t';
75                                         break;
76                                 case 'n':
77                                         c = '\n';
78                                         break;
79                                 case 'v':
80                                         c = '\v';
81                                         break;
82                                 case 'f':
83                                         c = '\f';
84                                         break;
85                                 case 'r':
86                                         c = '\r';
87                                         break;
88                                 case '0'...'7':
89                                 {
90                                         int v = digittoint(c);
91                                         if (i+1 < length && s[i+1] <= '7' && s[i+1] >= '0')
92                                         {
93                                                 v <<= 3;
94                                                 v |= digittoint(s[i+1]);
95                                                 i++;
96                                                 if (i+1 < length && s[i+1] <= '7' && s[i+1] >= '0')
97                                                 {
98                                                         v <<= 3;
99                                                         v |= digittoint(s[i+1]);
100                                                 }
101                                         }
102                                         c = (uint8_t)v;
103                                         break;
104                                 }
105                                 case 'x':
106                                 {
107                                         ++i;
108                                         if (i >= length)
109                                         {
110                                                 break;
111                                         }
112                                         int v = digittoint(s[i]);
113                                         if (i+1 < length && ishexdigit(s[i+1]))
114                                         {
115                                                 v <<= 4;
116                                                 v |= digittoint(s[++i]);
117                                         }
118                                         c = (uint8_t)v;
119                                         break;
120                                 }
121                         }
122                 }
123                 buffer.push_back(c);
124         }
125 }
126
127 namespace {
128 string
129 dirbasename(std::function<char*(char*)> fn, const string &s)
130 {
131         if (s == string())
132         {
133                 return string();
134         }
135         std::unique_ptr<char, decltype(free)*> str = {strdup(s.c_str()), free};
136         string dn(fn(str.get()));
137         return dn;
138 }
139 }
140
141 string dirname(const string &s)
142 {
143         return dirbasename(::dirname, s);
144 }
145
146 string basename(const string &s)
147 {
148         return dirbasename(::basename, s);
149 }
150 } // namespace dtc
151