Thursday, April 22, 2021

Digest for comp.lang.c++@googlegroups.com - 10 updates in 4 topics

jacobnavia <jacob@jacob.remcomp.fr>: Apr 22 06:58PM +0200

Recently, somebody started a thread about how C wasn't a simple
language. The excuse was a text editor project for a beginner.
 
Attached is the source code for the 10th edition of Unix of the "ed"
text editor, published by Brian Kernighan for his CS classes at
Princeton in 2001.
 
Maybe C is not a simple language but one of its incredible strengths is
its stability. This code is around 40 (yes FORTY) years old and you can
compile it without any trouble today and it will work in any UNIX system.
 
----------------------------------------------------------------cut here
/* This file contains the source for the 10th Edition Unix version of
ed, which is
1700 lines long. It dates from about 1989, but is typical of Unix
code from the
mid 1970's: terse, tight, efficient, and largely uncommented
This is a slightly modified version that compiles without any
warnings under gcc in 2021
See https://www.cs.princeton.edu/courses/archive/spring01/cs333/ed.c
Compile with gcc -O2 -o ed -Wall -Wno-parentheses ed.c
*/
#include <signal.h>
#include <stdlib.h>
#include <setjmp.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <wait.h>
#include <string.h>
#define BLKSIZE 4096 /* make BLKSIZE and LBSIZE 512 for smaller machines */
#define NBLK 2047
#define FNSIZE 128
#define LBSIZE 4096
#define ESIZE 256
#define GBSIZE 256
#define NBRA 5
#define KSIZE 9
#define CBRA 1
#define CCHR 2
#define CDOT 4
#define CCL 6
#define NCCL 8
#define CDOL 10
#define CEOF 11
#define CKET 12
#define CBACK 14
#define CCIRC 15
#define STAR 01
static unsigned char Q[] = "";
static unsigned char T[] = "TMP";
#define READ 0
#define WRITE 1
static int peekc;
static int lastc;
static unsigned char savedfile[FNSIZE];
static unsigned char file[FNSIZE];
static unsigned char linebuf[LBSIZE];
static unsigned char rhsbuf[LBSIZE/2];
static unsigned char expbuf[ESIZE+4];
static int given;
static unsigned int *addr1, *addr2;
static unsigned int *dot, *dol, *zero;
static unsigned char genbuf[LBSIZE];
static long count;
static unsigned char *nextip;
static unsigned char *linebp;
static int ninbuf;
static int io;
static int pflag;
static int vflag = 1;
static int oflag;
static int listf;
static int listn;
static int col;
static unsigned char *globp;
static int tfile = -1;
static int tline;
static char tfname[50];
static unsigned char *loc1;
static unsigned char *loc2;
static unsigned char ibuff[BLKSIZE];
static int iblock = -1;
static unsigned char obuff[BLKSIZE];
static int oblock = -1;
static int ichanged;
static int nleft;
static char WRERR[] = "WRITE ERROR";
static int names[26];
static int anymarks;
static unsigned char *braslist[NBRA];
static unsigned char *braelist[NBRA];
static int nbra;
static int subnewa;
static int subolda;
static int fchange;
static int wrapp;
static unsigned nlall = 128;
static char tmpXXXXX[50] = "/tmp/eXXXXXX";
 
static unsigned char *getblock(unsigned int atl, int iof);
static unsigned char *GetLine(unsigned int tl);
static unsigned char *place(unsigned char *sp,unsigned char *l1,unsigned
char *l2);
static void add(int i);
static int advance(unsigned char *lp, unsigned char *ep);
static int append(int (*f)(void), unsigned int *a);
static int backref(int i,unsigned char *lp);
static void blkio(int b, unsigned char *buf, int iof);
static void callunix(void);
static int cclass(unsigned char *set, int c, int af);
static void commands(void);
static void compile(int eof);
static int compsub(void);
static void dosub(void);
static void error(unsigned char *s);
static int execute(unsigned int *addr);
static void exfile(void);
static void filename(int comm);
static void gdelete(void);
static int getchr(void);
static int getcopy(void);
static int getfile(void);
static int getnum(void);
static int getsub(void);
static int gettty(void);
static int gety(void);
static void global(int k);
static void init(void);
static unsigned int *address(void);
static void join(void);
static void move(int cflag);
static void newline(void);
static void nonzero(void);
static void onhup(int n);
static void onintr(int n);
static void print(void);
static void putchr(int ac);
static void putd(void);
static void putfile(void);
static int putline(void);
static void quit(int n);
static void rdelete(unsigned int *ad1, unsigned int *ad2);
static void reverse(unsigned int *a1, unsigned int *a2);
static void setwide(void);
static void setnoaddr(void);
static void squeeze(int i);
static void substitute(int inglob);
static jmp_buf savej;
typedef void (*SIG_TYP)(int);
static SIG_TYP oldhup;
static SIG_TYP oldquit;
/* these two are not in ansi, but we need them */
#define SIGHUP 1 /* hangup */
#define SIGQUIT 3 /* quit (ASCII FS) */
 
