Saturday, February 18, 2023

M4 manual.GNU M4 1.4.19 macro processor

Looking for:

M4 manual 













































     

M4 manual.Army Publishing Directorate – Details Page



  WebArmy DA administrative publications and forms by the Army Publishing Directorate APD. The latest technologies high quality electronic pubs and forms view U.S. Army . Webby giving tips for reading the remainder of the manual. The following chapters then detail all the features of the m4language. Introduction to m4 m4 is a macro processor, in the . WebOPERATOR'S MANUAL FOR RIFLE, MM, M16A2 (NSN ), (EIC: 4GM) RIFLE, MM, M16A3 (NSN ) RIFLE, MM, M16A4 (NSN .    

 

M4 manual.Table of Contents



   

In foreach , paren-list is a comma-separated list of elements contained in parentheses. In foreachq , quote-list is a comma-separated list of elements contained in a quoted string. For each assignment to iterator , append text to the overall expansion. As an example, this displays each word in a list inside of a sentence, using an implementation of foreach distributed as m It is possible to be more complex; each element of the paren-list or quote-list can itself be a list, to pass as further arguments to a helper macro.

This example generates a shell case statement:. The implementation of the foreach macro is a bit more involved; it is a wrapper around two helper macros. Here is a simple implementation of foreach :. Unfortunately, that implementation is not robust to macro names as list elements. The first cut at implementing foreachq takes this into account.

Also, when using quoted elements in a paren-list , the overall list must be quoted. A quote-list has the nice property of requiring fewer characters to create a list containing the same quoted elements. To see the difference between the two macros, we attempt to pass double-quoted macro names in a list, expecting the macro name on output after one layer of quotes is removed during list iteration and the final layer removed during the final rescan:.

Unfortunately, this implementation of foreachq has its own severe flaw. Whereas the foreach implementation was linear, this macro is quadratic in the number of list elements, and is much more likely to trip up the limit set by the command line option --nesting-limit or -L , see Invoking m4. It is possible to have robust iteration with linear behavior and sane iterator contents for either list style.

See if you can learn from the best elements of both of these implementations to create robust macros or see Answers. Thanks to pushdef , manipulation of a stack is an intrinsic operation in m4. Normally, only the topmost definition in a stack is important, but sometimes, it is desirable to manipulate the entire definition stack. For each of the pushdef definitions associated with macro , invoke the macro action with a single argument of that definition.

There are a few special macros, such as defn , which cannot be used as the macro parameter. A sample implementation of these macros is distributed in the file m Now for the implementation. Since m4 is a macro language, it is possible to write macros that can build other macros. First on the list is a way to automate the creation of blind macros.

Defines name as a blind macro, such that name will expand to value only when given explicit arguments. This macro is only recognized with parameters, and results in an empty string. Defining a macro to define another macro can be a bit tricky. When composing macros, it is a common idiom to need a helper macro to concatenate text that forms parameters in the composed macro, rather than interpreting the text as a parameter of the composing macro.

As for the limitation against using defn , there are two reasons. And if a macro is a builtin, then it would result in an attempt to define a macro consisting of both text and a builtin token; this is not supported, and the builtin token is flattened to an empty string.

Another interesting composition tactic is argument currying , or factoring a macro that takes multiple arguments for use in a context that provides exactly one argument. Expand to a macro call that takes exactly one argument, then appends that argument to the original arguments and invokes macro with the resulting list of arguments. A demonstration of currying makes the intent of this macro a little more obvious.

But coupled with currying, we can invoke reverse with two arguments for each definition of a macro stack. This example uses the file m The use of a comma inside the shift call allows currying to also work for a macro that takes one argument, although it often makes more sense to invoke that macro directly rather than going through curry. Unfortunately, with M4 1. This limitation will be lifted in a future release of M4.

