8 ms·
I'm taking a look through DOSUTIL.ZIP and I love all these simple elegant C programs. A lot of these programs somehow only manage to have 1-2 standard c #includ
by jart 3y ago
I'm taking a look through DOSUTIL.ZIP and I love all these simple elegant C programs. A lot of these programs somehow only manage to have 1-2 standard c #include lines. How often do you see that? I also love how, out of 20,000 lines of C code, there only exists 24 #if statements. This is how C programming was meant to be. Reading codebases like this is one of the things I drew inspiration from when I started working on Cosmopolitan Libc.
- kelsey9876543 3y agoJustine, you are one of less than 5 programmers that make me feel envy. Hope to have a coffee or a whiskey with you some day if we ever cross paths. Enjoy your day, you are an inspiration and goals. Both mental goals and presentation goals, which is essentially unheard of.
- duskwuff 3y ago> A lot of these programs somehow only manage to have 1-2 standard c #include lines Older C compilers will let you get away with a lot of sins which a modern C compiler will (correctly) call you out for.
- jart 3y agoWe can still get away with those sins today if you change C's implicit type from int to long. I modified chibicc to do just that it was a 1 LOC patch. Suddenly I didn't need prototypes anymore and everything just worked without #include lines.
- duskwuff 3y ago> Suddenly I didn't need prototypes anymore Under some very old C standards, maybe. But C99 requires that you at least declare a function before calling it.
- fuzztester 3y agoPascal had a forward declaration from way back, even before Object Pascal: https://en.m.wikipedia.org/wiki/Forward_declaration https://en.m.wikipedia.org/wiki/Forward_declaration https://en.m.wikipedia.org/wiki/Pascal_(programming_language) https://en.m.wikipedia.org/wiki/Pascal_(programming_language... https://en.m.wikipedia.org/wiki/Object_Pascal https://en.m.wikipedia.org/wiki/Object_Pascal https://www.thedelphigeek.com/2017/03/forward-record-declaration.html?m=1 https://www.thedelphigeek.com/2017/03/forward-record-declara...
- billfruit 3y agoBut why does it have to be that way though, can't the compiler scan the rest of the code/files and see if a defenition/declaration is present somewhere? There is no such requirement of a declaration before first call in Java for example?
- fuzztester 3y agoGood question.
- rezonant 3y agoIt's because the C compiler was designed to be single pass, so as to be speedy and require less memory on the systems of it's time.
- eVeechu7 3y agoA little bit of advice like that is a tremendous blessing to those of us who just need to touch C occasionally.
- trealira 3y agoI haven't looked that deeply, but I don't see many sins in this source code, either, except for the K&R style, weird formatting and doing too much in one line, like this line in the file CAT.C: if(*(Ptr = argv[i]) == '-') { Older C compilers did let you get away with more, like using integers as pointers, and dereferencing pointers as though they were struct pointers when they aren't. But I don't see that in this code.
- fuzztester 3y ago>Older C compilers did let you get away with more, like using integers as pointers In older C compilers (maybe pre-ANSI, or later, can't remember), you could literally write i[a] instead of a[i], where a was an array and i was an int, and it would work equivalently, i.e. no compiler error, and give the same result as a[i]. This was because a was the address of the start of the array, and i was an offset, so a[i] actually meant *(a + i), which, by the commutative property of arithmetic, was equivalent to *(i + a), which was equivalent to i[a]. I had read this in some C book, maybe K&R or the Waite Group C Microsoft Bible. Never forgot it, because it was counter-intuitive, unless you knew the above reason. And tried it out in one or more C compilers at that approximate period, and it worked as stated.
- krackers 3y agoThis still works iirc.
- trealira 3y agoThis is still true, and it's mandated by the ISO C standard that a[i] is equivalent to (*((a)+(i))) (yes, they specify it with that many parentheses). You're still able to compile code that treats a[i] and i[a] interchangeably. https://godbolt.org/z/37Kv44o1b https://godbolt.org/z/37Kv44o1b > I had read this in some C book, maybe K&R or the Waite Group C Microsoft Bible. I haven't read the Microsoft C Bible, but it does say this in K&R while explaining pointers.
- fuzztester 3y ago
- flykespice 3y agoHmm implicit int conversion
- cdchn 3y agoIf your build targets are 1 then that saves you a lot of #if macros.
- lovasoa 3y agoYou are replying to someone who builds C programs for 6 OS and 2 architectures without an #if ;)
- d6e 3y agoHow? I’d be curious if you have a blog post.
- kr0bat 3y agohttps://justine.lol/ape.html https://justine.lol/ape.html For the uniformed
- spockz 3y agoCan cosmopolitan replace the whole llvm toolchain required by GraalVM’s native-image? Currently cross building with native-image is a pain, especially compared to golang. (Or resource intensive as you need to compile it on each platform/architecture you want.)
- kaba0 3y agoIt’s probably not the best form to abstract away the OS-distinctions, as every abstraction will hide important details from the underlying OS. E.g. certain JDK native methods could be more efficiently done for, say, windows, then through a libc-like abstraction library.
- echelon 3y agoI love all of the domain experts and accomplished people hanging out with the rest of us on HN. :)
- rezonant 3y ago
- toasted-subs 3y agoLooked through the Linux kernel and I was genuinely shocked. Something so simple, easy to read, and improve upon. Makes modern web frameworks seem like spaghetti code. Art vs scrap.
- marcus0x62 3y agoMeanwhile, over here in the Rust mines, I wrote a simple program that is little more than an http listener with a single route. Cargo pulled in something like 105 dependencies to build it. Although, as an apples to apples comparison, it does only have 2 use statements.
- rezonant 3y agoThis doesn't really surprise me, doing an HTTP service correctly is not actually trivial
- lrvick 3y agoThis is a culture problem, not a language problem. Here is a http health check in 19 lines using only the rust standard library. https://dpaste.org/f895z https://dpaste.org/f895z
- marcus0x62 3y agoThere’s a lot of distance between “reinvent the wheel by implementing all your network functionality using nothing more than sockets” and “download 100 libraries to serve a file over http”. There’s a happy medium to be had. I’d also disagree this is not at all a language problem - I think it’s both, in that the language has moved an awful lot of core functionality into the crate ecosystem, where there are a bewildering array of options for almost any need. The resulting explosion in the dependency graph is an entirely foreseeable consequence — partially of that language design decision and partially due to the “npm culture” (for lack of a better description.)
- kqr 3y agoSlighly off topic, but... how is npm culture different from CPAN culture? I have a feeling there is a difference but I'm too unfamiliar with both ecosystems to point it out.
- marcus0x62 3y ago
- throwaway892238 3y agoOTOH, here is a hash table in C implemented entirely as macros. It's super cool: https://troydhanson.github.io/uthash/ https://troydhanson.github.io/uthash/
- gilbetron 3y agoBecause there were barely any libraries to include back then. If you wanted some functionality, you wrote it yourself. Which was fun, but most of the code pales in comparison to modern libraries that have had years, or decades, or eyes on them improving and testing them. Pre 2000, if you wanted some specific capability, you wrote it yourself!