PL/I is not totally out of date! E.g., it has some really sweetheart scope of names rules. The On Conditions are generally nicer than Try-Catch, e.g., if in a code block A and do a Goto out of it to a statement label in a containing code block B (it's fair to call PL/I a block structured language), then the stack of that task (in some ways nicer than just a thread) is rolled (popped as in popping a stack, which is essentially what happens) back to the context of the last time block B was active.
Block B can have a function F that inherits names defined in the blocks that contain B, and block B can call a function G, pass F as an entry variable, and function G can call it's parameter for function F, function F can execute and access all the variables it has access to that function G may not. That can be nice. I used it once when scheduling the fleet for FedEx.
Can have tasks, like threads. Can allocate some storage as, say, controlled. Then when the task ends, that allocated storage is freed. That can be nice -- nice way to stop memory leaks when have to kill a task.
PL/I has structures which replace much of the utility of classes. And the structures, with arrays of structures of arrays of structures of arrays, etc., are much faster than instances of classes because all the addressing is just a fairly nice generalization of simple old array addressing without pointers.
Such a structure can be based which means that can allocate one and get back a pointer to it. So, that is a lot like allocating an instance of a class. B can be part of a structure A, and B can be defined to be like structure C -- so, can get some inheritance.
The flat file I/O is much sweeter than what is in C and was brought over to, say, Visual Basic .NET or C#.
PL/I will convert nearly any data type to nearly any other, e.g., something like a cast in the C family of languages, but the documentation says in very full and fine detail just how each conversion is done.
There's a relatively powerful pre-processor macro language executed by the compiler that can be used to generate a lot of source code -- can be nice.
If they have tried to upgrade PL/I, say, to 64 bit addressing, maybe more on event handling, some collection classes, a sweet DB/2 or RDBMS interface (it always had some DB syntax and semantics in the language), then it could be a nice language even now.
It's been said that the golden age of language design was the 1960s. C was designed after PL/I and was a really big step down so that it could compile on a DEC mini-computer with 8 KB of main memory while PL/I always had at least 64 KB.
On VM/CMS and MVS, PL/I didn't have access to TCP/IP, but C did, so I wrote some C code callable from PL/I that gave PL/I access to TCP/IP. Used it a little! Maybe now TCP/IP is closer to being native to the language.
I was in the group at IBM's Watson lab that did the expert system shell KnowledgeTool that was implemented as a pre-processor to PL/I. One night I stayed up until dawn and coded the logic that made rule subroutines fast, functional, etc. The key was to keep a crucial part of our run time software and the user's rule subroutine on the stack of dynamic descendancy. Gee, I got an award! The hourly rate for that night was actually relatively good!
PL/I doesn't have to be so bad!