summaryrefslogtreecommitdiffstats
path: root/scripts/ksymoops/re.c
blob: 9c65832f734071e7b34f6eaf99917535771dab11 (plain)
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
/*
	re.c.

	Regular expression processing for ksymoops.

	Copyright Keith Owens <kaos@ocs.com.au>.
	Released under the GNU Public Licence, Version 2.

	Tue Nov  3 02:31:01 EST 1998
	Version 0.6
	PPC trace addresses are not bracketed, add new re.

	Wed Oct 28 13:47:23 EST 1998
	Version 0.4
	Split into separate sources.
 */

#include "ksymoops.h"
#include <malloc.h>
#include <string.h>

/* Compile a regular expression */
void re_compile(regex_t *preg, const char *regex, int cflags,
		regmatch_t **pmatch)
{
	int i, l;
	char *p;
	static char const procname[] = "re_compile";

	if (preg->re_nsub)
		return;		/* already compiled */

	if (debug)
		fprintf(stderr, "DEBUG: %s '%s'", procname, regex);
	if ((i = regcomp(preg, regex, cflags))) {
		l = regerror(i, preg, NULL, 0);
		++l;	/* doc is ambiguous, be safe */
		p = malloc(l);
		if (!p)
			malloc_error("regerror text");
		regerror(i, preg, p, l);
		fprintf(stderr,
			"%s: fatal %s error on '%s' - %s\n",
			prefix, procname, regex, p);
		exit(2);
	}
	if (debug)
		fprintf(stderr, " %d sub expression(s)\n", preg->re_nsub);
	/* [0] is entire match, [1] is first substring */
	*pmatch = malloc((preg->re_nsub+1)*sizeof(**pmatch));
	if (!*pmatch)
		malloc_error("pmatch");

}

/* Compile common regular expressions */
void re_compile_common(void)
{

	/* nm: address, type, symbol */
	re_compile(&re_nm,
		"^([0-9a-fA-F]{4,}) +([^ ]) +([^ ]+)$",
		REG_NEWLINE|REG_EXTENDED,
		&re_nm_pmatch);

	/* bracketed address preceded by optional white space */
	re_compile(&re_bracketed_address,
		"^[ \t]*" BRACKETED_ADDRESS,
		REG_NEWLINE|REG_EXTENDED,
		&re_bracketed_address_pmatch);

	/* unbracketed address preceded by optional white space */
	re_compile(&re_unbracketed_address,
		"^[ \t*]*" UNBRACKETED_ADDRESS,
		REG_NEWLINE|REG_EXTENDED,
		&re_unbracketed_address_pmatch);

}

/* Split text into the matching re substrings - Perl is so much easier :).
 * Each element of *string is set to a malloced copy of the substring or
 * NULL if the substring did not match (undef).  A zero length substring match
 * is represented by a zero length **string.
 */
void re_strings(regex_t *preg, const char *text, regmatch_t *pmatch,
		char ***string)
{
	int i;
	if (!*string) {
		*string = malloc((preg->re_nsub+1)*sizeof(**string));
		if (!*string)
			malloc_error("re_strings base");
		for (i = 0; i < preg->re_nsub+1; ++i)
			(*string)[i] = NULL;
	}
	for (i = 0; i < preg->re_nsub+1; ++i) {
		if (debug > 4)
			fprintf(stderr,
				"DEBUG: re_string %d offsets %d %d",
				i, pmatch[i].rm_so, pmatch[i].rm_eo);
		if (pmatch[i].rm_so == -1) {
			/* no match for this sub expression */
			free((*string)[i]);
			(*string)[i] = NULL;
			if (debug > 4)
				fprintf(stderr, " (undef)\n");
		}
		else {
			int l = pmatch[i].rm_eo - pmatch[i].rm_so + 1;
			char *p;
			p = malloc(l);
			if (!p)
				malloc_error("re_strings");
			strncpy(p, text+pmatch[i].rm_so, l-1);
			*(p+l-1) = '\0';
			(*string)[i] = p;
			if (debug > 4)
				fprintf(stderr, " '%s'\n", p);
		}
	}
}

/* Free the matching re substrings */
void re_strings_free(const regex_t *preg, char ***string)
{
	if (*string) {
		int i;
		for (i = 0; i < preg->re_nsub+1; ++i)
			free((*string)[i]);
		free(*string);
		*string = NULL;
	}
}

/* Check that there are enough strings for an re */
void re_string_check(int need, int available, const char *msg)
{
	if (need > available) {
		fprintf(stderr,
			"%s: fatal not enough re_strings in %s.  "
			"Need %d, available %d\n",
			prefix, msg, need, available);
		exit(2);
	}
}