The METAL compiler option for XL C (referred to as Metal C) provides support for system program development. You can use the METAL option to generate code that does not have Language Environment runtime dependencies. In addition, language features are provided to embed pieces of HLASM source within C statements. Any system services required by the XL C application program can be obtained directly by calling Assembler Services. Metal C gives you the ability to use C language features to express low-level programming logic; for example, writing user exits. You are free from tasks such as managing the registers and developing the correct assembly instruction sequences.
Normally, the XL C compiler-generated code requires Language Environment to establish an overall execution context. The C library functions also require the Language Environment in order to provide their services, most noticeably the functions to manage the heap storage and dynamic storage area, to do file input/output and to handle exception conditions. If your C program needs to work closely with system facilities, it needs the means to acquire these services directly from the operating system. Because you can only acquire these using assembler macros, the compiler needs to incorporate assembler statements in the C program. The compiler also needs to make the C program to follow conventions expected in the operating system environment.
As a step toward addressing these requirements, the METAL option generates code in assembly source program format. You can then feed the assembly source through the High Level Assembler, like any other assembly programs. The resulting code is independent of the Language Environment. This opens up the following opportunities for you:
Use Metal C code with existing assembler programs
Code generated by the METAL option follows the MVS linkage convention. This makes it easy for you to mix C code with existing High-Level Assembler code. You don't have to rewrite everything in C in order to take advantage of the new facilities in the C compiler.
Take advantage of a large body of system services
With some limitations, you can call system macros from within a C function. For example, you can:
- Set up the parameter values for the STORAGE macro
- Call the STORAGE macro
- Return the obtained storage address in a C variable
You can do all this within a C function. You can even develop a C library to get at the system services and design a high-level application interface tailored for your purpose.
Associate a register with a pointer variable
You can tie a C pointer variable to a register, and use it to pass data back and forth between assembler code and C code. The register is meant to contain an address. You can use the C pointer variable to access data through the register without additional overhead.
Access data spaces using far pointers
You can manipulate data in secondary address spaces using far pointers. Each far pointer keeps track of the ALET under the cover, freeing you from coding with access registers. There are also built-in functions, similar to memcpy, to help move data within secondary address spaces, and between secondary and primary address spaces.
Metal C Runtime Library
The Metal C Runtime Library is a new base element of z/OS and is completely independent of Language Environment. The library modules are made available in the link pack area (LPA) during IPL. Both AMODE 31 and 64 are supported, as long as you are calling the functions in primary address space control (ASC) mode. The library functions make use of the default linkage provided by the compiler's METAL option, which requires a small contiguous stack that uses the standard save area convention that z/OS assembler programmers are familiar with.
A starter set of functions for a system environment includes functions to test and manipulate memory and strings (like memcpy() and strcmp() ), to classify characters (such as isalpha() and islowerj() ), and to process text strings (using the sprintf() and sscanf() family of functions). You can generate a random number using the rand() and rand_r() functions. If you are used to having heap management functions like malloc() and free() available, the Metal C Runtime Library supplies these as well. There is even an __malloc31() function to obtain below-the-bar storage while running AMODE 64.
However, unlike many of the other functions already mentioned, the heap management functions require the runtime to remember information about the heaps. To accomplish this, the Metal C Runtime Library introduces the concept of a Metal C environment. This environment is used to anchor heap storage and to keep track of other persistent data, such as the random number generator seed.
You can create a Metal C environment by calling the __cinit() function and passing it information that describes the environment, such as the subpool and size of the heap segments. __cinit() will set up the environment and return to you a token that represents the environment. Your program is responsible for keeping track of this token. You use the token to reference the environment on subsequent library calls by making sure that general-purpose register (GPR) 12 contains the token when the calls are made. When the environment is no longer needed, you can call the __cterm() function to perform cleanup, freeing all resources that had been obtained when using the token.
You can use these features in a number of ways. Metal C does not require you to rewrite your existing assembler code. Metal C code is meant to interoperate with existing assembler routines and work without the Language Environment. You can use Metal C when adding new features to your existing applications written in assembler language. This protects your investment in existing code and allows you to leverage it using a programming tool that can better express the high-level logic. If you like, you can rewrite selected routines in C; for example, code that requires frequent maintenance. In addition, you can write user exits in C. You have a powerful tool to work closely with system facilities, and you can use the capabilities of the XL C compiler to optimize your programs and take advantage of the latest hardware features you have.
Like other C library functions, printf() needs Language Environment. A useful subset of these functions is provided in the Metal C library. Normal input-output functionality is not provided, but functions like sprintf() are. You can still enjoy the convenience of %-substitution in the format string; and you can emit the resulting string in a buffer, and then print this buffer using, for example, WTO.