int main(int argc, char *argv[])
{
unsigned char *p1, *p2;
SIG_TYP oldintr;
 
oldquit = signal(SIGQUIT, SIG_IGN);
oldhup = signal(SIGHUP, SIG_IGN);
oldintr = signal(SIGINT, SIG_IGN);
if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
signal(SIGTERM, quit);
argv++;
while (argc > 1 && **argv=='-') {
switch((*argv)[1]) {
 
case '\0':
vflag = 0;
break;
 
case 'q':
signal(SIGQUIT, SIG_DFL);
vflag = 1;
break;
 
case 'o':
oflag = 1;
break;
}
argv++;
argc--;
}
if (oflag) {
p1 = (unsigned char *)"/dev/stdout";
p2 = savedfile;
while (*p2++ = *p1++)
;
}
if (argc>1) {
p1 = (unsigned char *)*argv;
p2 = savedfile;
while (*p2++ = *p1++)
if (p2 >= &savedfile[sizeof(savedfile)])
p2--;
globp = (unsigned char *)"r";
}
zero = (unsigned *)malloc(nlall*sizeof(unsigned));
strcpy(tfname,tmpXXXXX);
mkstemp(tfname);

init();
if (oldintr!=SIG_IGN)
signal(SIGINT, onintr);
if (oldhup!=SIG_IGN)
signal(SIGHUP, onhup);
setjmp(savej);
commands();
quit(0);
return 0;
}
static void commands(void)
{
unsigned int *a1;
int c;
int temp;
unsigned char lastsep;
 
for (;;) {
if (pflag) {
pflag = 0;
addr1 = addr2 = dot;
print();
}
c = '\n';
for (addr1 = 0;;) {
lastsep = c;
a1 = address();
c = getchr();
if (c!=',' && c!=';')
break;
if (lastsep==',')
error(Q);
if (a1==0) {
a1 = zero+1;
if (a1>dol)
a1--;
}
addr1 = a1;
if (c==';')
dot = a1;
}
if (lastsep!='\n' && a1==0)
a1 = dol;
if ((addr2=a1)==0) {
given = 0;
addr2 = dot;
}
else
given = 1;
if (addr1==0)
addr1 = addr2;
switch(c) {
case 'a':
add(0);
continue;
case 'c':
nonzero();
newline();
rdelete(addr1, addr2);
append(gettty, addr1-1);
continue;
case 'd':
nonzero();
newline();
rdelete(addr1, addr2);
continue;
case 'E':
fchange = 0;
c = 'e';
case 'e':
setnoaddr();
if (vflag && fchange) {
fchange = 0;
error(Q);
}
filename(c);
init();
addr2 = zero;
goto caseread;
case 'f':
setnoaddr();
filename(c);
puts((const char *)savedfile);
continue;
case 'g':
global(1);
continue;
case 'i':
add(-1);
continue;
case 'j':
if (!given)
addr2++;
newline();
join();
continue;
case 'k':
nonzero();
if ((c = getchr()) < 'a' || c > 'z')
error(Q);
newline();
names[c-'a'] = *addr2 & ~01;
anymarks |= 01;
continue;
case 'm':
move(0);
continue;
case 'n':
listn++;
newline();
print();
continue;
case '\n':
if (a1==0) {
a1 = dot+1;
addr2 = a1;
addr1 = a1;
}
if (lastsep==';')
addr1 = a1;
print();
continue;
case 'l':
listf++;
case 'p':
case 'P':
newline();
print();
continue;
case 'Q':
fchange = 0;
case 'q':
setnoaddr();
newline();
quit(0);
case 'r':
filename(c);
caseread:
if ((io = open((const char *)file, 0)) < 0) {
lastc = '\n';
error(file);
}
setwide();
squeeze(0);
ninbuf = 0;
c = zero != dol;
append(getfile, addr2);
exfile();
fchange = c;
continue;
case 's':
nonzero();
substitute(globp!=0);
continue;
case 't':
move(1);
continue;
case 'u':
nonzero();
newline();
if ((*addr2&~01) != subnewa)
error(Q);
*addr2 = subolda;
dot = addr2;
continue;
case 'v':
global(0);
continue;
case 'W':
wrapp++;
case 'w':
setwide();
squeeze(dol>zero);
if ((temp = getchr()) != 'q' && temp != 'Q') {
peekc = temp;
temp = 0;
}
filename(c);
if(!wrapp ||
((io = open((const char *)file,1)) == -1) ||
((lseek(io, 0L, 2)) == -1))
if ((io = creat((const char *)file, 0666)) < 0)
error(file);
wrapp = 0;
if (dol > zero)
putfile();
exfile();
if (addr1<=zero+1 && addr2==dol)
fchange = 0;
if (temp == 'Q')
fchange = 0;
if (temp)
quit(0);
continue;
case '=':
setwide();
squeeze(0);
newline();
count = addr2 - zero;
putd();
putchr('\n');
continue;
case '!':
callunix();
continue;
case EOF:
return;
}
error(Q);
}
}
static void print(void)
{
unsigned int *a1;
 
nonzero();
a1 = addr1;
do {
if (listn) {
count = a1-zero;
putd();
putchr('\t');
}
puts((const char *)GetLine(*a1++));
} while (a1 <= addr2);
dot = addr2;
listf = 0;
listn = 0;
pflag = 0;
}
static unsigned int * address(void)
{
int sign;
unsigned int *a, *b;
int opcnt, nextopand;
int c;
 
nextopand = -1;
sign = 1;
opcnt = 0;
a = dot;
do {
do c = getchr(); while (c==' ' || c=='\t');
if ('0'<=c && c<='9') {
peekc = c;
if (!opcnt) a = zero;
a += sign*getnum();
} else switch (c) {
case '$':
a = dol;
/* fall through */
case '.':
if (opcnt) error(Q);
break;
case '\'':
c = getchr();
if (opcnt || c<'a' || 'z'<c) error(Q);
a = zero;
do a++; while (a<=dol && names[c-'a']!=(*a&~01));
break;
case '?':
sign = -sign;
/* fall through */
case '/':
compile(c);
b = a;
for (;;) {
a += sign;
if (a<=zero) a = dol;
if (a>dol) a = zero;
if (execute(a)) break;
if (a==b) error(Q);
}
break;
default:
if (nextopand == opcnt) {
a += sign;
if (a<zero || dol<a)
continue; /* error(Q); */
}
if (c!='+' && c!='-' && c!='^') {
peekc = c;
if (opcnt==0) a = 0;
return (a);
}
sign = 1;
if (c!='+') sign = -sign;
nextopand = ++opcnt;
continue;
}
sign = 1;
opcnt++;
} while (zero<=a && a<=dol);
error(Q);
/*NOTREACHED*/
return 0;
}
static int getnum(void)
{
int r, c;
 
r = 0;
while ((c=getchr())>='0' && c<='9')
r = r*10 + c - '0';
peekc = c;
return (r);
}
static void setwide(void)
{
if (!given) {
addr1 = zero + (dol>zero);
addr2 = dol;
}
}
static void setnoaddr(void)
{
if (given) error(Q);
}
static void nonzero(void)
{
squeeze(1);
}
static void squeeze(int i)
{
if (addr1<zero+i || addr2>dol || addr1>addr2)
error(Q);
}
static void newline(void)
{
int c;
 
if ((c = getchr()) == '\n' || c == EOF) return;
if (c=='p' || c=='l' || c=='n') {
pflag++;
if (c=='l') listf++;
else if (c=='n') listn++;
if ((c=getchr())=='\n') return;
}
error(Q);
}
static void filename(int comm)
{
unsigned char *p1, *p2;
int c;
 
count = 0;
c = getchr();
if (c=='\n' || c==EOF) {
p1 = savedfile;
if (*p1==0 && comm!='f') error(Q);
p2 = file;
while (*p2++ = *p1++)
;
return;
}
if (c!=' ')
error(Q);
while ((c = getchr()) == ' ')
;
if (c=='\n') error(Q);
p1 = file;
do {
if (p1 >= &file[sizeof(file)-1] || c==' ' || c==EOF) error(Q);
*p1++ = c;
} while ((c = getchr()) != '\n');
*p1++ = 0;
if (savedfile[0]==0 || comm=='e' || comm=='f') {
p1 = savedfile;
p2 = file;
while (*p1++ = *p2++)
;
}
}
static void exfile(void)
{
close(io);
io = -1;
if (vflag) {
putd();
putchr('\n');
}
}
static void onintr(int n)
{
signal(SIGINT, onintr);
putchr('\n');
lastc = '\n';
error(Q);
}
static void onhup(int n)
{
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
if (dol > zero) {
addr1 = zero+1;
addr2 = dol;
io = creat("ed.hup", 0600);
if (io > 0)
putfile();
}
fchange = 0;
quit(0);
}
static void error(unsigned char *s)
{
int c;
 
wrapp = 0;
listf = 0;
listn = 0;
putchr('?');
puts((const char *)s);
count = 0;
lseek(0, (long)0, 2);
pflag = 0;
if (globp)
lastc = '\n';
globp = 0;
peekc = lastc;
if(lastc)
while ((c = getchr()) != '\n' && c != EOF)
;
if (io > 0) {
close(io);
io = -1;
}
longjmp(savej, 1);
}
static int getchr(void)
{
char c;
if (lastc=peekc) {
peekc = 0;
return(lastc);
}
if (globp) {
if ((lastc = *globp++) != 0)
return(lastc);
globp = 0;
return(EOF);
}
if (read(0, &c, 1) <= 0)
return(lastc = EOF);
lastc = c&0177;
return(lastc);
}
static int gettty(void)
{
int rc;
 
if (rc = gety())
return(rc);
if (linebuf[0]=='.' && linebuf[1]==0)
return(EOF);
return(0);
}
static int gety(void)
{
int c;
unsigned char *gf;
unsigned char *p;
 
p = linebuf;
gf = globp;
while ((c = getchr()) != '\n') {
if (c==EOF) {
if (gf)
peekc = c;
return(c);
}
if ((c &= 0177) == 0)
continue;
*p++ = c;
if (p >= &linebuf[LBSIZE-2])
error(Q);
}
 
*p++ = 0;
return(0);
}
static int getfile(void)
{
int c;
unsigned char *lp, *fp;
 
lp = linebuf;
fp = nextip;
do {
if (--ninbuf < 0) {
if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0)
if (lp>linebuf) {
puts("'\\n' appended");
*genbuf = '\n';
}
else return(EOF);
fp = genbuf;
while(fp < &genbuf[ninbuf]) {
if (*fp++ & 0200)
break;
}
fp = genbuf;
}
c = *fp++;
if (c=='\0')
continue;
if (c&0200 || lp >= &linebuf[LBSIZE]) {
lastc = '\n';
error(Q);
}
*lp++ = c;
count++;
} while (c != '\n');
*--lp = 0;
nextip = fp;
return(0);
}
static void putfile(void)
{
unsigned int *a1;
int n;
unsigned char *fp, *lp;
int nib;
 
nib = BLKSIZE;
fp = genbuf;
a1 = addr1;
do {
lp = GetLine(*a1++);
for (;;) {
if (--nib < 0) {
n = fp-genbuf;
if(write(io, genbuf, n) != n) {
puts((const char *)WRERR);
error(Q);
}
nib = BLKSIZE-1;
fp = genbuf;
}
count++;
if ((*fp++ = *lp++) == 0) {
fp[-1] = '\n';
break;
}
}
} while (a1 <= addr2);
n = fp-genbuf;
if(write(io, genbuf, n) != n) {
puts((const char *)WRERR);
error(Q);
}
}
static int append(int (*f)(void), unsigned int *a)
{
unsigned int *a1, *a2, *rdot;
int nline, tl;
 
nline = 0;
dot = a;
while ((*f)() == 0) {
if ((dol-zero)+1 >= nlall) {
unsigned *ozero = zero;
 
nlall += 1024;
if ((zero = (unsigned *)realloc((unsigned char *)zero,
nlall*sizeof(unsigned)))==NULL) {
error((unsigned char *)"MEM?");
onhup(0);
}
dot += zero - ozero;
dol += zero - ozero;
}
tl = putline();
nline++;
a1 = ++dol;
a2 = a1+1;
rdot = ++dot;
while (a1 > rdot)
*--a2 = *--a1;
*rdot = tl;
}
return(nline);
}
static void add(int i)
{
if (i && (given || dol>zero)) {
addr1--;
addr2--;
}
squeeze(0);
newline();
append(gettty, addr2);
}
static void callunix(void)
{
SIG_TYP savint;
int pid, rpid;
int retcode;
 
setnoaddr();
if ((pid = fork()) == 0) {
signal(SIGHUP, oldhup);
signal(SIGQUIT, oldquit);
execl("/bin/sh", "sh", "-t", NULL);
exit(0100);
}
savint = signal(SIGINT, SIG_IGN);
while ((rpid = wait(&retcode)) != pid && rpid != -1)
;
signal(SIGINT, savint);
if (vflag) {
puts("!");
}
}
static void quit(int n)
{
if (vflag && fchange && dol!=zero) {
fchange = 0;
error(Q);
}
unlink(tfname);
exit(0);
}
static void rdelete(unsigned int *ad1, unsigned int *ad2)
{
Bonita Montero <Bonita.Montero@gmail.com>: Apr 22 07:05PM +0200

> Recently, somebody started a thread about how C wasn't a simple
> language. The excuse was a text editor project for a beginner.
 
It is simple, but as we can see from your code it's actually also
very ugly.
wij <wyniijj@gmail.com>: Apr 22 12:41PM -0700

On Friday, 23 April 2021 at 00:58:41 UTC+8, jacobnavia wrote:
> }
> linp = lp;
> }
 
