head	1.37;
access;
symbols
	netbsd-11-0-RC4:1.37
	netbsd-11-0-RC3:1.37
	netbsd-11-0-RC2:1.37
	netbsd-11-0-RC1:1.37
	perseant-exfatfs-base-20250801:1.37
	netbsd-11:1.37.0.4
	netbsd-11-base:1.37
	netbsd-10-1-RELEASE:1.35
	perseant-exfatfs-base-20240630:1.37
	perseant-exfatfs:1.37.0.2
	perseant-exfatfs-base:1.37
	netbsd-8-3-RELEASE:1.35
	netbsd-9-4-RELEASE:1.35
	netbsd-10-0-RELEASE:1.35
	netbsd-10-0-RC6:1.35
	netbsd-10-0-RC5:1.35
	netbsd-10-0-RC4:1.35
	netbsd-10-0-RC3:1.35
	netbsd-10-0-RC2:1.35
	netbsd-10-0-RC1:1.35
	netbsd-10:1.35.0.52
	netbsd-10-base:1.35
	netbsd-9-3-RELEASE:1.35
	cjep_sun2x-base1:1.35
	cjep_sun2x:1.35.0.50
	cjep_sun2x-base:1.35
	cjep_staticlib_x-base1:1.35
	netbsd-9-2-RELEASE:1.35
	cjep_staticlib_x:1.35.0.48
	cjep_staticlib_x-base:1.35
	netbsd-9-1-RELEASE:1.35
	phil-wifi-20200421:1.35
	phil-wifi-20200411:1.35
	is-mlppp:1.35.0.46
	is-mlppp-base:1.35
	phil-wifi-20200406:1.35
	netbsd-8-2-RELEASE:1.35
	netbsd-9-0-RELEASE:1.35
	netbsd-9-0-RC2:1.35
	netbsd-9-0-RC1:1.35
	phil-wifi-20191119:1.35
	netbsd-9:1.35.0.44
	netbsd-9-base:1.35
	phil-wifi-20190609:1.35
	netbsd-8-1-RELEASE:1.35
	netbsd-8-1-RC1:1.35
	pgoyette-compat-merge-20190127:1.35
	pgoyette-compat-20190127:1.35
	pgoyette-compat-20190118:1.35
	pgoyette-compat-1226:1.35
	pgoyette-compat-1126:1.35
	pgoyette-compat-1020:1.35
	pgoyette-compat-0930:1.35
	pgoyette-compat-0906:1.35
	netbsd-7-2-RELEASE:1.35
	pgoyette-compat-0728:1.35
	netbsd-8-0-RELEASE:1.35
	phil-wifi:1.35.0.42
	phil-wifi-base:1.35
	pgoyette-compat-0625:1.35
	netbsd-8-0-RC2:1.35
	pgoyette-compat-0521:1.35
	pgoyette-compat-0502:1.35
	pgoyette-compat-0422:1.35
	netbsd-8-0-RC1:1.35
	pgoyette-compat-0415:1.35
	pgoyette-compat-0407:1.35
	pgoyette-compat-0330:1.35
	pgoyette-compat-0322:1.35
	pgoyette-compat-0315:1.35
	netbsd-7-1-2-RELEASE:1.35
	pgoyette-compat:1.35.0.40
	pgoyette-compat-base:1.35
	netbsd-7-1-1-RELEASE:1.35
	matt-nb8-mediatek:1.35.0.38
	matt-nb8-mediatek-base:1.35
	perseant-stdc-iso10646:1.35.0.36
	perseant-stdc-iso10646-base:1.35
	netbsd-8:1.35.0.34
	netbsd-8-base:1.35
	prg-localcount2-base3:1.35
	prg-localcount2-base2:1.35
	prg-localcount2-base1:1.35
	prg-localcount2:1.35.0.32
	prg-localcount2-base:1.35
	pgoyette-localcount-20170426:1.35
	bouyer-socketcan-base1:1.35
	pgoyette-localcount-20170320:1.35
	netbsd-7-1:1.35.0.30
	netbsd-7-1-RELEASE:1.35
	netbsd-7-1-RC2:1.35
	netbsd-7-nhusb-base-20170116:1.35
	bouyer-socketcan:1.35.0.28
	bouyer-socketcan-base:1.35
	pgoyette-localcount-20170107:1.35
	netbsd-7-1-RC1:1.35
	pgoyette-localcount-20161104:1.35
	netbsd-7-0-2-RELEASE:1.35
	localcount-20160914:1.35
	netbsd-7-nhusb:1.35.0.26
	netbsd-7-nhusb-base:1.35
	pgoyette-localcount-20160806:1.35
	pgoyette-localcount-20160726:1.35
	pgoyette-localcount:1.35.0.24
	pgoyette-localcount-base:1.35
	netbsd-7-0-1-RELEASE:1.35
	netbsd-7-0:1.35.0.22
	netbsd-7-0-RELEASE:1.35
	netbsd-7-0-RC3:1.35
	netbsd-7-0-RC2:1.35
	netbsd-7-0-RC1:1.35
	netbsd-5-2-3-RELEASE:1.31.4.1
	netbsd-5-1-5-RELEASE:1.31.4.1
	netbsd-6-0-6-RELEASE:1.35
	netbsd-6-1-5-RELEASE:1.35
	netbsd-7:1.35.0.20
	netbsd-7-base:1.35
	yamt-pagecache-base9:1.35
	yamt-pagecache-tag8:1.35
	netbsd-6-1-4-RELEASE:1.35
	netbsd-6-0-5-RELEASE:1.35
	tls-earlyentropy:1.35.0.18
	tls-earlyentropy-base:1.35
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.35
	riastradh-drm2-base3:1.35
	netbsd-6-1-3-RELEASE:1.35
	netbsd-6-0-4-RELEASE:1.35
	netbsd-5-2-2-RELEASE:1.31.4.1
	netbsd-5-1-4-RELEASE:1.31.4.1
	netbsd-6-1-2-RELEASE:1.35
	netbsd-6-0-3-RELEASE:1.35
	netbsd-5-2-1-RELEASE:1.31.4.1
	netbsd-5-1-3-RELEASE:1.31.4.1
	netbsd-6-1-1-RELEASE:1.35
	riastradh-drm2-base2:1.35
	riastradh-drm2-base1:1.35
	riastradh-drm2:1.35.0.12
	riastradh-drm2-base:1.35
	netbsd-6-1:1.35.0.16
	netbsd-6-0-2-RELEASE:1.35
	netbsd-6-1-RELEASE:1.35
	netbsd-6-1-RC4:1.35
	netbsd-6-1-RC3:1.35
	agc-symver:1.35.0.14
	agc-symver-base:1.35
	netbsd-6-1-RC2:1.35
	netbsd-6-1-RC1:1.35
	yamt-pagecache-base8:1.35
	netbsd-5-2:1.31.4.1.0.6
	netbsd-6-0-1-RELEASE:1.35
	yamt-pagecache-base7:1.35
	netbsd-5-2-RELEASE:1.31.4.1
	netbsd-5-2-RC1:1.31.4.1
	matt-nb6-plus-nbase:1.35
	yamt-pagecache-base6:1.35
	netbsd-6-0:1.35.0.10
	netbsd-6-0-RELEASE:1.35
	netbsd-6-0-RC2:1.35
	tls-maxphys:1.35.0.8
	tls-maxphys-base:1.35
	matt-nb6-plus:1.35.0.6
	matt-nb6-plus-base:1.35
	netbsd-6-0-RC1:1.35
	yamt-pagecache-base5:1.35
	yamt-pagecache-base4:1.35
	netbsd-6:1.35.0.4
	netbsd-6-base:1.35
	netbsd-5-1-2-RELEASE:1.31.4.1
	netbsd-5-1-1-RELEASE:1.31.4.1
	yamt-pagecache-base3:1.35
	yamt-pagecache-base2:1.35
	yamt-pagecache:1.35.0.2
	yamt-pagecache-base:1.35
	cherry-xenmp:1.34.0.4
	cherry-xenmp-base:1.34
	bouyer-quota2-nbase:1.34
	bouyer-quota2:1.34.0.2
	bouyer-quota2-base:1.34
	matt-mips64-premerge-20101231:1.34
	matt-nb5-mips64-premerge-20101231:1.31.10.1
	matt-nb5-pq3:1.31.4.1.0.4
	matt-nb5-pq3-base:1.31.4.1
	netbsd-5-1:1.31.4.1.0.2
	netbsd-5-1-RELEASE:1.31.4.1
	netbsd-5-1-RC4:1.31.4.1
	matt-nb5-mips64-k15:1.31.10.1
	netbsd-5-1-RC3:1.31.4.1
	netbsd-5-1-RC2:1.31.4.1
	netbsd-5-1-RC1:1.31.4.1
	netbsd-5-0-2-RELEASE:1.31
	matt-nb5-mips64-premerge-20091211:1.31
	matt-premerge-20091211:1.32
	matt-nb5-mips64-u2-k2-k4-k7-k8-k9:1.31
	matt-nb4-mips64-k7-u2a-k9b:1.31
	matt-nb5-mips64-u1-k1-k5:1.31
	matt-nb5-mips64:1.31.0.10
	netbsd-5-0-1-RELEASE:1.31
	jym-xensuspend-nbase:1.32
	netbsd-5-0:1.31.0.8
	netbsd-5-0-RELEASE:1.31
	netbsd-5-0-RC4:1.31
	netbsd-5-0-RC3:1.31
	netbsd-5-0-RC2:1.31
	jym-xensuspend:1.31.0.6
	jym-xensuspend-base:1.32
	netbsd-5-0-RC1:1.31
	netbsd-5:1.31.0.4
	netbsd-5-base:1.31
	matt-mips64-base2:1.31
	matt-mips64:1.30.0.24
	netbsd-4-0-1-RELEASE:1.30
	wrstuden-revivesa-base-3:1.31
	wrstuden-revivesa-base-2:1.31
	wrstuden-fixsa-newbase:1.30
	wrstuden-revivesa-base-1:1.30
	yamt-pf42-base4:1.30
	yamt-pf42-base3:1.30
	hpcarm-cleanup-nbase:1.30
	yamt-pf42-baseX:1.30
	yamt-pf42-base2:1.30
	wrstuden-revivesa:1.30.0.22
	wrstuden-revivesa-base:1.30
	yamt-pf42:1.30.0.20
	yamt-pf42-base:1.30
	keiichi-mipv6-nbase:1.30
	keiichi-mipv6:1.30.0.18
	keiichi-mipv6-base:1.30
	matt-armv6-nbase:1.30
	matt-armv6-prevmlocking:1.30
	wrstuden-fixsa-base-1:1.30
	netbsd-4-0:1.30.0.16
	netbsd-4-0-RELEASE:1.30
	cube-autoconf:1.30.0.14
	cube-autoconf-base:1.30
	netbsd-4-0-RC5:1.30
	netbsd-4-0-RC4:1.30
	netbsd-4-0-RC3:1.30
	netbsd-4-0-RC2:1.30
	netbsd-4-0-RC1:1.30
	matt-armv6:1.30.0.12
	matt-armv6-base:1.30
	matt-mips64-base:1.30
	hpcarm-cleanup:1.30.0.10
	hpcarm-cleanup-base:1.30
	netbsd-3-1-1-RELEASE:1.29
	netbsd-3-0-3-RELEASE:1.29
	wrstuden-fixsa:1.30.0.8
	wrstuden-fixsa-base:1.30
	abandoned-netbsd-4-base:1.30
	abandoned-netbsd-4:1.30.0.4
	netbsd-3-1:1.29.0.12
	netbsd-3-1-RELEASE:1.29
	netbsd-3-0-2-RELEASE:1.29
	netbsd-3-1-RC4:1.29
	netbsd-3-1-RC3:1.29
	netbsd-3-1-RC2:1.29
	netbsd-3-1-RC1:1.29
	netbsd-4:1.30.0.6
	netbsd-4-base:1.30
	chap-midi-nbase:1.30
	netbsd-3-0-1-RELEASE:1.29
	chap-midi:1.30.0.2
	chap-midi-base:1.30
	netbsd-3-0:1.29.0.10
	netbsd-3-0-RELEASE:1.29
	netbsd-3-0-RC6:1.29
	netbsd-3-0-RC5:1.29
	netbsd-3-0-RC4:1.29
	netbsd-3-0-RC3:1.29
	netbsd-3-0-RC2:1.29
	netbsd-3-0-RC1:1.29
	netbsd-2-0-3-RELEASE:1.29
	netbsd-2-1:1.29.0.8
	netbsd-2-1-RELEASE:1.29
	netbsd-2-1-RC6:1.29
	netbsd-2-1-RC5:1.29
	netbsd-2-1-RC4:1.29
	netbsd-2-1-RC3:1.29
	netbsd-2-1-RC2:1.29
	netbsd-2-1-RC1:1.29
	netbsd-2-0-2-RELEASE:1.29
	netbsd-3:1.29.0.6
	netbsd-3-base:1.29
	netbsd-2-0-1-RELEASE:1.29
	netbsd-2:1.29.0.4
	netbsd-2-base:1.29
	netbsd-2-0-RELEASE:1.29
	netbsd-2-0-RC5:1.29
	netbsd-2-0-RC4:1.29
	netbsd-2-0-RC3:1.29
	netbsd-2-0-RC2:1.29
	netbsd-2-0-RC1:1.29
	netbsd-2-0:1.29.0.2
	netbsd-2-0-base:1.29
	netbsd-1-6-PATCH002-RELEASE:1.28
	netbsd-1-6-PATCH002:1.28
	netbsd-1-6-PATCH002-RC4:1.28
	netbsd-1-6-PATCH002-RC3:1.28
	netbsd-1-6-PATCH002-RC2:1.28
	netbsd-1-6-PATCH002-RC1:1.28
	netbsd-1-6-PATCH001:1.28
	netbsd-1-6-PATCH001-RELEASE:1.28
	netbsd-1-6-PATCH001-RC3:1.28
	netbsd-1-6-PATCH001-RC2:1.28
	netbsd-1-6-PATCH001-RC1:1.28
	fvdl_fs64_base:1.28
	netbsd-1-6-RELEASE:1.28
	netbsd-1-6-RC3:1.28
	netbsd-1-6-RC2:1.28
	netbsd-1-6-RC1:1.28
	netbsd-1-6:1.28.0.2
	netbsd-1-6-base:1.28
	netbsd-1-5-PATCH003:1.20
	netbsd-1-5-PATCH002:1.20
	netbsd-1-5-PATCH001:1.20
	netbsd-1-5-RELEASE:1.20
	netbsd-1-5-BETA2:1.20
	netbsd-1-5-BETA:1.20
	netbsd-1-4-PATCH003:1.20
	netbsd-1-5-ALPHA2:1.20
	netbsd-1-5:1.20.0.10
	netbsd-1-5-base:1.20
	minoura-xpg4dl-base:1.20
	minoura-xpg4dl:1.20.0.8
	netbsd-1-4-PATCH002:1.20
	wrstuden-devbsize-19991221:1.20
	wrstuden-devbsize:1.20.0.6
	wrstuden-devbsize-base:1.20
	comdex-fall-1999:1.20.0.4
	comdex-fall-1999-base:1.20
	netbsd-1-4-PATCH001:1.20
	netbsd-1-4-RELEASE:1.20
	netbsd-1-4:1.20.0.2
	netbsd-1-4-base:1.20
	netbsd-1-3-PATCH003:1.13
	netbsd-1-3-PATCH003-CANDIDATE2:1.13
	netbsd-1-3-PATCH003-CANDIDATE1:1.13
	netbsd-1-3-PATCH003-CANDIDATE0:1.13
	netbsd-1-3-PATCH002:1.13
	netbsd-1-3-PATCH001:1.13
	netbsd-1-3-RELEASE:1.13
	netbsd-1-3-BETA:1.13
	netbsd-1-3:1.13.0.2
	netbsd-1-3-base:1.13
	lite-2:1.1.1.2
	CSRG:1.1.1
	netbsd-1-2-PATCH001:1.9
	netbsd-1-2-RELEASE:1.9
	netbsd-1-2-BETA:1.9
	netbsd-1-2:1.9.0.8
	netbsd-1-2-base:1.9
	netbsd-1-1-PATCH001:1.9
	netbsd-1-1-RELEASE:1.9
	netbsd-1-1:1.9.0.4
	netbsd-1-1-base:1.9
	netbsd-1-0-PATCH06:1.9
	netbsd-1-0-PATCH05:1.9
	netbsd-1-0-PATCH04:1.9
	netbsd-1-0-PATCH03:1.9
	netbsd-1-0-PATCH02:1.9
	netbsd-1-0-PATCH1:1.9
	netbsd-1-0-PATCH0:1.9
	netbsd-1-0-RELEASE:1.9
	netbsd-1-0:1.9.0.2
	netbsd-1-0-base:1.9
	netbsd-0-9-RELEASE:1.2
	netbsd-0-9-BETA:1.2
	netbsd-0-9-ALPHA2:1.2
	netbsd-0-9-ALPHA:1.2
	netbsd-0-9:1.2.0.2
	netbsd-0-9-base:1.2
	netbsd-0-8:1.1.1.1
	netbsd-alpha-1:1.1.1.1
	patchkit-0-2-2:1.1.1.1
	WFJ-386bsd-01:1.1.1.1
	WFJ-920714:1.1.1;