Putting the last few concepts together, it is possible to copy or rename an entire stack of macro definitions. Ensure that dest is undefined, then define it to the same stack of definitions currently in source. There are only a few macros, such as copy or defn , which cannot be copied via this macro. The implementation is relatively straightforward although since it uses curry , it is unable to copy builtin macros, such as the second definition of a as a synonym for divnum.

See if you can design a version that works around this limitation, or see Answers. When writing macros for m4 , they often do not work as intended on the first try as is the case with most programming languages.

Fortunately, there is support for macro debugging in m4. Accepts any number of arguments. If called without any arguments, it displays the definitions of all known names, otherwise it displays the definitions of the names given.

The output is printed to the current debug file usually standard error , and is sorted by name. If an unknown name is encountered, a warning is printed.

The last example shows how builtin macros definitions are displayed. The definition that is dumped corresponds to what would occur if the macro were to be called at that point, even if other definitions are still live due to redefining a macro during argument collection. See Debug Levels , for information on controlling the details of the display. It is possible to trace macro calls and expansions through the builtins traceon and traceoff :.

When called without any arguments, traceon and traceoff will turn tracing on and off, respectively, for all currently defined macros. When called with arguments, only the macros listed in names are affected, whether or not they are currently defined.

Whenever a traced macro is called and the arguments have been collected, the call is displayed. If the expansion of the macro call is not void, the expansion can be displayed after the call.

The output is printed to the current debug file defaulting to standard error, see Debug Output. The number between dashes is the depth of the expansion. It is one most of the time, signifying an expansion at the outermost level, but it increases when macro arguments contain unquoted macro calls.

The maximum number that will appear between dashes is controlled by the option --nesting-limit or -L , see Invoking m4. Additionally, the option --trace or -t can be used to invoke traceon name before parsing input. Tracing by name is an attribute that is preserved whether the macro is defined or not. This allows the selection of macros to trace before those macros are defined. Tracing even works on builtins. However, defn see Defn does not transfer tracing status.

The -d option to m4 or --debug , see Invoking m4 controls the amount of details presented in three categories of output. Finally, dumpdef see Dumpdef output is affected, with no prefix added to the output lines. In trace output, show the actual arguments that were collected before invoking the macro.

Arguments are subject to length truncation specified by the command line option --arglength or -l. In trace output, show several trace lines for each macro call. A line is shown when the macro is seen, but before the arguments are collected; a second line when the arguments have been collected and a third line after the call has completed. In trace output, show the expansion of each macro call, if it is not void.

The expansion is subject to length truncation specified by the command line option --arglength or -l. In debug output, print a message when a named file is found through the path search mechanism see Search Path , giving the actual file name used.

In trace and dumpdef output, quote actual arguments and macro expansions in the display with the current quotes. In trace output, trace all macro calls made in this invocation of m4 , regardless of the settings of traceon.

The examples throughout this manual assume the default flags. There is a builtin macro debugmode , which allows on-the-fly control of the debugging output format:. The argument flags should be a subset of the letters listed above. The following example demonstrates the behavior of length truncation, when specified on the command line. Note that each argument and the final result are individually truncated. Also, the special tokens for builtin functions are not truncated. Debug and tracing output can be redirected to files using either the --debugfile option to m4 see Invoking m4 , or with the builtin macro debugfile :.

Sends all further debug and trace output to file , opened in append mode. If file is the empty string, debug and trace output are discarded. If debugfile is called without any arguments, debug and trace output are sent to standard error.

This does not affect warnings, error messages, or errprint output, which are always sent to standard error. If file cannot be opened, the current debug file is unchanged, and an error is issued.

All characters, up to and including the next newline, are discarded without performing any macro expansion. A warning is issued if the end of the file is encountered without a newline. It is often used in connection with define , to remove the newline that follows the call to define. The input up to and including the next newline is discarded, as opposed to the way comments are treated see Comments. Usually, dnl is immediately followed by an end of line or some other whitespace. GNU m4 will produce a warning diagnostic if dnl is followed by an open parenthesis.

