#!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # # 8_13a.c 8_13b.c 8_13c.c all.c makefile pat.input patb.input tst.cmp tst13.c tst13b.c tstb.cmp # # To extract the files from this shell archive file simply # create a directory for this file, move the archive file # to it and enter the command # # sh filename # # The files will be extracted automatically. # Note: Do not use csh. # # Archive created: Mon Jul 30 23:12:25 EDT 1990 # echo x - 8_13a.c sed 's/^X//' > 8_13a.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // match a pattern on the input stream // %d looks for an integer & stops at the first // non-integer character // %o looks for an octal integer & stops ... // %x looks for a hexadecimal integer & stops ... // %i looks for a C++ integer & stops ... // %f looks for a floating point number & stops ... // %c matches a single character // %[xyz] matches a character within the set // %[^xyz] matches a character not within the set // %s matches a white-space delineated string // % may be followed by a field width // %% matches % // ' ' matches any white space // 'X' matches the character X #include /* DELETE */ #include /* DELETE */ #include /* DELETE */ #include /* DELETE */ #include "8_13b.c" /* DELETE */ int pat::match(char *pattern) { // reset base ptr to pt to beginning of buffer ebp->setbuffering(); // loop through the pattern looking // for things to match. int goodpattern = 1; while (*pattern && goodpattern) { int c = ebp->sgetc(); char p = *pattern++; // define a couple of small macros for // some common sequences #define Next() \ ebp->stossc(), c = ebp->sgetc() #define WNext() \ width--, ebp->stossc(), c = ebp->sgetc() #define doloop(testfunc) \ do { Next(); } while (testfunc(c)) #define dowloop(testfunc) \ do { width--; ebp->stossc(); \ } while ((width > 0) && \ testfunc(c = ebp->sgetc())) switch (p) { // space matches arbitrary white space case ' ': if (isspace(c)) doloop(isspace); else goodpattern = 0; break; // a pattern: %d, %f, %c, %s, %% case '%': p = *pattern++; // check pattern for a field // width specification long width = LONG_MAX; if (isdigit(p)) { width = strtol(&pattern[-1], &pattern, 10); p = *pattern++; } // the default for these two is 1 else if ((p == '[') || (p == 'c')) width = 1; // check for patterns which // toss white space first switch (p) { case 'd': case 'f': case 'o': case 'x': case 'i': case 's': if (isspace(c)) doloop(isspace); } // now skip past the particular type switch (p) { // decimal number case 'd': if ((width > 0) && ((c == '-') || (c == '+'))) WNext(); if ((width > 0) && isdigit(c)) dowloop(isdigit); else goodpattern = 0; break; // octal number case 'o': if ((width > 0) && ((c == '-') || (c == '+'))) WNext(); if ((width > 0) && isodigit(c)) dowloop(isodigit); else goodpattern = 0; break; // hexdecimal number case 'x': if ((width > 0) && ((c == '-') || (c == '+'))) WNext(); if ((width > 0) && isxdigit(c)) dowloop(isxdigit); else goodpattern = 0; break; // decimal, octal or hex number case 'i': if ((width > 0) && ((c == '-') || (c == '+'))) WNext(); // check for leading 0 or 0x if ((width > 0) && (c == '0')) { WNext(); if ((width > 0) && ((c == 'x') || (c == 'X'))) WNext(); } if ((width > 0) && isdigit(c)) dowloop(isdigit); else goodpattern = 0; break; // floating point case 'f': if ((width > 0) && ((c == '-') || (c == '+'))) WNext(); int digitsbefore = 0; int hasdecimal = 0; int digitsafter = 0; int hasexponent = 0; if ((width > 0) && isdigit(c)) { digitsbefore = 1; dowloop(isdigit); } if ((width > 0) && (c == '.')) { hasdecimal = 1; WNext(); if (isdigit(c)) { digitsafter = 1; dowloop(isdigit); } } if ((width > 0) && ((c == 'e') || (c == 'E'))) { hasexponent = 1; WNext(); if ((width > 0) && ((c == '-') || (c == '+'))) WNext(); if ((width > 0) && isdigit(c)) dowloop(isdigit); else goodpattern = 0; } if (!((digitsbefore && (hasdecimal || hasexponent)) || digitsafter)) goodpattern = 0; break; // any string. leading white // space was tossed above case 's': if (width > 0) dowloop(!isspace); break; // a scanset case '[': int x = 0; char *patbegin = pattern; if (pattern[1] == '^') { x = 1; patbegin++; } while ((width > 0) && checkcharset(patbegin, x, c)) WNext(); // found the right # of chars? if (width > 0) goodpattern = 0; pattern += x + 2 + checkcharset(patbegin, 0, -1); break; // any single character case 'c': while ((width > 0) && (c != EOF)) WNext(); if (width > 0) goodpattern = 0; break; // match single % case '%': while ((width > 0) && (c == '%')) WNext(); if (width > 0) goodpattern = 0; break; // unknown pattern default: goodpattern = 0; break; } break; // non-pattern, match the character default: if (c == p) ebp->stossc(); else goodpattern = 0; break; } } ebp->resetbuffering(); return goodpattern; } !EOF! ls -l 8_13a.c echo x - 8_13b.c sed 's/^X//' > 8_13b.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Check the scanset pattern for the character c. // Return complement for false and !complement for true. int checkcharset(char *pattern, int complement, int c) { char *svpat = pattern; // special case for pattern[0] == ']' if ((*pattern == ']') || (*pattern == '-')) if (c == *pattern) return !complement; else pattern++; // run down the pattern for ( ; *pattern && (*pattern != ']'); pattern++) // either a range or trailing `-' if (*pattern == '-') { // special case for trailing `-' if (pattern[1] == ']') { if (c == '-') return !complement; } // char range, a-z else if ((c > pattern[-1]) && (c <= pattern[1])) return !complement; // skip past the end value of the range else pattern++; } else if (*pattern == c) return !complement; // The character is not in the set. pattern now // points to the ']'. If c==-1, then return index // of ']', else false. if (c == -1) return pattern - svpat; return complement; } !EOF! ls -l 8_13b.c echo x - 8_13c.c sed 's/^X//' > 8_13c.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ // Match a pattern on the input stream. // Use the UNIX System V regcmp(3) routines // to do full regular expression matching. #include /* DELETE */ #include /* DELETE */ #include /* DELETE */ #include /* DELETE */ extern char *regcmp(char* ...); extern int regex(char *re, char *subj, char *ret0 ...); int pat::match(char *pattern) { // reset base ptr to pt to beginning of buffer ebp->setbuffering(); // make sure that a full line's worth is available for (int c = ebp->sgetc(); (c != '\n') && (c != EOF); c = ebp->sgetc()) ebp->stossc(); int foundnewline = (c == '\n'); // null out the newline if (foundnewline) { ebp->stossc(); ebp->sputbackc(0); } // compile the pattern char *re = regcmp(pattern, (char*)0); // check the line against the compiled pattern int goodpattern = regex(re, ebp->base, 0); // put the newline back if (foundnewline) { ebp->stossc(); ebp->sputbackc('\n'); } ebp->resetbuffering(); return goodpattern; } !EOF! ls -l 8_13c.c echo x - all.c sed 's/^X//' > all.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include #include #include #include #include "8_12a1.c" /* int extrabuf::overflow(int) */ #include "8_12a2.c" /* int extrabuf::underflow() */ #include "8_12a3.c" /* int extrabuf::reallocate() */ #include "8_12a4.c" /* void extrabuf::setbuffering() */ #include "8_12a5.c" /* void extrabuf::resetbuffering() */ !EOF! ls -l all.c echo x - makefile sed 's/^X//' > makefile << '!EOF!' CC= CC -I. -I../8.12dir -I../../CC CFLAGS= all: tst13 tst13b tst13: tst13.o all.o 8_13a.o ../8.12dir/memmove.o $(CC) tst13.o all.o 8_13a.o ../8.12dir/memmove.o -o tst13 -lPW tst13b: tst13b.o all.o 8_13c.o ../8.12dir/memmove.o $(CC) tst13b.o all.o 8_13c.o ../8.12dir/memmove.o -o tst13b -lPW all.o: all.c $(CC) $(CFLAGS) -c all.c 8_13a.o: 8_13a.c 8_13b.c $(CC) $(CFLAGS) -c 8_13a.c 8_13c.o: 8_13c.c $(CC) $(CFLAGS) -c 8_13c.c CMP= tst.cmp tstb.cmp OUT= tst.out tstb.out tst.out: tst13 pat.input ; tst13 < pat.input > tst.out tstb.out: tst13b patb.input ; tst13b < patb.input > tstb.out test: all $(OUT) $(CMP) cmp tst.out tst.cmp cmp tstb.out tstb.cmp @echo test done !EOF! ls -l makefile echo x - pat.input sed 's/^X//' > pat.input << '!EOF!' 1.75 75 5 123 4213 12341 2332 !EOF! ls -l pat.input echo x - patb.input sed 's/^X//' > patb.input << '!EOF!' Hello: 1.75 75 5 123 4213 Are: 12341 2332 !EOF! ls -l patb.input echo x - tst.cmp sed 's/^X//' > tst.cmp << '!EOF!' match 2 %f %d %d succeeded x = 75 y = 5 f = 1.75 a = 123 b = 4213 !EOF! ls -l tst.cmp echo x - tst13.c sed 's/^X//' > tst13.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include main() { pat p(cin); int x, y; float f; if (p.match("%d %f %d")) { cout << "match 1 %d %f %d succeeded\n"; p >> x >> f >> y; } else if (p.match("%f %d %d")) { cout << "match 2 %f %d %d succeeded\n"; p >> f >> x >> y; } else { cout << "default succeeded\n"; p >> x >> y >> f; } cout << "x = " << x << "\n" << "y = " << y << "\n" << "f = " << f << "\n"; int a = -1, b = -2; p >> a >> b; cout << "a = " << a << "\n" << "b = " << b << "\n"; return 0; } !EOF! ls -l tst13.c echo x - tst13b.c sed 's/^X//' > tst13b.c << '!EOF!' /* Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */ /* The C++ Answer Book */ /* Tony Hansen */ /* All rights reserved. */ #include main() { pat p(cin); int x, y; float f; char s[100]; if (p.match("Name:")) { cout << "match 1 %s %f %d succeeded\n"; p >> s >> f >> y >> x; } else if (p.match("Hello:")) { cout << "match 2 %s %f %d succeeded\n"; p >> s >> f >> x >> y; } else { cout << "default succeeded\n"; p >> s >> x >> y >> f; } cout << "s = '" << s << "'\n" << "x = '" << x << "'\n" << "y = '" << y << "'\n" << "f = '" << f << "'\n"; int a = -1, b = -2; p >> a >> b; cout << "a = " << a << "\n" << "b = " << b << "\n"; return 0; } !EOF! ls -l tst13b.c echo x - tstb.cmp sed 's/^X//' > tstb.cmp << '!EOF!' match 2 %s %f %d succeeded s = 'Hello:' x = '75' y = '5' f = '1.75' a = 123 b = 4213 !EOF! ls -l tstb.cmp # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0