locks; strict;
comment	@ * @;


1.37
date	2024.01.14.17.39.19;	author christos;	state Exp;
branches;
next	1.36;
commitid	k2abORd0ADDmtrUE;

1.36
date	2024.01.14.17.16.10;	author christos;	state Exp;
branches;
next	1.35;
commitid	X3iU9eCrDUFtlrUE;

1.35
date	2011.09.16.15.39.30;	author joerg;	state Exp;
branches;
next	1.34;

1.34
date	2010.02.19.11.15.23;	author tron;	state Exp;
branches;
next	1.33;

1.33
date	2010.02.18.10.43.50;	author tron;	state Exp;
branches;
next	1.32;

1.32
date	2009.04.14.07.58.38;	author lukem;	state Exp;
branches;
next	1.31;

1.31
date	2008.07.21.14.19.28;	author lukem;	state Exp;
branches
	1.31.4.1
	1.31.6.1
	1.31.10.1;
next	1.30;

1.30
date	2006.01.04.01.58.05;	author perry;	state Exp;
branches
	1.30.22.1;
next	1.29;

1.29
date	2003.08.07.11.17.15;	author agc;	state Exp;
branches;
next	1.28;

1.28
date	2002.05.02.13.07.13;	author wiz;	state Exp;
branches;
next	1.27;

