- Text editor project in C - 3 Updates
- No, C is not a simple language - 2 Updates
- std::bind with member functions and C++20 - 4 Updates
- Sharing Classes across modules in TC++ projects - 1 Update
| 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:
Post a Comment