home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-09-11 | 32.4 KB | 1,086 lines |
- Subject: v06i021: new printfck and manpage (printfck2)
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
- Reply-To: liam@cs.qmc.ac.uk (William Roberts)
-
- Mod.sources: Volume 6, Issue 21
- Submitted by: talcott!seismo!mcvax!cs.qmc.ac.uk!liam
- Archive-name: printfck2
-
- [ One of the major reasons why I'm sending this out is that is
- that there is now a manual page. From now on, I will probably
- not send out anything that is missing one. Probably exceptions
- are non-Unix source, like the recent Apollo pacman. --r$]
-
- The enclosed shar file is an enhanced version of printfck which
- generates check code for scanf() as well as printf(), has a
- manual page and comes with a makefile. It is a straightforward
- extension of the program from Guido van Rossum (mod.sources:
- Volume 4, Issue 114) which was recently distributed.
-
- William Roberts ARPA: liam@cs.qmc.ac.uk
- Queen Mary College UUCP: liam@qmc-cs.UUCP
- LONDON, UK
-
- --------------------CUT HERE--------------------
- #! /bin/sh
- # shar: Shell Archiver
- # Run the following with /bin/sh to create:
- # README
- # printfck.1
- # printfck.c
- # printfck.h
- # percent.c
- # Makefile
- # This archive created: Fri May 30 18:24:35 BST 1986
- echo shar: extracting "README" '('3109 chars')'
- if test -f README
- then
- echo shar: will not overwrite existing file "README"
- else
- cat << \SHAR_EOF > README
- Mod.sources: Volume 4, Issue 114
- Submitted by: Guido van Rossum <seismo!mcvax!guido>
-
- Here's something a colleague of mind wrote one or two years ago, and
- which recently prompted some interest on the net. Unfortunately it is
- not a very finished product; I post this so that others can benefit from
- it and change it to fit their needs. I tried to compile and run it (on
- a VAX running 4.2BSD) and it gave sensible output when fed with itself
- as input -- I can't say more about the quality. Foreseen use is
- something like:
- printfck file.c >temp.c
- lint temp.c procent.c
- Lint warnings about improper usage of any of the procent_* functions
- mean you're using an incorrect argument to a % escape. For variable
- strings used as formats it doesn't help you; see also the comments at
- the begin of the program.
- Look in the program to find the command line options (you can feed it
- your own list of printf-like functions).
-
- I'm sorry I can't spend more time on this (well I can but don't intend
- to since I have no need for it right now). If anybody comes up with a
- manual, an improved version or any other changes, I'd like to hear about
- it.
-
- Greetings,
- Guido van Rossum, CWI, Amsterdam <guido@mcvax.UUCP>
-
- /* printfck.c - check all uses of %d, %ld, %s, %u etc. - 850325 aeb@mcvax*/
- /* small fixes, made more robust, process cmdline arg - 850402 guido@boring*/
- /* Copyright 1985,1986 Stichting Mathematisch Centrum. Use at own risk. */
- #include <stdio.h>
-
- /* Feed with a list of routine names and descriptions:
- * printf("",...)
- * sprintf(s,"",...)
- * fprintf(f,"",...)
- * and with a source file; produce output in which occurrences of e.g.
- * sprintf(buf, "%s%ld", s, l)
- * are replaced by
- * sprintf(buf, "%s%ld", procent_s(s), procent_L(l))
- * Now let lint do the checking.
- * Bugs:
- * Cases where the format string is not explicitly given (e.g., is the
- * result of some other routine, or looks like bool ? "s1" : "s2")
- * are not handled.
- * Cases where the preprocessor produces quotes or comment delimiters
- * or concatenates partial identifiers are not handled.
- * We do not distinguish two sets of identifiers.
- * Only the parts lint sees get checked - not parts between (false)
- * #ifdef's. If the call to printf is outside #ifdef's, but some
- * args are inside, printfck may get confused. However, this is easy
- * to avoid:
- *
- * THIS FAILS THIS WORKS
- * ---------- ----------
- * printf("%s%d", printf("%s%d", (
- * #ifdef debug #ifdef debug
- * "foo" "foo"
- * #else #else
- * "bar" "bar"
- * #endif debug #endif debug
- * , num); ), num);
- *
- */
-
-
- 30/5/86 W.T. Roberts <liam@cs.qmc.ac.uk>
-
- I have modified printfck to handle scanf() as well as printf(),
- produced a manual page and a Makefile.
- SHAR_EOF
- if test 3109 -ne `wc -c < README`
- then
- echo shar: error transmitting "README" '('should be 3109 chars')'
- else
- echo README
- fi
- fi
- echo shar: extracting "printfck.1" '('3752 chars')'
- if test -f printfck.1
- then
- echo shar: will not overwrite existing file "printfck.1"
- else
- cat << \SHAR_EOF > printfck.1
- .TH PRINTFCK 1 "18 January 1983"
- .SH NAME
- printfck \- modify C program to enable typechecking of printf() calls
- .SH SYNOPSIS
- .B printfck
- [ -n ]
- [ -e functionname ] ...
- [ -f functionfile ] ...
- [ c-program ] ...
- .SH DESCRIPTION
- .I Printfck
- reads the C-program source from the named files (or standard
- input if no arguments are given) and determines the types of
- the arguments to
- .IR printf (3S)
- and
- .IR scanf (3S)
- according to the given format string. It writes to standard
- output a modified version of the program, where the
- .I printf()
- or
- .I scanf()
- arguments are turned into calls to dummy routines. For example:
- .PP
- printf("Name %8s not known.", x);
- becomes
- printf("Name %8s not known.", percent_s(x));
- .PP
- The routine percent_s() is defined within the modified program
- to be a function requiring a pointer to a character, so
- .IR lint (1)
- can now check that variable x does indeed have the appropriate
- type. Any lint warnings about improper usage of a percent_*
- function indicates that the corresponding printf argument does
- not match the command string!
- .PP
- The program recognises the routines
- .IR printf() ,
- .IR sprintf() ,
- .IR fprintf() ,
- .IR scanf() ,
- .I sscanf()
- and
- .IR fscanf() .
- .PP
- A typical way of using this would be:
-
- printfck part1.c part2.c part3.c > temp.c
- lint temp.c
- .SH "OPTIONS"
- The options allow modification of the list of functions checked
- by
- .IR printfck .
- This allows the correct checking of user-defined variants of
- printf() or scanf()
- and makes lint give more useful line numbers when it
- complains.
- .TP
- -n
- Erase the default list of functions.
- .TP
- -e
- The following argument is the name of a function to be checked
- in the same way as printf(): its first argument is a printf()
- format string from which subsequent argument types may be
- deduced. Note that fprintf() could not be specified in this
- way, because its first argument is not the format string.
- .TP
- -f
- The following argument is the name of a file containing a list
- of (function name,
- .IR n ,
- .IR t )
- triples, where
- .I n
- is the number of arguments which precede the format string
- and
- .I t
- indicates the type of formatting involved; 0 means
- printf()-style and 1 means scanf()-style.
- For example, the following file is equivalent to the default
- function names (# indicates a comment):
- .PP
- # default specification for printfck
- printf 0 # printf( "format", arg2, ... );
- fprintf 1 # fprintf( fp, "format", arg3, ... );
- sprintf 1 # sprintf( s, "format", arg3, ... );
- scanf 0 # scanf( "format", arg2, ... );
- fscanf 1 # fscanf( fp, "format", arg3, ... );
- sscanf 1 # sscanf( s, "format", arg3, ... );
- .SH "LIMITATIONS"
- If the format string is not an explicit constant,
- .I printfck
- cannot help you. It will however do its level best, and can
- cope with complicated #ifdefs, given suitable hints:
-
- .nr x \n(.lu/2u
- .in +0.5i
- THIS FAILS \h'|\nxu' THIS WORKS
- \h'|\nxu'
- printf("%s%d", \h'|\nxu' printf("%s%d", (
- #ifdef debug \h'|\nxu' #ifdef debug
- "foo" \h'|\nxu' "foo"
- #else \h'|\nxu' #else
- "bar" \h'|\nxu' "bar"
- #endif debug \h'|\nxu' #endif debug
- , num); \h'|\nxu' ), num);
- .in
- .SH "BUGS"
- Doesn't check arguments to see if they contain invocations of
- the routines to be checked.
- .SH "SEE ALSO"
- printf(3S), scanf(3S), lint(1)
- .SH "AUTHOR"
- .nf
- Mod.sources: Volume 4, Issue 114
- Submitted by: Guido van Rossum <seismo!mcvax!guido>
- SHAR_EOF
- if test 3752 -ne `wc -c < printfck.1`
- then
- echo shar: error transmitting "printfck.1" '('should be 3752 chars')'
- else
- echo printfck.1
- fi
- fi
- echo shar: extracting "printfck.c" '('13824 chars')'
- if test -f printfck.c
- then
- echo shar: will not overwrite existing file "printfck.c"
- else
- cat << \SHAR_EOF > printfck.c
- /* printfck.c - check all uses of %d, %ld, %s, %u etc. - 850325 aeb@mcvax*/
- /* small fixes, made more robust, process cmdline arg - 850402 guido@boring*/
- /* Copyright 1985,1986 Stichting Mathematisch Centrum. Use at own risk. */
- /* $Header: printfck.c,v 1.3 86/05/30 12:31:42 liam Exp $
- * $Log: printfck.c,v $
- * Revision 1.3 86/05/30 12:31:42 liam
- * Added facility to recognise scanf formats as well.
- *
- */
-
- #include <stdio.h>
- #include <strings.h>
-
- #include "printfck.h"
-
- /* Feed with a list of routine names and descriptions:
- * printf("",...)
- * sprintf(s,"",...)
- * fprintf(f,"",...)
- * and with a source file; produce output in which occurrences of e.g.
- * sprintf(buf, "%s%ld", s, l)
- * are replaced by
- * sprintf(buf, "%s%ld", percent_s(s), percent_L(l))
- * Now let lint do the checking.
- * Bugs:
- * Cases where the format string is not explicitly given (e.g., is the
- * result of some other routine, or looks like bool ? "s1" : "s2")
- * are not handled.
- * Cases where the preprocessor produces quotes or comment delimiters
- * or concatenates partial identifiers are not handled.
- * We do not distinguish two sets of identifiers.
- * Only the parts lint sees get checked - not parts between (false)
- * #ifdef's. If the call to printf is outside #ifdef's, but some
- * args are inside, printfck may get confused. However, this is easy
- * to avoid:
- *
- * THIS FAILS THIS WORKS
- * ---------- ----------
- * printf("%s%d", printf("%s%d", (
- * #ifdef debug #ifdef debug
- * "foo" "foo"
- * #else #else
- * "bar" "bar"
- * #endif debug #endif debug
- * , num); ), num);
- *
- */
-
- char *index();
- char *rindex();
- char *malloc();
-
- #define MAXIRS 100
-
- struct ir {
- char *rname;
- int pn; /* number of args preceding format string */
- int type; /* 0 = printf, 1 = scanf */
- } irs[MAXIRS+1] = { /* should be read in - for now explicit */
- "printf", 0, 0,
- "fprintf", 1, 0,
- "sprintf", 1, 0,
- "scanf", 0, 1,
- "fscanf", 1, 1,
- "sscanf", 1, 1,
- };
-
- int nirs;
-
- char *progname;
- char *filename = NULL;
- FILE *inp;
-
- int eof;
- int peekc;
- int lastc;
- int linenr;
-
- initgetcx()
- {
- eof = 0;
- peekc = '\n'; /* recognize # on very first line */
- lastc = 0; /* result of last getchar() */
- linenr = 1;
- }
-
- getcx()
- {
- register int c;
-
- if(peekc) {
- c = peekc;
- peekc = 0;
- } else if(eof) {
- c = EOF;
- } else {
- if(lastc) {
- putchar(lastc);
- lastc = 0;
- }
- if((c = getc(inp)) == EOF)
- eof++;
- else {
- lastc = c;
- if(c == '\n')
- linenr++;
- }
- }
-
- return(c);
- }
-
- /* Note: we do not want to eliminate comments; perhaps they contain
- lint directives. */
- getcy() /* as getcx(), but skip comments */
- {
- register int c = getcx();
-
- if(c == '/') {
- c = getcx();
- if(c == '*') {
- while(1) {
- c = getcx();
- if(c == EOF)
- error("unfinished comment");
- while(c == '*') {
- c = getcx();
- if(c == '/')
- return(getcy());
- }
- }
- } else {
- peekc = c;
- c = '/';
- }
- }
- return(c);
- }
-
- getcz() /* as getcy(), but skip preprocessor directives */
- {
- register int c = getcy();
-
- while(c == '\n') {
- c = getcx();
- if(c == '#') {
- while(c != '\n') {
- c = getcx();
- if(c == EOF)
- error("incomplete line");
- while(c == '\\') {
- (void) getcx(); c = getcx();
- }
- }
- } else {
- peekc = c;
- return('\n');
- }
- }
- return(c);
- }
-
- getcq() /* as getcz() but skip strings */
- {
- register int c = getcz();
- register int delim;
-
- if(c == '\'' || c == '"') {
- delim = c;
- while(1) {
- c = getcx();
- if(c == '\n' || c == EOF)
- error("Unfinished string (delim %c)", delim);
- if(c == '\\') {
- (void) getcx();
- continue;
- }
- if(c == delim)
- return(getcq());
- }
- }
- return(c);
- }
-
- usage()
- {
- fprintf(stderr,
- "Usage: %s [-n] [-e function] ... [-f datafile] ... [file.c] ...\n",
- progname);
- exit(2);
- }
-
- extern char *optarg;
- extern int optind;
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- register int c;
- FILE *fp;
-
- if (argc > 0) {
- progname = rindex(argv[0], '/');
- if (progname != NULL)
- ++progname;
- else
- progname = argv[0];
- }
-
- for (; irs[nirs].rname != NULL; ) ++nirs; /* Count defaults */
-
- while ((c = getopt(argc, argv, "e:nf:")) != EOF) {
- switch (c) {
- case '?':
- usage();
- /* NOTREACHED */
- case 'e':
- addir(optarg, 0, 0);
- break;
- case 'n':
- nirs = 0;
- irs[nirs].rname = NULL;
- break;
- case 'f':
- getirfile(optarg);
- break;
- }
- }
-
- /* tell lint the types of the percent_* routines */
-
- printf("#include \"%s\"\n", PERCENT_HEADERS);
-
- /* now process them files.... */
-
- if (optind == argc)
- treat(stdin, "stdin");
- else {
- for (; optind < argc; ++optind) {
- if (strcmp(argv[optind], "-") == 0)
- treat(stdin, "stdin");
- else {
- filename = argv[optind];
- fp = fopen(filename, "r");
- if (fp == NULL)
- filerror(filename);
- treat(fp, filename);
- fclose(fp);
- }
- }
- }
-
- /* now include the bodies of the routines */
-
- printf("#include \"%s\"\n", PERCENT_ROUTINES);
-
- exit(0);
- }
-
- treat(fp, file)
- FILE *fp;
- char *file;
- {
- register int c;
-
- filename = file;
- linenr = 0;
- inp = fp;
- printf("# line 1 \"%s\"\n", file);
-
- initgetcx();
-
- while((c = getcq()) != EOF) {
-
- /* check for (interesting) identifiers */
- if(letter(c))
- rd_id(c);
- }
- filename = NULL;
- linenr = 0;
- irs[nirs].rname = NULL;
- }
-
-
- rd_id(first)
- register int first;
- {
- char idf[256];
- register char *ip = idf;
- register int c;
-
- *ip++ = first;
- while(letdig(c = getcx()))
- if(ip-idf < sizeof(idf)-1)
- *ip++ = c;
- peekc = c;
- *ip = 0;
- handle(idf);
- }
-
- /*VARARGS1*/
- error(s, x)
- char *s;
- {
- printf("\n"); /* Finish incomplete output line */
- fprintf(stderr, "%s: Error (", progname);
- if (filename != NULL) fprintf(stderr, "%s, ", filename);
- fprintf(stderr, "line %d): ", linenr);
- fprintf(stderr, s, x);
- fprintf(stderr, "\n");
- exit(1);
- }
-
- /*VARARGS1*/
- warning(s, x1, x2)
- char *s;
- {
- fprintf(stderr, "%s: Warning (", progname);
- if (filename != NULL) fprintf(stderr, "%s, ", filename);
- fprintf(stderr, "line %d): ", linenr);
- fprintf(stderr, s, x1, x2);
- fprintf(stderr, "\n");
- }
-
- filerror(file)
- char *file;
- {
- fprintf(stderr, "%s: can't open ", progname);
- perror(file);
- exit(2);
- }
-
- letter(c)
- register int c;
- {
- return(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_');
- }
-
- digit(c)
- register int c;
- {
- return('0' <= c && c <= '9');
- }
-
- letdig(c)
- register int c;
- {
- return(letter(c) || digit(c));
- }
-
- handle(idf)
- register char *idf;
- {
- register struct ir *irp = irs;
-
- while(irp->rname) {
- if(!strcmp(idf, irp->rname)) {
- doit(irp);
- return;
- }
- irp++;
- }
- }
-
- skipspaces()
- {
- register int c;
-
- while(1) {
- c = getcz();
- if(c == ' ' || c == '\t' || c == '\n')
- continue;
- peekc = c;
- return;
- }
- }
-
- doit(irp)
- register struct ir *irp;
- {
- register int c, cnt = irp->pn;
-
- skipspaces();
- if((c = getcz()) != '(') {
- peekc = c;
- warning("%s not followed by '('", irp->rname);
- return;
- }
-
- while(cnt--) {
- c = skiparg();
- if(c != ',') {
- peekc = c;
- warning("arg of %s not followed by comma", irp->rname);
- return;
- }
- }
- skipspaces();
-
- /* now parse format string (if present) */
- /* (here we also avoid defining occurrences) */
- if((c = getcx()) != '"') {
- peekc = c;
- return;
- }
- if (irp->type == 0)
- do_printf(irp);
- else
- do_scanf(irp);
- }
-
- do_printf(irp)
- register struct ir *irp;
- {
- char fmt[256];
- register char *fp = fmt;
- register int c;
-
- while(1) {
- c = getcx();
- if(c == '\n' || c == EOF)
- error("Unfinished format string");
- if(c == '"')
- break;
- if(c != '%') {
- if (c == '\\')
- (void) getcx();
- continue;
- }
- c = getcx();
- if(c == '%')
- continue;
- if(c == '-')
- c = getcx();
- if(c == '*') {
- c = getcx();
- if(fp-fmt < sizeof(fmt)-1)
- *fp++ = '*';
- } else while(digit(c))
- c = getcx();
- if(c == '.')
- c = getcx();
- if(c == '*') {
- c = getcx();
- if(fp-fmt < sizeof(fmt)-1)
- *fp++ = '*';
- } else while(digit(c))
- c = getcx();
- if(c == '#')
- c = getcx();
- if(c == 'l') {
- c = getcx();
- if('a' <= c && c <= 'z')
- c -= 'a'-'A';
- else
- error("%%l not followed by lowercase");
- }
- if(fp-fmt < sizeof(fmt)-1)
- *fp++ = c;
- else
- warning("ridiculously long format");
- }
- *fp = 0;
- fp = fmt;
- skipspaces();
- while((c = getcz()) == ',') {
- if(!*fp)
- error("%s has too many arguments", irp->rname);
- skipspaces();
- if (*fp == '*') {
- printf("percent_star(");
- fp++;
- } else
- printf("percent_%c(", *fp++);
- c = skiparg();
- printf(")");
- peekc = c;
- }
- if(c != ')')
- error("%s has ill-formed argument list", irp->rname);
- if(*fp)
- error("%s has too few arguments", irp->rname);
- }
-
-
- do_scanf(irp)
- register struct ir *irp;
- {
- char fmt[256], shorten;
- register char *fp = fmt;
- register int c;
- int dummy = 0;
-
- while(1) {
- dummy = 0;
- c = getcx();
- if(c == '\n' || c == EOF)
- error("Unfinished format string");
- if(c == '"')
- break;
- if(c != '%') {
- if (c == '\\')
- (void) getcx();
- continue;
- }
- c = getcx();
- if(c == '%')
- continue; /* %% */
-
- if(c == '*') {
- dummy = 1; /* no corresponding argument */
- c = getcx();
- }
- while (digit(c) || c == '.' || c == '-') {
- c = getcx();
- }
- switch(c) {
- case '[':
- c = skipbracket(); /* scan to close bracket */
- break;
- case 'l':
- c = getcx();
- if('a' <= c && c <= 'z')
- c -= 'a'-'A';
- else
- error("%%l not followed by lowercase");
- break;
- case 'h':
- shorten = c;
- c = getcx();
- if('a' <= c && c <= 'z')
- c -= 'a'-'A';
- else
- error("%%h not followed by lowercase");
- break;
- default:
- /* must be a format letter */
- break;
- }
- if (!dummy) {
- if(fp-fmt < sizeof(fmt)-2) {
- if (shorten == 'h')
- *fp++ = 'h';
- *fp++ = c;
- } else
- warning("ridiculously long format");
- }
- }
- *fp = 0;
- fp = fmt;
- skipspaces();
- while((c = getcz()) == ',') {
- if(!*fp)
- error("%s has too many arguments", irp->rname);
- skipspaces();
- if ( (shorten = *fp) == 'h')
- fp++;
- switch (*fp) {
- case 's': printf("percent_s("); break;
- case ']': printf("percent_bkt("); break;
- default:
- if (shorten == 'h')
- printf("percent_h%c_ptr(", *fp);
- else
- printf("percent_%c_ptr(", *fp);
- }
- fp++;
- c = skiparg();
- printf(")");
- peekc = c;
- }
- if(c != ')')
- error("%s has ill-formed argument list", irp->rname);
- if(*fp)
- error("%s has too few arguments", irp->rname);
- }
-
- skiparg()
- {
- register int parenct = 0;
- register int c;
-
- parenct = 0;
- while(1) {
- c = getcq();
- if(c == EOF)
- error("eof in arg list");
- if(!parenct && (c == ',' || c == ')'))
- return(c);
- if(c == '(' || c == '[') {
- parenct++;
- continue;
- }
- if(c == ')' || c == ']') {
- parenct--;
- continue;
- }
- }
- }
-
- skipbracket()
- {
- register int c;
-
- while(1) {
- c = getcx();
- if(c == EOF)
- error("eof during %%[ ]");
- if(c == '\\') {
- c = getcx();
- continue; /* avoid escaped char */
- }
- if(c == ']') return c;
- }
- }
-
- char *strsave(s)
- char *s;
- {
- char *t = malloc(strlen(s) + 1);
- if (t == NULL) error("out of memory");
- strcpy(t, s);
- return t;
- }
-
- getirfile(irfile)
- char *irfile;
- {
- FILE *fp = fopen(irfile, "r");
- char line[256];
- char name[256];
- char *end;
- int n;
- int cnt, type;
-
- if (fp == NULL) filerror(irfile);
- filename = irfile;
- linenr = 0;
- while (fgets(line, sizeof line, fp)) {
- ++linenr;
- end = index(line, '#');
- if (end) *end = '\0';
- n= sscanf(line, " %s %d %d %s", name, &cnt, &type, name+1);
- if (n == 0 || name[0] == '\0')
- continue; /* Skip empty line or comment */
- if (n != 3 || cnt < 0 || (type != 0 && type != 1) )
- error("bad format (must be %%s %%u %%u)");
- /* Should also check for valid name... */
- addir(strsave(name), cnt, type);
- }
- fclose(fp);
- filename = NULL;
- linenr = 0;
- }
-
- addir(name, cnt, type)
- char *name;
- int cnt, type;
- {
- if (nirs >= MAXIRS) error("table overflow");
- irs[nirs].rname = name;
- irs[nirs].pn = cnt;
- irs[nirs].type = type;
- ++nirs;
- }
-
- /*
- * get option letter from argument vector
- */
- int opterr = 1, /* useless, never set or used */
- optind = 1, /* index into parent argv vector */
- optopt; /* character checked for validity */
- char *optarg; /* argument associated with option */
-
- #define BADCH (int)'?'
- #define EMSG ""
- #define tell(s) fputs(*nargv,stderr);fputs(s,stderr); \
- fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
-
- getopt(nargc,nargv,ostr)
- int nargc;
- char **nargv,
- *ostr;
- {
- static char *place = EMSG; /* option letter processing */
- register char *oli; /* option letter list index */
- char *index();
-
- if(!*place) { /* update scanning pointer */
- if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
- if (*place == '-') { /* found "--" */
- ++optind;
- return(EOF);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
- if(!*place) ++optind;
- tell(": illegal option -- ");
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place) ++optind;
- }
- else { /* need an argument */
- if (*place) optarg = place; /* no white space */
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- tell(": option requires an argument -- ");
- }
- else optarg = nargv[optind]; /* white space */
- place = EMSG;
- ++optind;
- }
- return(optopt); /* dump back option letter */
- }
-
- SHAR_EOF
- if test 13824 -ne `wc -c < printfck.c`
- then
- echo shar: error transmitting "printfck.c" '('should be 13824 chars')'
- else
- echo printfck.c
- fi
- fi
- echo shar: extracting "printfck.h" '('132 chars')'
- if test -f printfck.h
- then
- echo shar: will not overwrite existing file "printfck.h"
- else
- cat << \SHAR_EOF > printfck.h
- #define PERCENT_HEADERS "/usr/src/net/printfck/percent.h"
- #define PERCENT_ROUTINES "/usr/src/net/printfck/percent.c"
- SHAR_EOF
- if test 132 -ne `wc -c < printfck.h`
- then
- echo shar: error transmitting "printfck.h" '('should be 132 chars')'
- else
- echo printfck.h
- fi
- fi
- echo shar: extracting "percent.c" '('2094 chars')'
- if test -f percent.c
- then
- echo shar: will not overwrite existing file "percent.c"
- else
- cat << \SHAR_EOF > percent.c
- /*LINTLIBRARY*/
- int percent_d(x) int x; { return x; }
- int percent_o(x) int x; { return x; }
- int percent_x(x) int x; { return x; }
- long percent_D(x) long x; { return x; }
- long percent_O(x) long x; { return x; }
- long percent_X(x) long x; { return x; }
- double percent_e(x) double x; { return x; }
- double percent_f(x) double x; { return x; }
- double percent_g(x) double x; { return x; }
- double percent_E(x) double x; { return x; }
- double percent_F(x) double x; { return x; }
- double percent_G(x) double x; { return x; }
- unsigned percent_u(x) unsigned x; { return x; }
- int percent_c(x) int x; { return x; }
- char * percent_s(x) char * x; { return x; }
-
- int percent_star(x) int x; { return x; }
-
- int * percent_d_ptr(x) int * x; { return x; }
- int * percent_o_ptr(x) int * x; { return x; }
- int * percent_x_ptr(x) int * x; { return x; }
- short * percent_hd_ptr(x) short * x; { return x; }
- short * percent_ho_ptr(x) short * x; { return x; }
- short * percent_hx_ptr(x) short * x; { return x; }
- long * percent_D_ptr(x) long * x; { return x; }
- long * percent_O_ptr(x) long * x; { return x; }
- long * percent_X_ptr(x) long * x; { return x; }
- float * percent_e_ptr(x) float * x; { return x; }
- float * percent_f_ptr(x) float * x; { return x; }
- float * percent_g_ptr(x) float * x; { return x; }
- double * percent_E_ptr(x) double * x; { return x; }
- double * percent_F_ptr(x) double * x; { return x; }
- double * percent_G_ptr(x) double * x; { return x; }
- unsigned * percent_u_ptr(x) unsigned * x; { return x; }
-
- int * percent_c_ptr(x) int * x; { return x; }
- char * percent_bkt(x) char * x; { return x; }
-
- /* NOTE: not all C compilers support unsigned long! - If your compiler rejects
- * the following lines, replace "unsigned long" with just "long"
- */
- unsigned long percent_U(x) unsigned long x; { return x; }
- unsigned long * percent_U_ptr(x) unsigned long * x; { return x; }
- SHAR_EOF
- if test 2094 -ne `wc -c < percent.c`
- then
- echo shar: error transmitting "percent.c" '('should be 2094 chars')'
- else
- echo percent.c
- fi
- fi
- echo shar: extracting "Makefile" '('300 chars')'
- if test -f Makefile
- then
- echo shar: will not overwrite existing file "Makefile"
- else
- cat << \SHAR_EOF > Makefile
- # Makefile for printfck
- #
- # Change printfck.h so that PERCENT_HEADERS and PERCENT_ROUTINES
- # have the correct directory paths.
-
-
- all: printfck percent.h
-
-
- printfck: printfck.o printfck.h
- cc -o printfck printfck.o
-
- percent.h: percent.c
- sed -e "s/LINTLIBRARY//" -e "s/(x.*/();/" percent.c >percent.h
- SHAR_EOF
- if test 300 -ne `wc -c < Makefile`
- then
- echo shar: error transmitting "Makefile" '('should be 300 chars')'
- else
- echo Makefile
- fi
- fi
- # End of shar archive
- exit 0
-