Sunday, February 05, 2012
99 ways to program a hex, Part 28: K&R C, system calls, full buffering
So, how would the version based on
system calls have looked in the 80s? You know, probably before the mmap()
system call
existed? 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: sean@conman.org * *************************************************************************/ /* 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 vowel impairment 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)
and vowels typically being redundant (“f y cn rd ths y t cn wrt prgrms”)
is it any wonder early code was typically vwlmprd
?