Never mind with such kind of people (this example is too complex for him).
When feeling is good, C++ is a super-set of C
When feeling is not so good, C++ is not C.
wij <wyniijj@gmail.com>: Apr 22 10:14AM -0700

On Thursday, 22 April 2021 at 02:34:04 UTC+8, Scott Lurndal wrote:
> {
> ...
> }
 
I built a dual(mix) mode DOS environment in probably 1999, a last struggle
to sustain software life. So my question is where "placement new" was from?
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Apr 22 12:38PM -0700

> people who didn't even know where to start never mind write working code
> was quite worrying. I imagine they're the types now writing reams of
> garbage javascript for websites.
 
Oh God! Well, here is some of my crude JavaScript in action:
 
http://funwithfractals.atspace.cc/ct_fdla_anime_dynamic_test
 
And, yes it uses a linked list... ;^)
Bonita Montero <Bonita.Montero@gmail.com>: Apr 22 07:02PM +0200

> I must be missing the point. When would this ever be used?
 
I have some code that passes shared pointers to structures which
include function-objects which were passed bind-objects on creation.
Currently I use global functions. But if these functions were member
-functions I could use this bind-variant.
Cholo Lennon <chololennon@hotmail.com>: Apr 22 02:16PM -0300


>> Coooooool, I didn't know that this works.
>> YOU'RE MY HERO !
 