1.27
date	2002.03.23.21.36.08;	author enami;	state Exp;
branches;
next	1.26;

1.26
date	2002.03.23.21.32.21;	author enami;	state Exp;
branches;
next	1.25;

1.25
date	2002.03.23.21.29.38;	author enami;	state Exp;
branches;
next	1.24;

1.24
date	2002.03.23.21.27.14;	author enami;	state Exp;
branches;
next	1.23;

1.23
date	2002.03.23.21.20.21;	author enami;	state Exp;
branches;
next	1.22;

1.22
date	2002.03.23.21.10.40;	author enami;	state Exp;
branches;
next	1.21;

1.21
date	2001.10.19.06.09.56;	author yamt;	state Exp;
branches;
next	1.20;

1.20
date	99.03.05.22.52.09;	author kleink;	state Exp;
branches;
next	1.19;

1.19
date	99.03.05.22.31.06;	author mycroft;	state Exp;
branches;
next	1.18;

1.18
date	99.03.05.22.24.01;	author mycroft;	state Exp;
branches;
next	1.17;

1.17
date	99.02.14.19.10.28;	author christos;	state Exp;
branches;
next	1.16;

1.16
date	99.02.14.18.03.18;	author mjacob;	state Exp;
branches;
next	1.15;

1.15
date	99.02.13.15.53.17;	author explorer;	state Exp;
branches;
next	1.14;

1.14
date	98.10.13.17.03.39;	author wsanchez;	state Exp;
branches;
next	1.13;

1.13
date	97.10.20.02.40.26;	author mrg;	state Exp;
branches;
next	1.12;

1.12
date	97.10.19.19.33.37;	author mycroft;	state Exp;
branches;
next	1.11;

1.11
date	97.10.18.16.48.39;	author mrg;	state Exp;
branches;
next	1.10;

1.10
date	97.01.09.20.23.20;	author tls;	state Exp;
branches;
next	1.9;

1.9
date	94.01.03.03.11.06;	author andrew;	state Exp;
branches;
next	1.8;

1.8
date	93.11.04.05.43.30;	author jtc;	state Exp;
branches;
next	1.7;

1.7
date	93.10.12.23.32.20;	author jtc;	state Exp;
branches;
next	1.6;

1.6
date	93.10.12.22.39.43;	author jtc;	state Exp;
branches;
next	1.5;

1.5
date	93.08.27.22.31.06;	author jtc;	state Exp;
branches;
next	1.4;

1.4
date	93.08.17.00.37.11;	author jtc;	state Exp;
branches;
next	1.3;

1.3
date	93.08.01.18.03.04;	author mycroft;	state Exp;
branches;
next	1.2;

1.2
date	93.07.15.21.05.12;	author jtc;	state Exp;
branches;
next	1.1;

1.1
date	93.03.21.09.45.37;	author cgd;	state Exp;
branches
	1.1.1.1;
next	;

1.31.4.1
date	2010.03.06.21.19.11;	author sborrill;	state Exp;
branches;
next	;

1.31.6.1
date	2009.05.13.19.20.11;	author jym;	state Exp;
branches;
next	;

1.31.10.1
date	2010.04.21.05.27.12;	author matt;	state Exp;
branches;
next	;

1.30.22.1
date	2008.09.18.04.29.26;	author wrstuden;	state Exp;
branches;
next	;

1.1.1.1
date	93.03.21.09.45.37;	author cgd;	state Exp;
branches;
next	1.1.1.2;

1.1.1.2
date	95.05.02.22.28.04;	author mrg;	state Exp;
branches;
next	;


desc
@@


1.37
log
@Better check against st_size == 0 instead of st_dev == -1
@
text
@/*	$NetBSD: wc.c,v 1.36 2024/01/14 17:16:10 christos Exp $	*/

/*
 * Copyright (c) 1980, 1987, 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@@(#) Copyright (c) 1980, 1987, 1991, 1993\
 The Regents of the University of California.  All rights reserved.");
#endif /* not lint */

#ifndef lint
#if 0
static char sccsid[] = "@@(#)wc.c	8.2 (Berkeley) 5/2/95";
#else
__RCSID("$NetBSD: wc.c,v 1.36 2024/01/14 17:16:10 christos Exp $");
#endif
#endif /* not lint */

/* wc line, word, char count and optionally longest line. */

#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>

#include <ctype.h>
#include <fcntl.h>
#include <err.h>
#include <errno.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>

#ifdef NO_QUAD
typedef u_long wc_count_t;
# define WCFMT	" %7lu"
# define WCCAST unsigned long
#else
typedef u_quad_t wc_count_t;
# define WCFMT	" %7llu"
# define WCCAST	unsigned long long
#endif

static wc_count_t	tlinect, twordct, tcharct, tlongest;
static bool		doline, doword, dobyte, dochar, dolongest;
static int 		rval = 0;

static void	cnt(const char *);
static void	print_counts(wc_count_t, wc_count_t, wc_count_t, wc_count_t,
		    const char *);
__dead static void	usage(void);
static size_t	do_mb(wchar_t *, const char *, size_t, mbstate_t *,
		    size_t *, const char *);

int
main(int argc, char *argv[])
{
	int ch;

	setlocale(LC_ALL, "");

	while ((ch = getopt(argc, argv, "lwcmL")) != -1)
		switch (ch) {
		case 'l':
			doline = true;
			break;
		case 'w':
			doword = true;
			break;
		case 'm':
			dochar = true;
			dobyte = 0;
			break;
		case 'c':
			dochar = 0;
			dobyte = true;
			break;
		case 'L':
			dolongest = true;
			break;
		case '?':
		default:
			usage();
		}
	argv += optind;
	argc -= optind;

	/* Wc's flags are on by default. */
	if (!(doline || doword || dobyte || dochar || dolongest))
		doline = doword = dobyte = true;

	if (*argv == NULL) {
		cnt(NULL);
	} else {
		bool dototal = (argc > 1);

		do {
			cnt(*argv);
		} while(*++argv);

		if (dototal) {
			print_counts(tlinect, twordct, tcharct, tlongest,
			    "total");
		}
	}

	exit(rval);
}

static size_t
do_mb(wchar_t *wc, const char *p, size_t len, mbstate_t *st,
    size_t *retcnt, const char *file)
{
	size_t r;
	size_t c = 0;

	do {
		r = mbrtowc(wc, p, len, st);
		if (r == (size_t)-1) {
			warnx("%s: invalid byte sequence", file);
			rval = 1;

			/* XXX skip 1 byte */
			len--;
			p++;
			memset(st, 0, sizeof(*st));
			continue;
		} else if (r == (size_t)-2)
			break;
		else if (r == 0)
			r = 1;
		c++;
		if (wc)
			wc++;
		len -= r;
		p += r;
	} while (len > 0);

	*retcnt = c;

	return (r);
}