In this case, dnl will collect and process all arguments, looking for a matching close parenthesis. All predictable side effects resulting from this collection will take place. The input following the matching close parenthesis up to and including the next newline, on whatever line containing it, will still be discarded. If the end of file is encountered without a newline character, a warning is issued and dnl stops consuming input. This sets start as the new begin-quote delimiter and end as the new end-quote delimiter.

If start is void, then quoting is disabled. Otherwise, if end is missing or void, the default end-quote delimiter ' is used. The quote delimiters can be of any length.

If no single character is appropriate, start and end can be of any length. Other implementations cap the delimiter length to five characters, but GNU has no inherent limit. Calling changequote with start as the empty string will effectively disable the quoting mechanism, leaving no way to quote text.

However, using an empty string is not portable, as some other implementations of m4 revert to the default quoting, while others preserve the prior non-empty delimiter. Again, this is not portable, as some other m4 implementations reuse start as the end-quote delimiter, while others preserve the previous non-empty value. Omitting both arguments restores the default begin-quote and end-quote delimiters; fortunately this behavior is portable to all implementations of m4.

There is no way in m4 to quote a string containing an unmatched begin-quote, except using changequote to change the current quotes. To achieve this, two calls of changequote must be made, one for the temporary quotes and one for the new quotes.

Macros are recognized in preference to the begin-quote string, so if a prefix of start can be recognized as part of a potential macro name, the quoting mechanism is effectively disabled. However, even though quoted strings are not recognized, the quote characters can still be discerned in macro expansion and in trace output.

Quotes are recognized in preference to argument collection. Note that it takes two more changequote invocations to restore the original quotes. If end is a prefix of start , the end-quote will be recognized in preference to a nested begin-quote. In particular, changing the quotes to have the same string for start and end disables nesting of quotes.

When quote nesting is disabled, it is impossible to double-quote strings across macro expansions, so using the same string is not done very often. This sets start as the new begin-comment delimiter and end as the new end-comment delimiter. If both arguments are missing, or start is void, then comments are disabled. Otherwise, if end is missing or void, the default end-comment delimiter of newline is used. The comment delimiters can be of any length.

Note how comments are copied to the output, much as if they were quoted strings. If you want the text inside a comment expanded, quote the begin-comment delimiter. Calling changecom without any arguments, or with start as the empty string, will effectively disable the commenting mechanism.

If start is not empty, then an empty end will use the default end-comment delimiter of newline, as otherwise, it would be impossible to end a comment.

However, this is not portable, as some other m4 implementations preserve the previous non-empty delimiters instead. Comments are recognized in preference to macros. However, this is not compatible with other implementations, where macros and even quoting takes precedence over comments, so it may change in a future release. Comments are recognized in preference to argument collection.

The macro changeword and all associated functionality is experimental. It is only available if the --enable-changeword option was given to configure , at GNU m4 installation time. The functionality will go away in the future, to be replaced by other new features that are more efficient at providing the same capabilities.

Do not rely on it. Please direct your comments about it the same way you would do for bugs. A file being processed by m4 is split into quoted strings, words potential macro names and simple tokens any other single character. Initially a word is defined by the following regular expression:. Changes the regular expression for recognizing macro names to be regex.

If regex contains grouping parentheses, the macro invoked is the portion that matched the first group, rather than the entire matching string. The expansion of changeword is void. The macro changeword is recognized only with parameters. Relaxing the lexical rules of m4 might be useful for example if you wanted to apply translations to a file of numbers:. Tightening the lexical rules is less useful, because it will generally make some of the builtins unavailable.

You could use it to prevent accidental call of builtins, for example:. Because m4 constructs its words a character at a time, there is a restriction on the regular expressions that may be passed to changeword. If the regular expression supplied contains any grouped subexpressions, then text outside the first of these is discarded before symbol lookup. In m4 , macro substitution is based on text, while in TeX, it is based on tokens. For example, here is the same idea represented in TeX and m4.

