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 }