Or, more specifically, IBM/360
No.
All labels were always global.
The 360 assembler did not provide such relative labels (*1).
But.
On the other hand it provided procedural macro language (*2), which as well included the ability to generate symbols and thus labels in arbitrary manner. All needed to make them local is using a unique number - which quite handy was supplied by a macro call counter called SYSNDX. So to generate a local label within a macro, simply build one using this. For example:
A&SYSNDX DS 0H * Generates a label Annnn with nnnn increasing with each macro call ... * Some code BCT R1,A&SYSNDX * Jump to the label generated before
As said, the 360 macro language is a full figured procedural language, not just a set of random functions, making it possible to create the same effect. One macro to define such 'relative' labels and build a set of lists (*3), one for each 'number' used, to keep track of existing and future labels. Another macro would then be used to generate these jumps. Such a source may look like this:
... 0 RELAB * Generating a '0' label ... * Some code RELBR EQ,2F * Jump forward to the next '2' label ... * Some code 1 RELAB * The one generating the labels ... * Some code RELBR NE,1B * Jump back to the last '1' label ... * Some code 2 RELAB * Generating a '2' label
Looks quite like your example - although, I'd split the forth and back from the label (e.g. write EQ,1,B), but that's up to taste.
The incredible simple and mighty nature of having a procedural macro language and not a bunch of replacement rules opens the range to any concept one can think up. Which in turn would lead to skipping the idea at all, and go straight for structured programming. After all, why bother with labels at all if one can let the Assembler do all low level work?
*1 - And I never missed them in all the decades of /360 programming. Tried them with some toy assemblers, but never really found them useful ... well, maybe if there is nothing else.
Beside that, I'd rather consider them bad idea. Put a new label between two existing (something that happens all the time when editing/extending) and the whole sequence may be screwed.
*2 - Think of macros as scripts written in a simple language. Whenever a macro is invoked, its script is executed. It may generate code, or just manipulate some data structures to be interpreted by a later macro (or macro instructions within the source as well). Every part of the invocation can be read, checked and acted upon as parameters. Noting is done by default. As output any arbitrary source line can be generated - including ofc. macro calls as well :))
*3 - Ok, lists sounds more than it is, in reality one needs to hold only two variables for each of the numbers allowed as label.
nn$, where the 'nn' part had to be unique in the range between any two ordinary labels.. There was no 'f' and 'b' suffix on the reference to the label (no need). The forward-and-back convention was for the Unix PDP-11 assembler. A glance at an arbitrary online copy of the Macro-32 manual confirms my view for VAX.$DIRSIZyou evidently mean 'literally the value DIRSIZ'. That would be written#DIRSIZin the DEC assembly language, and$is just another valid character in a name.