First, the TeX version:. The fourth line invokes the macro a. The reason for this is that TeX does lexical analysis of macro definition when the macro is defined. You should note that using changeword will slow m4 down by a factor of about seven, once it is changed to something other than the default regular expression. You can invoke changeword with the empty string to restore the default word definition, and regain the parsing speed.

Text can be saved, to be read again by m4 when the normal input has been exhausted. This feature is normally used to initiate cleanup actions before normal exit, e. Stores string in a safe place, to be reread when end of input is reached.

As a GNU extension, additional arguments are concatenated with a space to the string. The expansion of m4wrap is void. The macro m4wrap is recognized only with parameters.

The saved input is only reread when the end of normal input is seen, and not if m4exit is used to exit m4. It is safe to call m4wrap from saved text, but then the order in which the saved text is reread is undefined. If m4wrap is not used recursively, the saved pieces of text are reread in the opposite order in which they were saved LIFO—last in, first out. However, this behavior is likely to change in a future release, to match POSIX, so you should not depend on this order.

Unfortunately, both examples shown here share some subtle bugs. See if you can find and correct them; or see Answers. Invocations of m4wrap at the same recursion level are concatenated and rescanned as usual:.

Both macros cause the file named file to be read by m4. When the end of the file is reached, input is resumed from the previous input file. The expansion of include and sinclude is therefore the contents of file. If file does not exist, is a directory, or cannot otherwise be read, the expansion is void, and include will fail with an error while sinclude is silent. The empty string counts as a file that does not exist.

The rest of this section assumes that m4 is invoked with the -I option see Invoking m4 pointing to the m The file m Normally file inclusion is used to insert the contents of a file into the input stream. The contents of the file will be read by m4 and macro calls in the file will be expanded:. The fact that include and sinclude expand to the contents of the file can be used to define macros that operate on entire files.

This use of include is not trivial, though, as files can contain quotes, commas, and parentheses, which can interfere with the way the m4 parser works. GNU m4 seamlessly concatenates the file contents with the next character, even if the included file ended in the middle of a comment, string, or macro call. These conditions are only treated as end of file errors if specified as input files on the command line. In GNU m4 , an alternative method of reading files is using undivert see Undivert on a named file.

GNU m4 allows included files to be found in other directories than the current working directory. If the --prepend-include or -B command-line option was provided see Invoking m4 , those directories are searched first, in reverse order that those options were listed on the command line. Then m4 looks in the current working directory. Next comes the directories specified with the --include or -I option, in the order found on the command line.

Finally, if the M4PATH environment variable is set, it is expected to contain a colon-separated list of directories, which will be searched in order. Diversions are a way of temporarily saving output. The output of m4 can at any time be diverted to a temporary file, and be reinserted into the output stream, undiverted , again at a later time. Numbered diversions are counted from 0 upwards, diversion number 0 being the normal output stream.

GNU m4 tries to keep diversions in memory. However, there is a limit to the overall memory usable by all diversions taken together K, currently. When this maximum is about to be exceeded, a temporary file is opened to receive the contents of the biggest diversion still in memory, freeing this memory for other diversions. Thus, the amount of available disk space provides the only real limit on the number and aggregate size of diversions.

Diversions make it possible to generate output in a different order than the input was read. It is possible to implement topological sorting dependencies. The current diversion is changed to number. If number is left out or empty, it is assumed to be zero. If number cannot be parsed, the diversion is unchanged.

When all the m4 input will have been processed, all existing diversions are automatically undiverted, in numerical order. Several calls of divert with the same argument do not overwrite the previous diverted text, but append to it. Diversions are printed after any wrapped text is expanded. If output is diverted to a negative diversion, it is simply discarded.

This can be used to suppress unwanted output. A common example of unwanted output is the trailing newlines after macro definitions. Here is a common programming idiom in m4 for avoiding them. Traditional implementations only supported ten diversions. But as a GNU extension, diversion numbers can be as large as positive integers will allow, rather than treating a multi-digit diversion number as a request to discard text.