static void
cnt(const char *file)
{
	u_char buf[MAXBSIZE];
	wchar_t wbuf[MAXBSIZE];
	struct stat sb;
	wc_count_t charct, linect, wordct, longest;
	mbstate_t st;
	u_char *C;
	wchar_t *WC;
	const char *name;			/* filename or <stdin> */
	size_t r = 0;
	int fd, len = 0;

	linect = wordct = charct = longest = 0;
	if (file != NULL) {
		if ((fd = open(file, O_RDONLY, 0)) < 0) {
			warn("%s", file);
			rval = 1;
			return;
		}
		name = file;
	} else {
		fd = STDIN_FILENO;
		name = "<stdin>";
	}

	if (dochar || doword || dolongest)
		(void)memset(&st, 0, sizeof(st));

	if (!(doword || dolongest)) {
		/*
		 * line counting is split out because it's a lot
		 * faster to get lines than to get words, since
		 * the word count requires some logic.
		 */
		if (doline || dochar) {
			while ((len = read(fd, buf, MAXBSIZE)) > 0) {
				if (dochar) {
					size_t wlen;

					r = do_mb(0, (char *)buf, (size_t)len,
					    &st, &wlen, name);
					charct += wlen;
				} else if (dobyte)
					charct += len;
				if (doline) {
					for (C = buf; len--; ++C) {
						if (*C == '\n')
							++linect;
					}
				}
			}
		}

		/*
		 * if all we need is the number of characters and
		 * it's a directory or a regular or linked file, just
		 * stat the puppy.  We avoid testing for it not being
		 * a special device in case someone adds a new type
		 * of inode.
		 */
		else if (dobyte) {
			if (fstat(fd, &sb)) {
				warn("%s", name);
				rval = 1;
			} else {
				if (sb.st_size != 0 &&
				    (S_ISREG(sb.st_mode) ||
				    S_ISLNK(sb.st_mode) ||
				    S_ISDIR(sb.st_mode))) {
					charct = sb.st_size;
				} else {
					while ((len =
					    read(fd, buf, MAXBSIZE)) > 0)
						charct += len;
				}
			}
		}
	} else {
		/* do it the hard way... */
		wc_count_t linelen;
                bool       gotsp;

		linelen = 0;
		gotsp = true;
		while ((len = read(fd, buf, MAXBSIZE)) > 0) {
			size_t wlen;

			r = do_mb(wbuf, (char *)buf, (size_t)len, &st, &wlen,
			    name);
			if (dochar) {
				charct += wlen;
			} else if (dobyte) {
				charct += len;
			}
			for (WC = wbuf; wlen--; ++WC) {
				if (iswspace(*WC)) {
					gotsp = true;
					if (*WC == L'\n') {
						++linect;
						if (linelen > longest)
							longest = linelen;
						linelen = 0;
					} else {
						linelen++;
					}
				} else {
					/*
					 * This line implements the POSIX
					 * spec, i.e. a word is a "maximal
					 * string of characters delimited by
					 * whitespace."  Notice nothing was
					 * said about a character being
					 * printing or non-printing.
					 */
					if (gotsp) {
						gotsp = false;
						++wordct;
					}

					linelen++;
				}
			}
		}
	}

	if (len == -1) {
		warn("%s", name);
		rval = 1;
	}
	if (dochar && r == (size_t)-2) {
		warnx("%s: incomplete multibyte character", name);
		rval = 1;
	}

	print_counts(linect, wordct, charct, longest, file);

	/*
	 * don't bother checkint doline, doword, or dobyte --- speeds
	 * up the common case
	 */
	tlinect += linect;
	twordct += wordct;
	tcharct += charct;
	if (dolongest && longest > tlongest)
		tlongest = longest;

	if (close(fd)) {
		warn("%s", name);
		rval = 1;
	}
}

static void
print_counts(wc_count_t lines, wc_count_t words, wc_count_t chars,
    wc_count_t longest, const char *name)
{

	if (doline)
		(void)printf(WCFMT, (WCCAST)lines);
	if (doword)
		(void)printf(WCFMT, (WCCAST)words);
	if (dobyte || dochar)
		(void)printf(WCFMT, (WCCAST)chars);
	if (dolongest)
		(void)printf(WCFMT, (WCCAST)longest);

	if (name != NULL)
		(void)printf(" %s\n", name);
	else
		(void)putchar('\n');
}

static void
usage(void)
{

	(void)fprintf(stderr, "usage: wc [-c | -m] [-Llw] [file ...]\n");
	exit(1);
}
@


