aboutsummaryrefslogtreecommitdiff
path: root/pkg/system/match.x
blob: b9f8feb2343df80a0194952a5554554fa509f905 (plain) (blame)
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
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<pattern.h>
include	<ctype.h>

# MATCH -- Search for the indicated pattern in each line of a file or files,
# passing or stopping only those lines which contain the pattern.

procedure t_match()

bool	stop_matched_lines		# pass or stop matched lines?
char	chset[2]
int	fd, list
pointer	sp, ip, line, fname, patbuf, pattern
bool	line_matches, encode_pattern, print_file_names, match_pattern
bool	clgetb()
int	strmatch(), strsearch(), patmatch(), patmake(), stridxs()
int	open(), getline(), clpopni(), clplen(), clgfil()

begin
	call smark (sp)
	call salloc (line, SZ_LINE, TY_CHAR)
	call salloc (fname, SZ_FNAME, TY_CHAR)
	call salloc (patbuf, SZ_LINE, TY_CHAR)
	call salloc (pattern, SZ_FNAME, TY_CHAR)

	# Get pattern.  If it contains either * or [, general pattern
	# matching with an encoded pattern must be used.  If no metacharacters
	# at all are used, or if metacharacters are disabled, use STRSEARCH
	# for maximum efficiency.

	call clgstr ("pattern", Memc[pattern], SZ_FNAME)
	if (clgetb ("metacharacters")) {

	    # Check for the tough pattern matching metachars.
	    chset[1] = CH_CLOSURE
	    chset[2] = CH_CCL
	    chset[3] = EOS
	    encode_pattern = (stridxs (chset, Memc[pattern]) > 0)

	    # If don't have to use patmatch, see if we have a simple alphanum
	    # string so that we can use strsearch.

	    if (!encode_pattern) {
		for (ip=pattern;  IS_ALNUM(Memc[ip]);  ip=ip+1)
		    ;
		match_pattern = (Memc[ip] != EOS)
	    }

	} else {
	    encode_pattern = false
	    match_pattern = false
	}

	stop_matched_lines = clgetb ("stop")
	list = clpopni ("files")
	print_file_names = (clplen(list) > 1) && (clgetb("print_file_names"))

	if (encode_pattern)
	    if (patmake (Memc[pattern], Memc[patbuf], SZ_LINE) == ERR)
		call error (1, "Pattern is too complex")

	# Search each file in the list, passing a line on to the output
	# only if the line matches and stop is false, or if the line does
	# not match and stop is true.

	while (clgfil (list, Memc[fname], SZ_FNAME) != EOF) {
	    fd = open (Memc[fname], READ_ONLY, TEXT_FILE)

	    while (getline (fd, Memc[line]) != EOF) {
		if (encode_pattern)
		    line_matches = (patmatch (Memc[line], Memc[patbuf]) > 0)
		else if (match_pattern)
		    line_matches = (strmatch (Memc[line], Memc[pattern]) > 0)
		else
		    line_matches = (strsearch (Memc[line], Memc[pattern]) > 0)

		if ((line_matches && !stop_matched_lines) ||
		    (!line_matches && stop_matched_lines)) {

		    if (print_file_names) {
			call printf ("%s:")
			    call pargstr (Memc[fname])
		    }

		    call putline (STDOUT, Memc[line])
		    call flush (STDOUT)
		}
	    }

	    call close (fd)
	}

	call sfree (sp)
	call clpcls (list)
end