Coding Standards
****************

All of you should have taken a class like CS 107, so we expect you to be familiar with some set of coding standards such as CS 107 Coding Standards. Even if you've taken 107, we recommend reviewing that document.  We expect code at the "Peer-Review Quality" level as described there.

Our standards for coding are mostly important in grading.  More information on our grading methodology can be found on the Course Info page and the Grading page.  We also want to stress that aside from the fact that we are explicitly basing part of your grade on these things, good coding practices will improve the quality of your code.  This makes it easier for your partners to interact with it, and ultimately, will improve your chances of having a good working program.  That said once, the rest of this document will discuss only the ways in which our coding standards will affect our grading.

Style
=====

Style, for the purposes of our grading, refers to how readable your code is.  At minimum, this means that your code is well formatted, your variable names are descriptive and your functions are decomposed and well commented.  Any other factors which make it hard (or easy) for us to read or use your code will be reflected in your style grade.

The existing Pintos code is written in the GNU style and largely follows the GNU Coding Standards.  We encourage you to follow the applicable parts of them too, especially chapter 5, ``Making the Best Use of C.''  Using a different style won't cause actual problems, but it's ugly to see gratuitous differences in style from one function to another.

Pintos comments sometimes refer to outside standards or specifications by writing a name inside square brackets, like this: [IA32-v3].  These names refer to the reference names used in this documentation (see References).

Conditional Compilation
=======================

Given the scope and complexity of your assignments this quarter, you may find it convenient while coding and debugging (and we will find it convenient while grading) to be able to independently turn different parts of the assignments on and off.  To do this, choose a macro name and use it in conditional compilation directives, e.g.:

     #ifdef NAME
     ...your code...
     #endif

In general, the code that you turn in must not depend on conditional compilation directives.  Project code should be written so that all of the subproblems for the project function together, and it should compile properly without the need for any new macros to be defined. There are a few exceptions:

  * Problem 1-2, thread_join.  Some other code expects THREAD_JOIN_IMPLEMENTED to be defined once you've implemented this function.

  * Problem 1-4, the advanced scheduler.  We must be able to turn this on and off with a compile-time directive.  You must use the macro name we specify for that part.  See Problem 1-4 Advanced Scheduler, for details.

  * Code written for extra credit may be included conditionally.  If the extra credit code changes the normally expected functionality of the code, then it must be included conditionally, and it must not be enabled by default.

You can use constants.h in pintos/src to define macros for conditional compilation.  We will replace the constants.h that you supply with one of our own when we test your code, so do not define anything important in it.

C99
===

The Pintos source code uses a few features of the ``C99'' standard library that were not in the original 1989 standard for C.  Because they are so new, most classes do not cover these features, so this section will describe them.  The new features used in Pintos are mostly in new headers:

<stdbool.h>
     Defines macros bool, a 1-bit type that takes on only the values 0 and 1, true, which expands to 1, and false, which expands to 0.

<stdint.h>
     On systems that support them, this header defines types intN_t and uintN_t for N = 8, 16, 32, 64, and possibly others.  These are 2's complement signed and unsigned types, respectively, with the given number of bits.

     On systems where it is possible, this header also defines types intptr_t and uintptr_t, which are integer types big enough to hold a pointer.

     On all systems, this header defines types intmax_t and uintmax_t, which are the system's signed and unsigned integer types with the widest ranges.

     For every signed integer type TYPE_t it defines, as well as for ptrdiff_t defined in <stddef.h>, this header also defines macros TYPE_MAX and TYPE_MIN that give the type's range.  Similarly, for every unsigned integer type TYPE_t defined here, as well as for size_t defined in <stddef.h>, this header defines a TYPE_MAX macro giving its maximum value.

<inttypes.h>
     <stdint.h> is useful on its own, but it provides no way to pass the types it defines to printf and related functions.  This header provides macros to help with that.  For every intN_t defined by <stdint.h>, it provides macros PRIdN and PRIiN for formatting values of that type with "%d" and "%i".  Similarly, for every uintN_t, it provides PRIoN, PRIuN, PRIuX, and PRIuX.

     You use these something like this, taking advantage of the fact that the C compiler concatenates adjacent string literals:

          #include <inttypes.h>
          ...
          int32_t value = ...;
          printf ("value=%08"PRId32"\n", value);

     The % is not supplied by the PRI macros.  As shown above, you supply it yourself and follow it by any flags, field widths, etc.

<stdio.h>
     The printf function has some new type modifiers for printing standard types:

     j
          For intmax_t (e.g. %jd) or uintmax_t (e.g. %ju).

     z
          For size_t (e.g. %zu).

     t
          For ptrdiff_t (e.g. %td).

     Pintos printf also implements a nonstandard ' flag that group large numbers with commas to make them easier to read.

Unsafe String Functions
=======================

A few of the string functions declared in the standard <string.h> and <stdio.h> headers are notoriously unsafe. The worst offenders are intentionally not included in the Pintos C library:

strcpy
     When used carelessly this function can overflow the buffer reserved for its output string.  Use strlcpy instead.  Refer to comments in its source code in lib/string.c for documentation.

strncpy
     This function can leave its destination buffer without a null string terminator and it has performance problems besides.  Again, use strlcpy.

strcat
     Same issue as strcpy, but substitute strlcat. Again, refer to comments in its source code in lib/string.c for documentation.

strncat
     The meaning of its buffer size argument often leads to problems. Again, use strlcat.

strtok
     Uses global data, so it is unsafe in threaded programs such as kernels.  Use strtok_r instead, and see its source code in lib/string.c for documentation and an example.

sprintf
     Same issue as strcpy.  Use snprintf instead.  Refer to comments in lib/stdio.h for documentation.

vsprintf
     Same issue as strcpy.  Use vsnprintf instead.

If you try to use any of these functions, you should get a hint from the error message, which will refer to an identifier like dont_use_sprintf_use_snprintf.