1.36
log
@PR/57854: Richardo Branco: wc -c does not work on procfs/kernfs
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.35 2011/09/16 15:39:30 joerg Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.35 2011/09/16 15:39:30 joerg Exp $");
d242 1
a242 2
				/* st_dev == -1 for kernfs/procfs files */
				if (sb.st_dev != (dev_t)-1 &&
@


1.35
log
@Use __dead
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.34 2010/02/19 11:15:23 tron Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.34 2010/02/19 11:15:23 tron Exp $");
d242 3
a244 1
				if (S_ISREG(sb.st_mode) ||
d246 1
a246 1
				    S_ISDIR(sb.st_mode)) {
@


1.34
log
@Report the number of characters, not the number of bytes in the
longest line.

Problem pointed out by YAMAMOTO Takashi on "tech-userlevel" mailing list.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.33 2010/02/18 10:43:50 tron Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.33 2010/02/18 10:43:50 tron Exp $");
d82 1
a82 1
static void	usage(void);
a84 1
int	main(int, char *[]);
@


1.33
log
@Add support for "-L" option (longest line) as present in the GNU and
FreeBSD version of "wc".

No objections on "tech-userlevel" mailing list.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.32 2009/04/14 07:58:38 lukem Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.32 2009/04/14 07:58:38 lukem Exp $");
d188 1
a188 1
	int fd, gotsp, len = 0;
d203 2
a204 2
	if (dochar || doword)
		memset(&st, 0, sizeof(st));
d206 1
a206 1
	if (!doword) {
d212 1
a212 2
		if (doline || dochar || dolongest) {
			wc_count_t llen = 0;
d222 1
a222 1
				if (doline || dolongest) {
d224 1
a224 1
						if (*C == '\n') {
a225 6
							if (llen > longest)
								longest = llen;
							llen = 0;
						} else {
							llen++;
						}
d256 2
a257 1
		wc_count_t llen = 0;
d259 2
a260 1
		gotsp = 1;
d273 1
a273 1
					gotsp = 1;
d276 3
a278 3
						if (llen > longest)
							longest = llen;
						llen = 0;
d280 1
a280 1
						llen++;
d292 1
a292 1
						gotsp = 0;
d296 1
a296 1
					llen++;
@


1.32
log
@Fix WARNS=4 issues (-Wshadow -Wcast-qual)
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.31 2008/07/21 14:19:28 lukem Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.31 2008/07/21 14:19:28 lukem Exp $");
d46 1
a46 1
/* wc line, word and char count */
d57 1
d75 2
a76 2
static wc_count_t	tlinect, twordct, tcharct;
static int		doline, doword, dobyte, dochar;
d80 2
a81 1
static void	print_counts(wc_count_t, wc_count_t, wc_count_t, const char *);
d94 1
a94 1
	while ((ch = getopt(argc, argv, "lwcm")) != -1)
d97 1
a97 1
			doline = 1;
d100 1
a100 1
			doword = 1;
d103 1
a103 1
			dochar = 1;
d108 4
a111 1
			dobyte = 1;
d121 2
a122 2
	if (doline + doword + dobyte + dochar == 0)
		doline = doword = dobyte = 1;
d124 1
a124 1
	if (!*argv) {
d127 1
a127 1
		int dototal = (argc > 1);
d133 4
a136 2
		if (dototal)
			print_counts(tlinect, twordct, tcharct, "total");
d182 1
a182 1
	wc_count_t charct, linect, wordct;
d190 2
a191 2
	linect = wordct = charct = 0;
	if (file) {
d212 2
a213 1
		if (doline || dochar) {
d223 3
a225 3
				if (doline)
					for (C = buf; len--; ++C)
						if (*C == '\n')
d227 8
d263 2
d273 1
a273 1
			} else if (dobyte)
d275 1
d281 5
d300 2
d316 1
a316 1
	print_counts(linect, wordct, charct, file);
d325 2
d336 1
a336 1
    const char *name)
d340 1
a340 1
		printf(WCFMT, (WCCAST)lines);
d342 1
a342 1
		printf(WCFMT, (WCCAST)words);
d344 3
a346 1
		printf(WCFMT, (WCCAST)chars);
d348 2
a349 2
	if (name)
		printf(" %s\n", name);
d351 1
a351 1
		printf("\n");
d358 1
a358 1
	(void)fprintf(stderr, "usage: wc [-c | -m] [-lw] [file ...]\n");
@


1.31
log
@Remove the \n and tabs from the __COPYRIGHT() strings.
Tweak to use a consistent format.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.30 2006/01/04 01:58:05 perry Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.30 2006/01/04 01:58:05 perry Exp $");
d78 2
a79 2
static void	cnt(char *);
static void	print_counts(wc_count_t, wc_count_t, wc_count_t, char *);
d136 2
a137 2
do_mb(wchar_t *wc, const char *p, size_t mblen, mbstate_t *st,
    size_t *cnt, const char *file)
d143 1
a143 1
		r = mbrtowc(wc, p, mblen, st);
d149 1
a149 1
			mblen--;
d160 1
a160 1
		mblen -= r;
d162 1
a162 1
	} while (mblen > 0);
d164 1
a164 1
	*cnt = c;
d170 1
a170 1
cnt(char *file)
d179 1
a179 1
	char *name;				/* filename or <stdin> */
d307 2
a308 1
print_counts(wc_count_t lines, wc_count_t words, wc_count_t chars, char *name)
@


1.31.10.1
log
@sync to netbsd-5
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.31.4.1 2010/03/06 21:19:11 sborrill Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.31.4.1 2010/03/06 21:19:11 sborrill Exp $");
d46 1
a46 1
/* wc line, word, char count and optionally longest line. */
a56 1
#include <stdbool.h>
d74 2
a75 2
static wc_count_t	tlinect, twordct, tcharct, tlongest;
static bool		doline, doword, dobyte, dochar, dolongest;
d78 2
a79 3
static void	cnt(const char *);
static void	print_counts(wc_count_t, wc_count_t, wc_count_t, wc_count_t,
		    const char *);
d92 1
a92 1
	while ((ch = getopt(argc, argv, "lwcmL")) != -1)
d95 1
a95 1
			doline = true;
d98 1
a98 1
			doword = true;
d101 1
a101 1
			dochar = true;
d106 1
a106 4
			dobyte = true;
			break;
		case 'L':
			dolongest = true;
d116 2
a117 2
	if (!(doline || doword || dobyte || dochar || dolongest))
		doline = doword = dobyte = true;
d119 1
a119 1
	if (*argv == NULL) {
d122 1
a122 1
		bool dototal = (argc > 1);
d128 2
a129 4
		if (dototal) {
			print_counts(tlinect, twordct, tcharct, tlongest,
			    "total");
		}
d136 2
a137 2
do_mb(wchar_t *wc, const char *p, size_t len, mbstate_t *st,
    size_t *retcnt, const char *file)
d143 1
a143 1
		r = mbrtowc(wc, p, len, st);
d149 1
a149 1
			len--;
d160 1
a160 1
		len -= r;
d162 1
a162 1
	} while (len > 0);
d164 1
a164 1
	*retcnt = c;
d170 1
a170 1
cnt(const char *file)
d175 1
a175 1
	wc_count_t charct, linect, wordct, longest;
d179 1
a179 1
	const char *name;			/* filename or <stdin> */
d181 1
a181 1
	int fd, len = 0;
d183 2
a184 2
	linect = wordct = charct = longest = 0;
	if (file != NULL) {
d196 2
a197 2
	if (dochar || doword || dolongest)
		(void)memset(&st, 0, sizeof(st));
d199 1
a199 1
	if (!(doword || dolongest)) {
d215 2
a216 2
				if (doline) {
					for (C = buf; len--; ++C) {
a218 2
					}
				}
d247 1
a247 5
		wc_count_t linelen;
                bool       gotsp;

		linelen = 0;
		gotsp = true;
d255 1
a255 1
			} else if (dobyte) {
a256 1
			}
d259 1
a259 1
					gotsp = true;
a261 5
						if (linelen > longest)
							longest = linelen;
						linelen = 0;
					} else {
						linelen++;
d273 1
a273 1
						gotsp = false;
a275 2

					linelen++;
d290 1
a290 1
	print_counts(linect, wordct, charct, longest, file);
a298 2
	if (dolongest && longest > tlongest)
		tlongest = longest;
d307 1
a307 2
print_counts(wc_count_t lines, wc_count_t words, wc_count_t chars,
    wc_count_t longest, const char *name)
d311 1
a311 1
		(void)printf(WCFMT, (WCCAST)lines);
d313 1
a313 1
		(void)printf(WCFMT, (WCCAST)words);
d315 1
a315 3
		(void)printf(WCFMT, (WCCAST)chars);
	if (dolongest)
		(void)printf(WCFMT, (WCCAST)longest);
d317 2
a318 2
	if (name != NULL)
		(void)printf(" %s\n", name);
d320 1
a320 1
		(void)putchar('\n');
d327 1
a327 1
	(void)fprintf(stderr, "usage: wc [-c | -m] [-Llw] [file ...]\n");
@


1.31.4.1
log
@Pull up the following revisions(s) (requested by tron in ticket #1313):
	usr.bin/wc/wc.c:	revision 1.32-1.34
	usr.bin/wc/wc.1:	revision 1.14-1.15

Add support for "-L" option (longest line) as present in the GNU and
FreeBSD versions of "wc".
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.31 2008/07/21 14:19:28 lukem Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.31 2008/07/21 14:19:28 lukem Exp $");
d46 1
a46 1
/* wc line, word, char count and optionally longest line. */
a56 1
#include <stdbool.h>
d74 2
a75 2
static wc_count_t	tlinect, twordct, tcharct, tlongest;
static bool		doline, doword, dobyte, dochar, dolongest;
d78 2
a79 3
static void	cnt(const char *);
static void	print_counts(wc_count_t, wc_count_t, wc_count_t, wc_count_t,
		    const char *);
d92 1
a92 1
	while ((ch = getopt(argc, argv, "lwcmL")) != -1)
d95 1
a95 1
			doline = true;
d98 1
a98 1
			doword = true;
d101 1
a101 1
			dochar = true;
d106 1
a106 4
			dobyte = true;
			break;
		case 'L':
			dolongest = true;
d116 2
a117 2
	if (!(doline || doword || dobyte || dochar || dolongest))
		doline = doword = dobyte = true;
d119 1
a119 1
	if (*argv == NULL) {
d122 1
a122 1
		bool dototal = (argc > 1);
d128 2
a129 4
		if (dototal) {
			print_counts(tlinect, twordct, tcharct, tlongest,
			    "total");
		}
d136 2
a137 2
do_mb(wchar_t *wc, const char *p, size_t len, mbstate_t *st,
    size_t *retcnt, const char *file)
d143 1
a143 1
		r = mbrtowc(wc, p, len, st);
d149 1
a149 1
			len--;
d160 1
a160 1
		len -= r;
d162 1
a162 1
	} while (len > 0);
d164 1
a164 1
	*retcnt = c;
d170 1
a170 1
cnt(const char *file)
d175 1
a175 1
	wc_count_t charct, linect, wordct, longest;
d179 1
a179 1
	const char *name;			/* filename or <stdin> */
d181 1
a181 1
	int fd, len = 0;
d183 2
a184 2
	linect = wordct = charct = longest = 0;
	if (file != NULL) {
d196 2
a197 2
	if (dochar || doword || dolongest)
		(void)memset(&st, 0, sizeof(st));
d199 1
a199 1
	if (!(doword || dolongest)) {
d215 2
a216 2
				if (doline) {
					for (C = buf; len--; ++C) {
a218 2
					}
				}
d247 1
a247 5
		wc_count_t linelen;
                bool       gotsp;

		linelen = 0;
		gotsp = true;
d255 1
a255 1
			} else if (dobyte) {
a256 1
			}
d259 1
a259 1
					gotsp = true;
a261 5
						if (linelen > longest)
							longest = linelen;
						linelen = 0;
					} else {
						linelen++;
d273 1
a273 1
						gotsp = false;
a275 2

					linelen++;
d290 1
a290 1
	print_counts(linect, wordct, charct, longest, file);
a298 2
	if (dolongest && longest > tlongest)
		tlongest = longest;
d307 1
a307 2
print_counts(wc_count_t lines, wc_count_t words, wc_count_t chars,
    wc_count_t longest, const char *name)
d311 1
a311 1
		(void)printf(WCFMT, (WCCAST)lines);
d313 1
a313 1
		(void)printf(WCFMT, (WCCAST)words);
d315 1
a315 3
		(void)printf(WCFMT, (WCCAST)chars);
	if (dolongest)
		(void)printf(WCFMT, (WCCAST)longest);
d317 2
a318 2
	if (name != NULL)
		(void)printf(" %s\n", name);
d320 1
a320 1
		(void)putchar('\n');
d327 1
a327 1
	(void)fprintf(stderr, "usage: wc [-c | -m] [-Llw] [file ...]\n");
@


1.31.6.1
log
@Sync with HEAD.

Third (and last) commit. See http://mail-index.netbsd.org/source-changes/2009/05/13/msg221222.html
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.32 2009/04/14 07:58:38 lukem Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.32 2009/04/14 07:58:38 lukem Exp $");
d78 2
a79 2
static void	cnt(const char *);
static void	print_counts(wc_count_t, wc_count_t, wc_count_t, const char *);
d136 2
a137 2
do_mb(wchar_t *wc, const char *p, size_t len, mbstate_t *st,
    size_t *retcnt, const char *file)
d143 1
a143 1
		r = mbrtowc(wc, p, len, st);
d149 1
a149 1
			len--;
d160 1
a160 1
		len -= r;
d162 1
a162 1
	} while (len > 0);
d164 1
a164 1
	*retcnt = c;
d170 1
a170 1
cnt(const char *file)
d179 1
a179 1
	const char *name;			/* filename or <stdin> */
d307 1
a307 2
print_counts(wc_count_t lines, wc_count_t words, wc_count_t chars,
    const char *name)
@


1.30
log
@de-__P, ANSIfy prototypes
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.29 2003/08/07 11:17:15 agc Exp $	*/
d34 2
a35 2
__COPYRIGHT("@@(#) Copyright (c) 1980, 1987, 1991, 1993\n\
	The Regents of the University of California.  All rights reserved.\n");
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.29 2003/08/07 11:17:15 agc Exp $");
@


1.30.22.1
log
@Sync with wrstuden-revivesa-base-2.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.30 2006/01/04 01:58:05 perry Exp $	*/
d34 2
a35 2
__COPYRIGHT("@@(#) Copyright (c) 1980, 1987, 1991, 1993\
 The Regents of the University of California.  All rights reserved.");
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.30 2006/01/04 01:58:05 perry Exp $");
@


1.29
log
@Move UCB-licensed code from 4-clause to 3-clause licence.

Patches provided by Joel Baker in PR 22365, verified by myself.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.28 2002/05/02 13:07:13 wiz Exp $	*/
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.28 2002/05/02 13:07:13 wiz Exp $");
d78 6
a83 6
static void	cnt __P((char *));
static void	print_counts __P((wc_count_t, wc_count_t, wc_count_t, char *));
static void	usage __P((void));
static size_t	do_mb __P((wchar_t *, const char *, size_t, mbstate_t *,
		    size_t *, const char *));
int	main __P((int, char *[]));
d86 1
a86 3
main(argc, argv)
	int argc;
	char *argv[];
d136 2
a137 7
do_mb(wc, p, mblen, st, cnt, file)
	wchar_t *wc;
	const char *p;
	size_t mblen;
	mbstate_t *st;
	size_t *cnt;
	const char *file;
d170 1
a170 2
cnt(file)
	char *file;
d307 1
a307 5
print_counts(lines, words, chars, name)
	wc_count_t lines;
	wc_count_t words;
	wc_count_t chars;
	char *name;
d324 1
a324 1
usage()
@


1.28
log
@Mention -m in usage. bin/16594 by Ryan Younce.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.27 2002/03/23 21:36:08 enami Exp $	*/
d15 1
a15 5
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
d42 1
a42 1
__RCSID("$NetBSD: wc.c,v 1.27 2002/03/23 21:36:08 enami Exp $");
@


1.27
log
@Don't pass NULL to warn() etc.  Instead, use "<stdin>" to warn about stdin.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.26 2002/03/23 21:32:21 enami Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.26 2002/03/23 21:32:21 enami Exp $");
d343 1
a343 1
	(void)fprintf(stderr, "usage: wc [-clw] [file ...]\n");
@


1.26
log
@Actually skip the first byte of invalid byte sequence.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.25 2002/03/23 21:29:38 enami Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.25 2002/03/23 21:29:38 enami Exp $");
d191 1
d202 1
d205 1
d223 1
a223 1
					    &st, &wlen, file);
d243 1
a243 1
				warn("%s", file);
d264 1
a264 1
			    file);
d294 1
a294 1
		warn("%s", file);
d298 1
a298 1
		warnx("%s: incomplete multibyte character", file);
d302 1
a302 1
	print_counts(linect, wordct, charct, file ? file : 0);
d313 1
a313 1
		warn("%s", file);
@


1.25
log
@One more; Don't put space before function call op.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.24 2002/03/23 21:27:14 enami Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.24 2002/03/23 21:27:14 enami Exp $");
d163 1
@


1.24
log
@- Remove unnecessary cast.
- Other misc. KNF changes.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.23 2002/03/23 21:20:21 enami Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.23 2002/03/23 21:20:21 enami Exp $");
d290 1
a290 1
		warn ("%s", file);
d294 1
a294 1
		warnx ("%s: incomplete multibyte character", file);
d309 1
a309 1
		warn ("%s", file);
@


1.23
log
@Fix whitespace usage.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.22 2002/03/23 21:10:40 enami Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.22 2002/03/23 21:10:40 enami Exp $");
d99 1
a99 1
		switch ((char)ch) {
d176 1
a176 1
	return r;
d183 5
a189 7
	short gotsp;
	int len = 0;
	wc_count_t linect, wordct, charct;
	struct stat sb;
	int fd;
	u_char buf[MAXBSIZE];
	wchar_t wbuf[MAXBSIZE];
d191 1
a191 1
	mbstate_t st;
@


1.22
log
@Don't include same file twice.  Sort includes alphabetically.
Don't place sys/*.h and *.h mixed.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.21 2001/10/19 06:09:56 yamt Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.21 2001/10/19 06:09:56 yamt Exp $");
d85 2
a86 2
static size_t do_mb __P((wchar_t *, const char *, size_t, mbstate_t *,
		size_t *, const char *));
d99 1
a99 1
		switch((char)ch) {
d135 1
a135 1
			print_counts(tlinect, twordct, tcharct, "total"); 
d160 2
a161 2
			mblen --;
			p ++;
d163 1
a163 2
		}
		else if (r == (size_t)-2)
d167 1
a167 1
		c ++;
d169 1
a169 1
			wc ++;
d178 1
a178 1
				
d202 1
a202 1
	} else  {
d208 1
a208 1
	
d220 2
a221 1
					r = do_mb(0, (char *)buf, (size_t)len, &st, &wlen, file);
d223 1
a223 2
				}
				else if (dobyte)
d249 2
a250 1
					while ((len = read(fd, buf, MAXBSIZE)) > 0)
d255 1
a255 3
	}
	else
	{
d261 2
a262 1
			r = do_mb(wbuf, (char *)buf, (size_t)len, &st, &wlen, file);
d265 1
a265 2
			}
			else if (dobyte)
d302 4
a305 2
	/* don't bother checkint doline, doword, or dobyte --- speeds
           up the common case */
d340 1
@


1.21
log
@- implement -m.(count characters instead of bytes)
- use iswspace instead of isspace for -w.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.20 1999/03/05 22:52:09 kleink Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.20 1999/03/05 22:52:09 kleink Exp $");
d53 1
a54 1
#include <sys/types.h>
d56 1
d58 1
a58 1
#include <unistd.h>
d60 1
a61 1

a63 6
#include <locale.h>
#include <ctype.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
a64 1
#include <err.h>
@


1.20
log
@Normalize usage string.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.19 1999/03/05 22:31:06 mycroft Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.19 1999/03/05 22:31:06 mycroft Exp $");
d71 2
d85 1
a85 1
static int		doline, doword, dochar;
d91 2
a111 1
		case 'c':
d114 5
d128 2
a129 2
	if (doline + doword + dochar == 0)
		doline = doword = dochar = 1;
d147 39
d191 1
d193 1
a193 1
	int len;
d198 3
d212 3
d222 1
a222 1
		if (doline) {
d224 12
a235 8
				charct += len;
				for (C = buf; len--; ++C)
					if (*C == '\n')
						++linect;
			}
			if (len == -1) {
				warn ("%s", file);
				rval = 1;
d246 1
a246 1
		else if (dochar) {
a257 4
					if (len == -1) {
						warn ("%s", file);
						rval = 1;
					}
d267 10
a276 3
			charct += len;
			for (C = buf; len--; ++C) {
				if (isspace(*C)) {
d278 1
a278 1
					if (*C == '\n') {
d297 9
a305 4
		if (len == -1) {
			warn("%s", file);
			rval = 1;
		}
d310 1
a310 1
	/* don't bother checkint doline, doword, or dochar --- speeds
d334 1
a334 1
	if (dochar)
@


1.19
log
@Don't print a trailing space when counting from stdin.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.18 1999/03/05 22:24:01 mycroft Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.18 1999/03/05 22:24:01 mycroft Exp $");
d280 1
a280 1
	(void)fprintf(stderr, "usage: wc [-clw] [files]\n");
@


1.18
log
@Make the output format match what it used to be.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.17 1999/02/14 19:10:28 christos Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.17 1999/02/14 19:10:28 christos Exp $");
d132 1
a132 1
		if (dototal) {
a133 1
		}
d242 1
a242 1
	print_counts(linect, wordct, charct, file ? file : "");
d271 4
a274 1
	printf(" %s\n", name);
@


1.17
log
@Quad portability fixes:
- Use %llu instead of %qu
- Don't use quad types if NO_QUAD is defined
- Always cast to the appropriate type in printf.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.16 1999/02/14 18:03:18 mjacob Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.16 1999/02/14 18:03:18 mjacob Exp $");
d74 1
a74 1
# define WCFMT	" %lu"
d78 1
a78 1
# define WCFMT	" %llu"
@


1.16
log
@Hopefully somebody better at this than I can correct this somewhat
iffy change. The problem with the last checkin is twofold- first %q
should refer to quad_t, not u_int64_r. Second, for the alpha compiler,
%q is taken to be 'long long'- which is definitely not the same as
u_int64_t. Take home lesson- didn't build on alpha.

I thought about an #ifdef __alpha__- but that's wrong, so I put in a runtime
determinant to set a constant format string. Like I said, I hope somebody
better than I can fix it right.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.15 1999/02/13 15:53:17 explorer Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.15 1999/02/13 15:53:17 explorer Exp $");
d72 11
a82 1
static u_int64_t	tlinect, twordct, tcharct;
a84 1
static char *qfmt;
d87 1
a87 1
static void	print_counts __P((u_int64_t, u_int64_t, u_int64_t, char *));
a98 4
	if (sizeof (u_int64_t) > 4)
		qfmt = " %7u";
	else
		qfmt = " %7qu";
d147 1
a147 1
	u_int64_t linect, wordct, charct;
d259 3
a261 3
	u_int64_t lines;
	u_int64_t words;
	u_int64_t chars;
d266 1
a266 1
		printf(qfmt, lines);
d268 1
a268 1
		printf(qfmt, words);
d270 1
a270 1
		printf(qfmt, chars);
@


1.15
log
@use u_int64_t for line, word, and character counts.  It bothers me to see wc -c
return -2146435072 characters for files > 2G.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.14 1998/10/13 17:03:39 wsanchez Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.14 1998/10/13 17:03:39 wsanchez Exp $");
d75 1
d90 4
d261 1
a261 1
		printf(" %7qu", lines);
d263 1
a263 1
		printf(" %7qu", words);
d265 1
a265 1
		printf(" %7qu", chars);
@


1.14
log
@Use unsigned long instead of ulong
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.13 1997/10/20 02:40:26 mrg Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.13 1997/10/20 02:40:26 mrg Exp $");
d54 1
d72 1
a72 1
static unsigned long	tlinect, twordct, tcharct;
d77 1
a77 1
static void	print_counts __P((long, long, long, char *));
d137 1
a137 1
	u_long linect, wordct, charct;
d249 3
a251 3
	long lines;
	long words;
	long chars;
d256 1
a256 1
		printf(" %7ld", lines);
d258 1
a258 1
		printf(" %7ld", words);
d260 1
a260 1
		printf(" %7ld", chars);
@


1.13
log
@WARNSify;  deprecate register;  clean up .Nm
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.12 1997/10/19 19:33:37 mycroft Exp $	*/
d46 1
a46 1
__RCSID("$NetBSD: wc.c,v 1.11 1997/10/18 16:48:39 mrg Exp $");
d71 3
a73 3
static ulong	tlinect, twordct, tcharct;
static int	doline, doword, dochar;
static int 	rval = 0;
@


1.12
log
@Use S_IS*(), not S_IF*.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.11 1997/10/18 16:48:39 mrg Exp $	*/
d36 1
d38 2
a39 3
static char copyright[] =
"@@(#) Copyright (c) 1980, 1987, 1991, 1993\n\
	The Regents of the University of California.  All rights reserved.\n";
d46 1
a46 1
static char rcsid[] = "$NetBSD: wc.c,v 1.11 1997/10/18 16:48:39 mrg Exp $";
d78 1
d85 1
a85 1
	register int ch;
d133 4
a136 4
	register u_char *C;
	register short gotsp;
	register int ch, len;
	register u_long linect, wordct, charct;
@


1.11
log
@merge lite-2.
@
text
@d1 1
a1 1
/*	$NetBSD: wc.c,v 1.10 1997/01/09 20:23:20 tls Exp $	*/
d46 1
a46 1
static char rcsid[] = "$NetBSD: wc.c,v 1.10 1997/01/09 20:23:20 tls Exp $";
a177 2
			int ifmt;

d182 3
a184 3
				ifmt = sb.st_mode & S_IFMT;
				if (ifmt == S_IFREG || ifmt == S_IFLNK
					|| ifmt == S_IFDIR) {
@


1.10
log
@RCS ID police
@
text
@d1 1
a1 1
/*	$NetBSD$	*/
d4 2
a5 2
 * Copyright (c) 1980, 1987 Regents of the University of California.
 * All rights reserved.
d37 3
a39 3
char copyright[] =
"@@(#) Copyright (c) 1980, 1987 Regents of the University of California.\n\
 All rights reserved.\n";
d43 5
a47 2
/*static char sccsid[] = "from: @@(#)wc.c	5.7 (Berkeley) 3/2/91";*/
static char rcsid[] = "$NetBSD: wc.c,v 1.9 1994/01/03 03:11:06 andrew Exp $";
d52 6
d59 1
d71 1
a71 3
static void	print_counts();
static void	cnt();
static long	tlinect, twordct, tcharct;
d75 4
d82 1
a82 1
	char **argv;
a83 1
	extern int optind;
d102 1
a102 2
			fprintf(stderr, "usage: wc [-c | -m] [-lw] [file ...]\n");
			exit(1);
d107 2
a108 6
	/*
	 * wc is unusual in that its flags are on by default, so,
	 * if you don't get any arguments, you have to turn them
	 * all on.
	 */
	if (!doline && !doword && !dochar) {
a109 1
	}
d112 1
a112 1
		cnt((char *)NULL);
d121 1
a121 1
			print_counts (tlinect, twordct, tcharct, "total"); 
a127 1

d134 3
a136 3
	register int len;
	register long linect, wordct, charct;
	struct stat sbuf;
d143 1
a143 1
			warn ("%s", file);
d158 1
a158 1
			while((len = read(fd, buf, MAXBSIZE)) > 0) {
d180 2
a181 2
			if (fstat(fd, &sbuf)) {
				warn ("%s", file);
d184 1
a184 1
				ifmt = sbuf.st_mode & S_IFMT;
d187 1
a187 1
					charct = sbuf.st_size;
d189 1
a189 1
					while((len = read(fd, buf, MAXBSIZE)) > 0)
d206 1
a206 1
				if (isspace (*C)) {
d228 1
a228 1
			warn ("%s", file);
d233 1
a233 1
	print_counts (linect, wordct, charct, file ? file : "");
d247 2
a248 3

void
print_counts (lines, words, chars, name)
d262 8
a269 1
	printf (" %s\n", name);
@


1.9
log
@Fixed problems with wc -c when reading from stdin.
@
text
@d1 2
d44 1
a44 1
static char rcsid[] = "$Id: wc.c,v 1.8 1993/11/04 05:43:30 jtc Exp $";
@


1.8
log
@Checkin minor tweaks before giving a copy to the FreeBSD folks.
@
text
@d42 1
a42 1
static char rcsid[] = "$Id: wc.c,v 1.7 1993/10/12 23:32:20 jtc Exp $";
d182 7
@


1.7
log
@Streamline the char/word/line counting logic in anticipation of multibyte
character support.
@
text
@d42 1
a42 1
static char rcsid[] = "$Id: wc.c,v 1.6 1993/10/12 22:39:43 jtc Exp $";
d59 1
d114 1
a114 7
			if (doline)
				printf(" %7ld", tlinect);
			if (doword)
				printf(" %7ld", twordct);
			if (dochar)
				printf(" %7ld", tcharct);
			puts(" total");
d189 2
a190 6
		for (gotsp = 1; (len = read(fd, buf, MAXBSIZE));) {
			if (len == -1) {
				warn ("%s", file);
				rval = 1;
				break;
			}
d214 4
d220 11
a230 3
	if (doline) {
		tlinect += linect;
		printf(" %7ld", linect);
d232 17
a248 8
	if (doword) {
		twordct += wordct;
		printf(" %7ld", wordct);
	}
	if (dochar) {
		tcharct += charct;
		printf(" %7ld", charct);
	}
d250 1
a250 2
	printf (" %s\n", file ? file : "");
	close(fd);
@


1.6
log
@Like cat, set the return-value variable "rval" instead of exiting when
we encounter run-time errors.
Update usage message.
@
text
@d42 1
a42 1
static char rcsid[] = "$Id: wc.c,v 1.5 1993/08/27 22:31:06 jtc Exp $";
a46 3
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
d50 1
d53 3
d57 1
d72 2
d88 1
a88 1
			fprintf(stderr, "usage: wc [-c | -m] [-lw] [files]\n");
a104 1
		putchar('\n');
a109 1
			printf(" %s\n", *argv);
d126 1
d142 1
a142 1
			fprintf (stderr, "wc: %s: %s\n", file, strerror(errno));
d146 20
a165 28
		if (!doword) {
			/*
			 * line counting is split out because it's a lot
			 * faster to get lines than to get words, since
			 * the word count requires some logic.
			 */
			if (doline) {
				while((len = read(fd, buf, MAXBSIZE)) != 0) {
					if (len == -1) {
						fprintf (stderr, "wc: %s: %s\n",
							file, strerror(errno));
						rval = 1;
						close (fd);
						return;	
					}
					charct += len;
					for (C = buf; len--; ++C)
						if (*C == '\n')
							++linect;
				}
				tlinect += linect;
				printf(" %7ld", linect);
				if (dochar) {
					tcharct += charct;
					printf(" %7ld", charct);
				}
				close(fd);
				return;
d167 1
a167 17
			/*
			 * if all we need is the number of characters and
			 * it's a directory or a regular or linked file, just
			 * stat the puppy.  We avoid testing for it not being
			 * a special device in case someone adds a new type
			 * of inode.
			 */
			if (dochar) {
				int ifmt;

				if (fstat(fd, &sbuf)) {
					fprintf (stderr, "wc: %s: %s\n",
						file, strerror(errno));
					rval = 1;
					close (fd);
					return;
				}
d169 14
d186 1
a186 4
					printf(" %7ld", sbuf.st_size);
					tcharct += sbuf.st_size;
					close(fd);
					return;
d192 28
a219 27
		fd = 0;

	/* do it the hard way... */
	for (gotsp = 1; (len = read(fd, buf, MAXBSIZE));) {
		if (len == -1) {
			fprintf (stderr, "wc: %s: %s\n", file, strerror(errno));
			break;
		}
		charct += len;
		for (C = buf; len--; ++C) {
			if (isspace (*C)) {
				gotsp = 1;
				if (*C == '\n') {
					++linect;
				}
			} else {
				/*
				 * This line implements the POSIX
				 * spec, i.e. a word is a "maximal
				 * string of characters delimited by
				 * whitespace."  Notice nothing was
				 * said about a character being
				 * printing or non-printing.
				 */
				if (gotsp) {
					gotsp = 0;
					++wordct;
d224 1
d237 2
@


1.5
log
@Minor tweaks: including header files to bring prototypes into scope,
explicitly declaring function return values, etc. to make gcc -Wall
shut up.
@
text
@d42 1
a42 1
static char rcsid[] = "$Id: wc.c,v 1.4 1993/08/17 00:37:11 jtc Exp $";
a56 5
#define DEL	0177			/* del char */
#define NL	012			/* newline char */
#define SPACE	040			/* space char */
#define TAB	011			/* tab char */

d60 1
d70 1
a70 1
	while ((ch = getopt(argc, argv, "lwcm")) != EOF)
d84 1
a84 1
			fputs("usage: wc [-lwc] [files]\n", stderr);
d121 1
a121 1
	exit(0);
d140 2
a141 1
			exit(1);
d154 3
a156 1
						exit(1);
d185 3
a187 1
					exit(1);
d203 1
d208 1
a208 1
			exit(1);
d214 1
a214 1
				if (*C == NL) {
a217 16
#if 0
				/*
				 * This line of code implements the
				 * original V7 wc algorithm, i.e.
				 * a non-printing character doesn't
				 * toggle the "word" count, so that
				 * "  ^D^F  " counts as 6 spaces,
				 * while "foo^D^Fbar" counts as 8
				 * characters.
				 *
				 * test order is important -- gotsp
				 * will normally be NO, so test it
				 * first
				 */
				if (gotsp && *C > SPACE && *C < DEL) ...
#endif
@


1.4
log
@Make wc 1003.2-1992 compliant by adding -m option (currently a noop, as
we don't support multibyte chars).
Remove blatant lie from manpage: the order of the output is, and always
has been, fixed.  The order of the command line arguments makes no difference.
@
text
@d42 1
a42 1
static char rcsid[] = "$Id: wc.c,v 1.3 1993/08/01 18:03:04 mycroft Exp $";
d55 1
d62 1
d66 1
d128 1
d153 1
a153 1
				while(len = read(fd, buf, MAXBSIZE)) {
d203 1
a203 1
	for (gotsp = 1; len = read(fd, buf, MAXBSIZE);) {
@


1.3
log
@Add RCS identifiers.
@
text
@d42 1
a42 1
static char rcsid[] = "$Id: $";
d71 1
a71 1
	while ((ch = getopt(argc, argv, "lwc")) != EOF)
d80 1
@


1.2
log
@Update to POSIX 1003.2 (D11.2) compliance.
Make error messages print leading "wc: ", so we know what program is
complaining when we're writing shell scripts.
Simplify argument parsing and total printing.
@
text
@d41 2
a42 1
static char sccsid[] = "@@(#)wc.c	5.7 (Berkeley) 3/2/91";
@


1.1
log
@Initial revision
@
text
@d50 4
a68 1
	int total;
d70 19
d94 1
a94 23
	if (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
		while ((ch = getopt(argc, argv, "lwc")) != EOF)
			switch((char)ch) {
			case 'l':
				doline = 1;
				break;
			case 'w':
				doword = 1;
				break;
			case 'c':
				dochar = 1;
				break;
			case '?':
			default:
				fputs("usage: wc [-lwc] [files]\n", stderr);
				exit(1);
			}
		argv += optind;
		argc -= optind;
	}
	else {
		++argv;
		--argc;
a97 1
	total = 0;
d101 17
d119 1
a119 15
	else do {
		cnt(*argv);
		printf(" %s\n", *argv);
		++total;
	} while(*++argv);

	if (total > 1) {
		if (doline)
			printf(" %7ld", tlinect);
		if (doword)
			printf(" %7ld", twordct);
		if (dochar)
			printf(" %7ld", tcharct);
		puts(" total");
	}
d137 1
a137 1
			perror(file);
d149 2
a150 1
						perror(file);
d178 2
a179 1
					perror(file);
d199 1
a199 1
			perror(file);
d203 4
a206 3
		for (C = buf; len--; ++C)
			switch(*C) {
				case NL:
d208 17
a224 20
				case TAB:
				case SPACE:
					gotsp = 1;
					continue;
				default:
#ifdef notdef
					/*
					 * This line of code implements the
					 * original V7 wc algorithm, i.e.
					 * a non-printing character doesn't
					 * toggle the "word" count, so that
					 * "  ^D^F  " counts as 6 spaces,
					 * while "foo^D^Fbar" counts as 8
					 * characters.
					 *
					 * test order is important -- gotsp
					 * will normally be NO, so test it
					 * first
					 */
					if (gotsp && *C > SPACE && *C < DEL) {
d226 12
a237 12
					/*
					 * This line implements the manual
					 * page, i.e. a word is a "maximal
					 * string of characters delimited by
					 * spaces, tabs or newlines."  Notice
					 * nothing was said about a character
					 * being printing or non-printing.
					 */
					if (gotsp) {
						gotsp = 0;
						++wordct;
					}
d239 1
@


1.1.1.1
log
@initial import of 386bsd-0.1 sources
@
text
@@


1.1.1.2
log
@4.4BSD-Lite2
@
text
@d2 2
a3 2
 * Copyright (c) 1980, 1987, 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
d35 3
a37 3
static char copyright[] =
"@@(#) Copyright (c) 1980, 1987, 1991, 1993\n\
	The Regents of the University of California.  All rights reserved.\n";
d41 1
a41 1
static char sccsid[] = "@@(#)wc.c	8.2 (Berkeley) 5/2/95";
d44 2
d48 1
a48 3
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
a49 10
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

u_long tlinect, twordct, tcharct;
int doline, doword, dochar;

void cnt __P((char *));
void err __P((const char *, ...));
void usage __P((void));
d51 8
a58 1
int
d61 1
a61 1
	char *argv[];
d63 1
d67 28
a94 20
	while ((ch = getopt(argc, argv, "lwc")) != EOF)
		switch((char)ch) {
		case 'l':
			doline = 1;
			break;
		case 'w':
			doword = 1;
			break;
		case 'c':
			dochar = 1;
			break;
		case '?':
		default:
			usage();
		}
	argv += optind;
	argc -= optind;

	/* Wc's flags are on by default. */
	if (doline + doword + dochar == 0)
d96 1
d100 2
a101 2
		cnt(NULL);
		(void)printf("\n");
d105 1
a105 1
		(void)printf(" %s\n", *argv);
d111 1
a111 1
			(void)printf(" %7ld", tlinect);
d113 1
a113 1
			(void)printf(" %7ld", twordct);
d115 2
a116 2
			(void)printf(" %7ld", tcharct);
		(void)printf(" total\n");
a120 1
void
d124 1
a124 1
	register u_char *p;
d126 3
a128 3
	register int ch, len;
	register u_long linect, wordct, charct;
	struct stat sb;
a131 1
	fd = STDIN_FILENO;
d134 29
a162 17
		if ((fd = open(file, O_RDONLY, 0)) < 0)
			err("%s: %s", file, strerror(errno));
		if (doword)
			goto word;
		/*
		 * Line counting is split out because it's a lot faster to get
		 * lines than to get words, since the word count requires some
		 * logic.
		 */
		if (doline) {
			while (len = read(fd, buf, MAXBSIZE)) {
				if (len == -1)
					err("%s: %s", file, strerror(errno));
				charct += len;
				for (p = buf; len--; ++p)
					if (*p == '\n')
						++linect;
d164 7
a170 2
			tlinect += linect;
			(void)printf(" %7lu", linect);
d172 15
a186 2
				tcharct += charct;
				(void)printf(" %7lu", charct);
a187 2
			(void)close(fd);
			return;
d189 8
a196 13
		/*
		 * If all we need is the number of characters and it's a
		 * regular or linked file, just stat the puppy.
		 */
		if (dochar) {
			if (fstat(fd, &sb))
				err("%s: %s", file, strerror(errno));
			if (S_ISREG(sb.st_mode)) {
				(void)printf(" %7qu", sb.st_size);
				tcharct += sb.st_size;
				(void)close(fd);
				return;
			}
a197 11
	}

	/* Do it the hard way... */
word:	for (gotsp = 1; len = read(fd, buf, MAXBSIZE);) {
		if (len == -1)
			err("%s: %s", file, strerror(errno));
		/*
		 * This loses in the presence of multi-byte characters.
		 * To do it right would require a function to return a
		 * character while knowing how many bytes it consumed.
		 */
d199 37
a235 9
		for (p = buf; len--;) {
			ch = *p++;
			if (ch == '\n')
				++linect;
			if (isspace(ch))
				gotsp = 1;
			else if (gotsp) {
				gotsp = 0;
				++wordct;
a236 1
		}
d240 1
a240 1
		(void)printf(" %7lu", linect);
d244 1
a244 1
		(void)printf(" %7lu", wordct);
d248 1
a248 1
		(void)printf(" %7lu", charct);
d250 1
a250 37
	(void)close(fd);
}

void
usage()
{
	(void)fprintf(stderr, "usage: wc [-clw] [files]\n");
	exit(1);
}

#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif

void
#if __STDC__
err(const char *fmt, ...)
#else
err(fmt, va_alist)
	char *fmt;
        va_dcl
#endif
{
	va_list ap;
#if __STDC__
	va_start(ap, fmt);
#else
	va_start(ap);
#endif
	(void)fprintf(stderr, "wc: ");
	(void)vfprintf(stderr, fmt, ap);
	va_end(ap);
	(void)fprintf(stderr, "\n");
	exit(1);
	/* NOTREACHED */
@