> I must be missing the point. When would this ever be used?
 
Perhaps it's old fashioned, but a common use case for this it's a
callback event style similar to C# delegates. Instead of using virtual
functions, your class has several "delegates" modeled by std::function.
A user of your class can connect his/her callbacks to your delegates
using for that std::bind, which can accept any kind of callable object
(free functions, functors, member functions, lambdas, etc) with the
optional plus of binding/adding extra predefined values to your callback.
 
--
Cholo Lennon
Bs.As.
ARG
Bonita Montero <Bonita.Montero@gmail.com>: Apr 22 07:25PM +0200

> include function-objects which were passed bind-objects on creation.
> Currently I use global functions. But if these functions were member
> -functions I could use this bind-variant.
 
Or more generally: function( bind() 9-objects can be used every time
you have a function-pointer which is passed some parameters and you
store both for later use.
Andrey Tarasevich <andreytarasevich@hotmail.com>: Apr 22 10:35AM -0700


>> Coooooool, I didn't know that this works.
>> YOU'RE MY HERO !
 
> I must be missing the point. When would this ever be used?
 
I'm not sure what the focal point of your question is. What is that
"this" you are asking about?
 
`std::bind` functionality in general? Applying `std::bind` to member
functions specifically? Something else?
 
--
Best regards,
Andrey Tarasevich
Paul Panaro <pjpanaro@gmail.com>: Apr 22 10:35AM -0700

On Monday, April 15, 1991 at 11:39:59 AM UTC-4, Panaro wrote:
> class in every file that I want to use it in. Thanks in advance.
> -Paul Panaro
> PAN...@REMUS.RUTGERS.EDU
 
This is a message from your future self. Buy AMZN in 2002 and BitCoin in 2015
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: