hbase

heirloom base
git clone git://git.2f30.org/hbase
Log | Files | Refs | README

plist.c (4498B)


      1 /*
      2  * grep - search a file for a pattern
      3  *
      4  * Gunnar Ritter, Freiburg i. Br., Germany, April 2001.
      5  */
      6 /*
      7  * Copyright (c) 2003 Gunnar Ritter
      8  *
      9  * This software is provided 'as-is', without any express or implied
     10  * warranty. In no event will the authors be held liable for any damages
     11  * arising from the use of this software.
     12  *
     13  * Permission is granted to anyone to use this software for any purpose,
     14  * including commercial applications, and to alter it and redistribute
     15  * it freely, subject to the following restrictions:
     16  *
     17  * 1. The origin of this software must not be misrepresented; you must not
     18  *    claim that you wrote the original software. If you use this software
     19  *    in a product, an acknowledgment in the product documentation would be
     20  *    appreciated but is not required.
     21  *
     22  * 2. Altered source versions must be plainly marked as such, and must not be
     23  *    misrepresented as being the original software.
     24  *
     25  * 3. This notice may not be removed or altered from any source distribution.
     26  */
     27 
     28 /*	Sccsid @(#)plist.c	1.22 (gritter) 12/8/04>	*/
     29 
     30 /*
     31  * Pattern list routines.
     32  */
     33 
     34 #include	<sys/types.h>
     35 #include	<sys/stat.h>
     36 #include	<fcntl.h>
     37 #include	<unistd.h>
     38 #include	<stdio.h>
     39 #include	<string.h>
     40 #include	<stdlib.h>
     41 #include	<ctype.h>
     42 
     43 #include	"grep.h"
     44 #include	"alloc.h"
     45 
     46 /*
     47  * Add a pattern starting at the given node of the expression list.
     48  */
     49 static void
     50 addpat(struct expr **e, char *pat, long len, enum eflags flg)
     51 {
     52 	if (e0) {
     53 		(*e)->e_nxt = (struct expr *)smalloc(sizeof **e);
     54 		(*e) = (*e)->e_nxt;
     55 	} else
     56 		e0 = (*e) = (struct expr *)smalloc(sizeof **e);
     57 	if (wflag)
     58 		wcomp(&pat, &len);
     59 	(*e)->e_nxt = NULL;
     60 	(*e)->e_pat = pat;
     61 	(*e)->e_len = len;
     62 	(*e)->e_flg = flg;
     63 }
     64 
     65 /*
     66  * Read patterns from pattern string. In traditional command versions, -f
     67  * overrides all -e and all previous -f options. In POSIX.2 command versions,
     68  * all -e and -f options are cumulated.
     69  */
     70 void
     71 patstring(char *cp)
     72 {
     73 	struct expr *e = NULL;
     74 	char *ep;
     75 	int nl;
     76 
     77 	if (e0) {
     78 		if (sus)
     79 			for (e = e0; e->e_nxt; e = e->e_nxt);
     80 		else if (fflag)
     81 			return;
     82 		else
     83 			e0 = NULL;
     84 	}
     85 	if (cp) {
     86 		do {
     87 			if ((nl = (ep = strchr(cp, '\n')) != NULL) != 0)
     88 				*ep = 0;
     89 			addpat(&e, cp, ep ? ep - cp : strlen(cp), nl);
     90 			cp = ep + 1;
     91 			if (nl)
     92 				*ep = '\n';
     93 		} while (ep);
     94 	} else
     95 		addpat(&e, strdup(""), 0, E_NULL);
     96 }
     97 
     98 /*
     99  * Read patterns from file.
    100  */
    101 void
    102 patfile(char *fn)
    103 {
    104 	struct stat st;
    105 	struct expr *e = NULL;
    106 	char *cp;
    107 	struct iblok	*ip;
    108 	size_t sz, len;
    109 	int nl;
    110 
    111 	if ((ip = ib_open(fn, 0)) == NULL || fstat(ip->ib_fd, &st) < 0) {
    112 		fprintf(stderr, "%s: can't open %s\n", progname, fn);
    113 		exit(2);
    114 	}
    115 	if (e0) {
    116 		if (sus)
    117 			for (e = e0; e->e_nxt; e = e->e_nxt);
    118 		else
    119 			e0 = NULL;
    120 	}
    121 	while (cp = NULL, sz = 0,
    122 			(len = ib_getlin(ip, &cp, &sz, srealloc)) > 0) {
    123 		if ((nl = cp[len - 1] == '\n') != 0)
    124 			cp[len - 1] = '\0';
    125 		addpat(&e, cp, len - nl, nl);
    126 	}
    127 	ib_close(ip);
    128 }
    129 
    130 /*
    131  * getc() substitute operating on the pattern list.
    132  */
    133 int
    134 nextch(void)
    135 {
    136 	static struct expr *e;
    137 	static char *cp;
    138 	static long len;
    139 	static int oneof;
    140 	wchar_t wc;
    141 	int n;
    142 
    143 	if (oneof)
    144 		return EOF;
    145 	if (e == NULL) {
    146 		e = e0;
    147 		if (e->e_flg & E_NULL) {
    148 			oneof++;
    149 			return EOF;
    150 		}
    151 	}
    152 	if (cp == NULL) {
    153 		cp = e->e_pat;
    154 		len = e->e_len;
    155 	}
    156 	if (mbcode && *cp & 0200) {
    157 		if ((n = mbtowc(&wc, cp, MB_LEN_MAX)) < 0) {
    158 			fprintf(stderr, "%s: illegal byte sequence\n",
    159 				progname);
    160 			exit(1);
    161 		}
    162 		cp += n;
    163 		len -= n;
    164 	} else {
    165 		wc = *cp++ & 0377;
    166 		len--;
    167 	}
    168 	if (len >= 0)
    169 		return iflag ? mbcode && wc & ~(wchar_t)0177 ?
    170 			towlower(wc) : tolower(wc) : wc;
    171 	cp = NULL;
    172 	n = e->e_flg & E_NL;
    173 	if ((e = e->e_nxt) == NULL) {
    174 		oneof++;
    175 		if (!n)
    176 			return EOF;
    177 	}
    178 	return '\n';
    179 }
    180 
    181 /*
    182  * Print matching line based on ip->ib_cur and moff. Advance ip->ib_cur to start
    183  * of next line. Used from special rangematch functions.
    184  */
    185 void
    186 outline(struct iblok *ip, char *last, size_t moff)
    187 {
    188 	register char *sol, *eol;	/* start and end of line */
    189 
    190 	if (qflag == 0) {
    191 		if (status == 1)
    192 			status = 0;
    193 		if (lflag) {
    194 			puts(filename ? filename : stdinmsg);
    195 		} else {
    196 			lmatch++;
    197 			sol = ip->ib_cur + moff;
    198 			if (*sol == '\n' && sol > ip->ib_cur)
    199 				sol--;
    200 			while (sol > ip->ib_cur && *sol != '\n')
    201 				sol--;
    202 			if (sol > ip->ib_cur)
    203 				sol++;
    204 			ip->ib_cur += moff;
    205 			for (eol = ip->ib_cur; eol <= last
    206 					&& *eol != '\n'; eol++);
    207 			if (!cflag)
    208 				report(sol, eol - sol, ib_offs(ip) / BSZ, 1);
    209 			ip->ib_cur = eol + 1;
    210 		}
    211 	} else	/* qflag != 0 */
    212 		exit(0);
    213 }