Note that divert is an English word, but also an active macro without arguments. When processing plain text, the word might appear in normal text and be unintentionally swallowed as a macro invocation. One way to avoid this is to use the -P option to rename all builtins see Invoking m4.

Another is to write a wrapper that requires a parameter to be recognized. Undiverts the numeric diversions given by the arguments, in the order given. If no arguments are supplied, all diversions are undiverted, in numerical order. As a GNU extension, diversions may contain non-numeric strings, which are treated as the names of files to copy into the output without expansion.

A warning is issued if a file could not be opened. Notice the last two blank lines. One of them comes from the newline following undivert , the other from the newline that followed the divert! A diversion often starts with a blank line like this. When diverted text is undiverted, it is not reread by m4 , but rather copied directly to the current output, and it is therefore not an error to undivert into a diversion.

Undiverting the empty string is the same as specifying diversion 0; in either case nothing happens since the output has already been flushed. When a diversion has been undiverted, the diverted text is discarded, and it is not possible to bring back diverted text more than once. Attempts to undivert the current diversion are silently ignored.

Thus, when the current diversion is not 0, the current diversion does not get rearranged among the other diversions. GNU m4 allows named files to be undiverted. Given a non-numeric argument, the contents of the file named will be copied, uninterpreted, to the current output. This complements the builtin include see Include.

To illustrate the difference, assume the file foo contains:. If the file is not found or cannot be read , an error message is issued, and the expansion is void. It is possible to intermix files and diversion numbers. Often it is not known, when output is diverted, whether the diverted text is actually needed. Since all non-empty diversion are brought back on the main output stream when the end of input is seen, a method of discarding a diversion is needed.

It is called just like undivert , but the effect is to clear the diversions, given by the arguments. This macro has a nasty bug! You should try to see if you can find it and correct it; or see Answers. There are a number of builtins in m4 for manipulating text in various ways, extracting substrings, searching, substituting, and so on. Expands to the index of the first occurrence of substring in string. The first character in string has index 0. Omitting substring evokes a warning, but still produces output; contrast this with an empty substring.

Searches for regexp in string. If replacement is omitted, regexp expands to the index of the first match of regexp in string. If regexp does not match anywhere in string , it expands to If there was no match, regexp expands to the empty string. Omitting regexp evokes a warning, but still produces output; contrast this with an empty regexp argument.

Expands to the substring of string , which starts at index from , and extends for length characters, or to the end of string , if length is omitted. The starting index of a string is always 0.

The expansion is empty if there is an error parsing from or length , if from is beyond the end of string , or if length is negative. Expands to string , with each character that occurs in chars translated into the character from replacement with the same index. If replacement is shorter than chars , the excess characters of chars are deleted from the expansion; if chars is shorter, the excess characters in replacement are silently ignored.

If replacement is omitted, all characters in string that are present in chars are deleted from the expansion. If a character appears more than once in chars , only the first instance is used in making the translation. Only a single translation pass is made, even if characters in replacement also appear in chars. As a GNU extension, both chars and replacement can contain character-ranges, e.

Back-to-back ranges can share a common endpoint. In that case, the range runs backwards, i. The expansion of a range is dependent on the underlying encoding of characters, so using ranges is not always portable between machines. Searches string for matches of regexp , and substitutes replacement for each match. The parts of string that are not covered by any match of regexp are copied to the expansion.

Whenever a match is found, the search proceeds from the end of the match, so a character from string will never be substituted twice. If regexp matches a string of zero length, the start position for the search is incremented, to avoid infinite loops.

The replacement argument can be omitted, in which case the text matched by regexp is deleted. Here is a slightly more realistic example, which capitalizes individual words or whole sentences, by substituting calls of the macros upcase and downcase into the strings.

Expand to text , but with capitalization changed: upcase changes all letters to upper case, downcase changes all letters to lower case, and capitalize changes the first character of each word to upper case and the remaining characters to lower case.

