* * * * *

    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]