* * * * *
99 ways to program a hex, Part 28: K&R C, system calls, full buffering
So, how would the version based on system calls [1] have looked in the 80s?
You know, probably before the mmap() system call existed [2]? Probably like
this, vowel impairments, sorry, vwlmprmnts and all.
> /*************************************************************************
> *
> * Copyright 2012 by Sean Conner. All Rights Reserved.
> *
> * This program is free software; you can redistribute it and/or
> * modify it under the terms of the GNU General Public License
> * as published by the Free Software Foundation; either version 2
> * of the License, or (at your option) any later version.
> *
> * This program is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> * GNU General Public License for more details.
> *
> * You should have received a copy of the GNU General Public License
> * along with this program; if not, write to the Free Software
> * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> *
> * Comments, questions and criticisms can be sent to:
[email protected]
> *
> *************************************************************************/
>
> /* Style: K&R, system calls, full buffering */
>
> #include <stdlib.h>
> #include <string.h>
> #include <errno.h>
>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <unistd.h>
>
> #define LINESIZE 16
>
> /********************************************************************/
>
> main(argc,argv)
> char **argv;
> {
> int i,fhin;
>
> if (argc == 1) {
> hexdmp(0,1);
> } else {
> for (i = 1 ; i < argc ; i++) {
> fhin = open(argv[i],O_RDONLY);
> if (fhin == -1) {
> myperr(argv[i]);
> continue;
> }
>
> mywrt(1,"-----",5);
> mywrt(1,argv[i],strlen(argv[i]));
> mywrt(1,"-----\n",6);
>
> hexdmp(fhin,1);
> if (close(fhin) < 0) {
> myperr(argv[i]);
> }
> }
> }
>
> return 0;
> }
>
> /************************************************************************/
>
> char buffer[4096],outbuf[75 * 109];
>
> hexdmp(fhin,fhout)
> {
> int off,bytes,count,amount;
> char *pout,*p;
>
> memset(outbuf,' ',sizeof(outbuf));
> off = count = 0;
> pout = outbuf;
>
> while((bytes = myread(fhin,(char *)buffer,sizeof(buffer))) > 0) {
> p = buffer;
> for (p = buffer ; bytes > 0 ; ) {
> amount = hexln(&pout,p,bytes,off);
> p += amount;
> bytes -= amount;
> off += amount;
> count++;
>
> if (count == 109) {
> mywrt(fhout,outbuf,pout - outbuf);
> memset(outbuf,' ',sizeof(outbuf));
> count = 0;
> pout = outbuf;
> }
> }
> }
>
> if (pout - outbuf > 0) {
> mywrt(fhout,outbuf,pout - outbuf);
> }
> }
>
> /********************************************************************/
>
> hexln(pline,p,bytes,off)
> char **pline,*p;
> {
> char *line,*dh,*da;
> int count;
>
> line = *pline;
>
> hexout(line,off,8,':');
> if (bytes > LINESIZE) {
> bytes = LINESIZE;
> }
>
> p += bytes;
> dh = &line[10 + bytes * 3];
> da = &line[58 + bytes];
>
> for (count = 0 ; count < bytes ; count++) {
> p --;
> da --;
> dh -= 3;
>
> if ((*p >= ' ') && (*p <= '~')) {
> *da = *p;
> } else {
> *da = '.';
> }
>
> hexout(dh,(unsigned long)*p,2,' ');
> }
>
> line[58 + count] = '\n';
> *pline = &line[59 + count];
> return count;
> }
>
> /**********************************************************************/
>
> hexout(dest,value,size,padding)
> char *dest;
> {
> dest[size] = padding;
> while(size--) {
> dest[size] = (char)((value & 0x0F) + '0');
> if (dest[size] > '9') {
> dest[size] += 7;
> }
> value >>= 4;
> }
> }
>
> /************************************************************************/
>
> myperr(s)
> char *s;
> {
> extern char **sys_errlist;
> extern int sys_nerr;
> int err = errno;
>
> mywrt(2,s,strlen(s));
> mywrt(2,": ",2);
>
> if (err > sys_nerr) {
> mywrt(2,"(unknown)",9);
> } else {
> mywrt(2,sys_errlist[err],strlen(sys_errlist[err]));
> }
> mywrt(2,"\n",1);
> }
>
> /************************************************************************/
>
> myread(fh,buf,size)
> char *buf;
> {
> int amount = 0,bytes;
>
> while(size > 0) {
> bytes = read(fh,buf,size);
> if (bytes < 0) {
> myperr("read()");
> exit(1);
> }
> if (bytes == 0) {
> break;
> }
> amount += bytes;
> size -= bytes;
> buf += bytes;
> }
> return amount;
> }
>
> /*********************************************************************/
>
> mywrt(fh,msg,size)
> char *msg;
> {
> if (write(fh,msg,size) < size) {
> if (fh != 2) {
> myperr("output");
> }
> exit(1);
> }
> }
>
> /***********************************************************************/
>
Actually, the [DELETED-vowel impairment-DELETED] vwlmprmnt code was due to
linker strictions at the time—linkers at the time were fairly limited, and
one of the limits was the length of identifiers it could handle, a limit of
around 6 characters (some might have handled more, but the first C standard
in 1989 set the limit to six, so that's probably the smallest size at the
time). With only six characters (makes you wonder where that limit comes from
[3]) and vowels typically being redundant (“f y cn rd ths y t cn wrt prgrms”)
is it any wonder early code was typically vwlmprd?
* Part 27: C♯, binary stream [4]
* Part 29: K&R, system calls, full buffering, obfuscated [5]
[1]
gopher://gopher.conman.org/0Phlog:2012/01/30.1
[2]
gopher://gopher.conman.org/0Phlog:2012/02/03.1
[3]
http://en.wikipedia.org/wiki/DEC_Radix-50
[4]
gopher://gopher.conman.org/0Phlog:2012/02/04.1
[5]
gopher://gopher.conman.org/0Phlog:2012/02/06.1
Email author at
[email protected]