First, an example of their usage, using implementations distributed in m As presented here, the capitalize macro has some subtle flaws. You should try to see if you can find and correct them; or see Answers. While regexp replaces the whole input with the replacement as soon as there is a match, patsubst replaces each occurrence of a match and preserves non-matching pieces:.

Works much like the C function printf. Using the forloop macro defined earlier see Forloop , this example shows how format can be used to produce tabular output.

Unrecognized specifiers result in a warning. It is anticipated that a future release of GNU m4 will support more specifiers, and give better warnings when various problems such as overflow are encountered. Likewise, escape sequences are not yet recognized.

Integer arithmetic is included in m4 , with a C-like syntax. As convenient shorthands, there are builtins for simple increment and decrement operations. Increment and decrement of integers are supported using the builtins incr and decr :. Expand to the numerical value of number , incremented or decremented, respectively, by one. Except for the empty string, the expansion is empty if number could not be parsed.

Expands to the value of expression. The expansion is empty if a problem is encountered while parsing the arguments. If specified, radix and width control the format of the output. Calculations are done with bit signed numbers. Overflow silently results in wraparound. A warning is issued if division by zero is attempted, or if expression could not be parsed. All binary operators, except exponentiation, are left associative.

Attempting to use them results in an error. The unary operators could not be used reliably more than once on the same term without intervening parentheses. Starting with version 1. M4 scripts designed to be portable between releases must be aware that parentheses may be required to enforce C precedence rules.

Likewise, division by zero, even in the unused branch of a short-circuiting operator, is not always well-defined in other implementations. Following are some examples where the current version of M4 follows C precedence rules, but where older versions and some other implementations of m4 require explicit parentheses to get the correct result:. The operator is right-associative, and if evaluated, the exponent must be non-negative, and at least one of the arguments must be non-zero, or a warning is issued.

Within expression , but not radix or width , numbers without a special prefix are decimal. Lower and upper case letters can be used interchangeably in numbers prefixes and as number digits. Parentheses may be used to group subexpressions whenever needed. For the relational operators, a true relation returns 1 , and a false relation return 0. As the last two lines show, eval does not handle macro names, even if they expand to a valid expression or part of a valid expression.

Therefore all macros must be expanded before they are passed to eval. Some calculations are not portable to other implementations, since they have undefined semantics in C, but GNU m4 has well-defined behavior on overflow. When shifting, an out-of-range shift amount is implicitly brought into the range of bit signed integers using an implicit bit-wise and with 0x1f.

If radix is specified, it specifies the radix to be used in the expansion. The default radix is 10; this is also the case if radix is the empty string. A warning results if the radix is outside the range of 1 through 36, inclusive. The result of eval is always taken to be signed. No radix prefix is output, and for radices greater than 10, the digits are lower case. The width argument specifies the minimum output width, excluding any negative sign. The result is zero-padded to extend the expansion to the requested width.

A warning results if the width is negative. If radix or width is out of bounds, the expansion of eval is empty. There are a few builtin macros in m4 that allow you to run shell commands from within m4.

Note that the definition of a valid shell command is system dependent. But on other systems, such as native Windows, the shell has a different syntax of commands that it understands. Sometimes it is desirable for an input file to know which platform m4 is running on. GNU m4 provides several macros that are predefined to expand to the empty string; checking for their existence will confirm platform details.

Each of these macros is conditionally defined as needed to describe the environment of m4. If defined, each macro expands to the empty string. For now, these macros silently ignore all arguments, but in a future release of M4, they might warn if arguments are present.

If GNU m4 does not provide a platform macro for your system, please report that as a bug. The expansion of syscmd is void, not the output from shell-command! Output or error messages from shell-command are not read by m4. See Esyscmd , if you need to process the command output. Prior to executing the command, m4 flushes its buffers.

