forked from panda3d/panda3d
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsedAddress.cxx
More file actions
152 lines (130 loc) · 4.18 KB
/
sedAddress.cxx
File metadata and controls
152 lines (130 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Filename: sedAddress.cxx
// Created by: drose (24Oct00)
//
////////////////////////////////////////////////////////////////////
#include "sedAddress.h"
#include "sedContext.h"
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
////////////////////////////////////////////////////////////////////
// Function: SedAddress::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
SedAddress::
SedAddress() {
_address_type = AT_invalid;
}
////////////////////////////////////////////////////////////////////
// Function: SedAddress::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
SedAddress::
~SedAddress() {
if (_address_type == AT_re) {
regfree(&_re);
}
}
////////////////////////////////////////////////////////////////////
// Function: SedAddress::parse_address
// Access: Public
// Description: Scans the indicated string beginning at the indicated
// character position for an address specification,
// e.g. a number, $, or a regular expression. If a
// correct address is found, increments p to the first
// non-whitespace character past it and returns true;
// otherwise, returns false.
////////////////////////////////////////////////////////////////////
bool SedAddress::
parse_address(const string &line, size_t &p) {
assert(p < line.length());
if (line[p] == '$') {
p++;
_address_type = AT_last;
} else if (isdigit(line[p])) {
const char *str = line.c_str() + p;
char *end;
_number = strtol(str, &end, 10);
_address_type = AT_numeric;
p += (end - str);
} else {
// It must be a regular expression.
size_t p0 = p;
char delimiter = line[p];
p++;
if (p < line.length() && delimiter == '\\') {
// A backslash might escape the opening character.
delimiter = line[p];
p++;
}
size_t begin = p;
while (p < line.length() && line[p] != delimiter) {
if (line[p] == '\\') {
p++;
// A backslash could escape the closing character.
}
p++;
}
if (p >= line.length()) {
cerr << "Could not find terminating character '" << delimiter
<< "' in regular expression: " << line.substr(p0) << "\n";
return false;
}
string re = line.substr(begin, p - begin);
p++;
int error = regcomp(&_re, re.c_str(), REG_NOSUB);
if (error != 0) {
static const int errbuf_size = 512;
char errbuf[errbuf_size];
regerror(error, &_re, errbuf, errbuf_size);
cerr << "Invalid regular expression: " << re << "\n"
<< errbuf << "\n";
return false;
}
_address_type = AT_re;
}
// Skip whitespace following the address.
while (p < line.length() && isspace(line[p])) {
p++;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: SedAddress::matches
// Access: Public
// Description: Returns true if this address exactly matches the
// current pattern space.
////////////////////////////////////////////////////////////////////
bool SedAddress::
matches(const SedContext &context) const {
switch (_address_type) {
case AT_invalid:
cerr << "Internal error!\n";
assert(false);
return false;
case AT_numeric:
return (_number == context._line_number);
case AT_last:
return context._is_last_line;
case AT_re:
return (regexec(&_re, context._pattern_space.c_str(), 0, (regmatch_t *)NULL, 0) == 0);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: SedAddress::precedes
// Access: Public
// Description: Returns true if this address exactly matches the
// current line or refers to a previous line. This
// never returns true if the address is a regular
// expression type.
////////////////////////////////////////////////////////////////////
bool SedAddress::
precedes(const SedContext &context) const {
if (_address_type == AT_numeric) {
return (_number <= context._line_number);
}
return false;
}