The default standard input, output and error of shell-command are the same as those of m4. Note how the expansion of syscmd keeps the trailing newline of the command, as well as using the newline that appeared after the macro. The following is an example of shell-command using the same standard input as m4 :. It tells m4 to read all of its input before executing the wrapped text, then hand a valid albeit emptied pipe as standard input for the cat subcommand.

When standard input is a seekable file, the subprocess will pick up with the next character not yet processed by m4 ; when it is a pipe or other non-seekable file, there is no guarantee how much data will already be buffered by m4 and thus unavailable to the child. The default standard input and standard error of shell-command are the same as those of m4.

Which one is truly more important to the enthusiast? Or is it? As more and more manufacturers shy away from the effort and cost to produce manual transmission in cars, it is impressive to realize BMW is still willing to commit engineering and financial resources to sell manual transmission cars for enthusiasts. The new massive twin kidney grills that run from the edge of the hood to the bottom of the bumper make quite the statement. As I pulled our Black Sapphire Metallic G82 M4 into the parking lot at the hotel in Spartanburg, SC, two pilots who had just gotten there immediately came over to see the new car.

Both of them thought the design was stunning and had a ton of questions while pouring all over the car. The Performance Center is a playground for the motorhead and includes a high speed track section, a skid pad, an autocross style course. And a lot more elevation changes than I would have expected. This is a great place to explore the capabilities of the all new M4 as it is so powerful and readily exceeds legal speed limits. He then left us to get photos, video and drive the section as much as we wanted.

I spent time changing different settings on the car and trying them out on different sections of the track. In fact, there is such a myriad of settings on the BMW M4, it does get overwhelming. Three settings each for the engine and chassis and two settings for the steering and brake.

So I asked, Mike, their pro-driver, what the M School sets them to. He said for their driving school, they set M1 to be what they would use in the dry and M2 what they set them for in the wet. Good advice! Eve though I am sure it is programmed that way to help with the fuel economy. Remember, comparison is the thief of joy. While the M4's steering is a bit devoid of feedback, it does its job without offending. Just don't drive a GT4, like ever. Eventually, the skies blued, the sun dried the canyon roads, and it took all of two corners to realize that the M4 has astonishing front-end grip.

Much of that is due to the changes BMW made from the F82's setup. There's a total resistance to understeer and a heady 1. Stressed near its cornering limits, the body remains resolutely flat. While it's not what we'd call nimble—again, the Cayman GT4 colors our opinion here—careful tuning and a Even as speeds and g-forces creep ever higher, there are no missteps or surprises, which removes any worries about painting a guardrail Sao Paulo Yellow.

If you're on the wrong side of 40, climbing in and out of the car elicits involuntary grunts and moans, but the payoff is a warm embrace and a pound weight savings over the standard seats.

Once in, you'll notice your legs are separated by a slightly uncomfortable divide in the seat bottom that is intended to evoke racing seats. Like the M4 badging on the headrest, the leg separator is a design element that's sure to inspire oohs and aahs from non-car people and eye rolls from the rest of us. There's a lot of car here to ooh and aah over. The M4 is now a mere 2. And compared with the last M4, the new car is 0. You notice the dimensions mostly when you're parking.

The M4 feels a size smaller when you're having fun, but the scale doesn't lie: This is a big, heavy car. The last M4 manual we weighed came in at pounds; this one is up to The new-to-M4 S58 twin-turbo six helps offset the extra mass, offering 48 more horsepower than the S55 did in the previous gen at its launch. Last year the most powerful manual-trans M4 had horsepower. Blessed with an imperviousness to vibration, the smooth inline-six doesn't seem to care whether it's idling, at redline, or anywhere between.

So you're left studying the multicolored tachometer or, if you select M View, the double-strip tach. Neither is as easy to read as the big analog dials BMW used to fit in its cars.



No comments:

Post a Comment

M4 manual.GNU M4 1.4.19 macro processor

Looking for: M4 manual  Click here to DOWNLOAD       M4 manual.Army Publishing Directorate – Details Page   WebArmy DA administrative ...