Throught this course you will be working on big software projects and an important part of any large project is documentation. Documentation is especially important in group projects, like many of the projects in this class. Imagine how useful a browsable index will be when your partner is asleep and you're trying to figure out his/her code. In order to ensure that your source code has adequate documentation, we will be requiring that your code be fully documented using doxygen, a documentation system for C similar to JavaDoc. This document serves as a brief overview of doxygen and the features you will use on a regular basis. For a more detailed description of doxygen and all of its features visit the doxygen homepage. You can get detailed documentation and information about compiling and installing doxygen on a home system.
There are two types of comments we want in your code. The first kind are comments at the beginning of each file which describes the file and lists things like author and known bugs. The second kind of comments are those that describe your functions and data structures. We want you to put comments on all your functions and data structures. You do not have to comment individual variable instances but are welcome to if you'd like. The rest of this document talks about the doxygen commands that you need for each of the two kinds. First, we'll describe what we expect to see and then talk about the specific commands that you need to use including simple examples. Lastly there will be a larger example showing all of commands together.
Each file needs to begin with the @file command stating the name of the file. This should be followed by a brief description of the file using the @brief command. If necessary, you can follow this with a more detailed description. Next you should put your name and andrew id, along with your partners name and andrew id, using the @author tag. This needs to be followed with a bugs section with a list of known bugs using the @bug command. If there are no known bugs, explicitly state that using the @bug command.
Before each function, data structure, and macro you should put a comment block giving at least a brief description using the @brief command. A brief description will suffice for your data structures but for you macros and functions you will need to use a few more commands. After your description, you should use the @param command to describe all of the parameters to your function. These descriptions should be followed by a description of the return value using the @return command. Note: When we say "each" function, that is not a strong statement. You can leave out simple helper functions, like a max() macro, so you don't waste time.
You can choose to comment your functions either in the header files where they are declared, in the source files where they are implemented or both. This is a matter of taste. If you put it in the header file, like in the example, then you should be sure to remember to update the comments with the latest details of the implemenation. If you choose to put the comments in both places note that if there is a difference between the two sets of comments, the block at the declaration will superceed the one at the implementation. The long and short of this is that you should not put the comments in both. For assembly files, you can put the comments in the header file where they are declared.
Here is what we expect to see in the non-brief section of the function:
At some point in your career you may well be required, or at least expected to adhere to an explicit coding standard document. If you are ever present at the inception of a large project, you will have the opportunity to watch the inevitable flame war over tab stops and brace placement. Don't worry--for 15-410, we aren't going to tie you down that much.
However, you should use a consistent and defensible style. It would probably be a good experience for you to read a few coding style documents to see how they differ and how you feel about the differences. When you begin work with your partner on Project 2 you will have an opportunity to discuss this issue. We won't require the two of you to use exactly the same style, but it would probably make sense for style to not vary wildly within a single file. For open source projects (i.e., potentially many authors over many years), one popular approach is for the "primary author" of each file to set the style (within reason) and other developers to try to emulate that style (again, within reason, but it really is good form for any change you suggest to blend in with the code that's already there).
Here are some coding style documents you may find useful.
You may also wish to consult How NOT to go about a programming assignment by Agustín Cernuda del Río.
What really matters is:
flag
.
Before writing a function that contains two "flag"
variables (e.g., flag
and flag2
),
please consult a member of the course staff for advice on
what to do instead.
Using "state" as a variable or field name is rarely appropriate.
Using i
and j
as variables may be
appropriate for code involving matrices, but probably not otherwise.
Single-character variable names can be fine,
as long as a meaningful single character is chosen every time.
// printf("!!!! joe = %d\n", 4 * i / 0);
int threadstatus = THR_RUNNING; // THR_RUNNING|128
// if (threadid ==17) MAGIC_BREAK;
*nodeptr
. If, by design, nodeptr
can never point
to NULL
, then a statement like
ASSERT (nodeptr);
if (!nodeptr)
BUG();
likely()
and unlikely()
preprocessor macros in the Linux kernel and the associated
gcc builtin function
__builtin_expect()
.
However, people who don't have measurable performance
problems should probably avoid littering their code with cryptic
incantations without actual benefit.
Go here: https://www.doxygen.nl/manual/commands.html for descriptions of the commands mentioned.
Here is a short example showing all the elements together. This is an old version of the Project 1 starter code, presented in order to demonstrate doxygen (i.e., don't cut and paste this code into a current project!). As a note, README.dox is a text file with a single block of C-style comments in it.
/** @mainpage 15-410 Project 1 @author Harry Q. Bovik (hqbovik) Here you should tell us about how your game works. How to play, any special rules you have, etc. Also, explain any non-trivial design decisions you make, like how your ball gets its position updated, how you designed your buffer for readchar(), etc. You should also comment on the stability of your code. Any big bugs should be listed here. Basically, anything that you think we need to know in general about your project should go here. Any additional comments you want to make can go here. Did you like the project? Was it too hard, too easy? My TA smells bad. Well, you get the idea. As a last little note, please make sure that all the documentation you turn in is true and accurate. Otherwise, we will deduct points. */
/** @file console.h * @brief Function prototypes for the console driver. * * This contains the prototypes for the console * driver and eventually any macros, constants, * or global variables you will need. * * @author Harry Q. Bovik (hqbovik) * @author Fred Hacker (fhacker) * @bug No known bugs. */ #ifndef _MY_CONSOLE_H #define _MY_CONSOLE_H #include <video_defines.h> /** @brief Prints character ch at the current location * of the cursor. * * If the character is a newline ('\n'), the cursor should * be moved to the next line (scrolling if necessary). If * the character is a carriage return ('\r'), the cursor * should be immediately reset to the beginning of the current * line, causing any future output to overwrite any existing * output on the line. If backsapce ('\b') is encountered, * the previous character should be erased (write a space * over it and move the cursor back one column). It is up * to you how you want to handle a backspace occurring at the * beginning of a line. * * @param ch the character to print * @return The input character */ int putbyte( char ch ); /** @brief Prints the string s, starting at the current * location of the cursor. * * If the string is longer than the current line, the * string should fill up the current line and then * continue on the next line. If the string exceeds * available space on the entire console, the screen * should scroll up one line, and then the string should * continue on the new line. If '\n', '\r', and '\b' are * encountered within the string, they should be handled * as per putbyte. If len is not a positive integer or s * is null, the function has no effect. * * @param s The string to be printed. * @param len The length of the string s. * @return Void. */ void putbytes(const char* s, int len); /** @brief Changes the foreground and background color * of future characters printed on the console. * * If the color code is invalid, the function has no effect. * * @param color The new color code. * @return Void. */ void set_term_color(int color); /** @brief Writes the current foreground and background * color of characters printed on the console * into the argument color. * @param color The address to which the current color * information will be written. * @return Void. */ void get_term_color(int* color); /** @brief Sets the position of the cursor to the * position (row, col). * * Subsequent calls to putbytes should cause the console * output to begin at the new position. If the cursor is * currently hidden, a call to set_cursor() must not show * the cursor. * * @param row The new row for the cursor. * @param col The new column for the cursor. * @return Void. */ void set_cursor(int row, int col); /** @brief Writes the current position of the cursor * into the arguments row and col. * @param row The address to which the current cursor * row will be written. * @param col The address to which the current cursor * column will be written. * @return Void. */ void get_cursor(int* row, int* col); /** @brief Hides the cursor. * * Subsequent calls to putbytes must not cause the * cursor to show again. * * @return Void. */ void hide_cursor(); /** @brief Shows the cursor. * * If the cursor is already shown, the function has no effect. * * @return Void. */ void show_cursor(); /** @brief Clears the entire console. * @return Void. */ void clear_console(); /** @brief Prints character ch with the specified color * at position (row, col). * * If any argument is invalid, the function has no effect. * * @param row The row in which to display the character. * @param col The column in which to display the character. * @param ch The character to display. * @param color The color to use to display the character. * @return Void. */ void draw_char(int row, int col, int ch, int color); /** @brief Returns the character displayed at position (row, col). * @param row Row of the character. * @param col Column of the character. * @return The character at (row, col). */ char get_char(int row, int col); #endif /* _MY_CONSOLE_H */
/** @file console.c * @brief A console driver. * * These empty function definitions are provided * so that stdio will build without complaining. * You will need to fill these functions in. This * is the implementation of the console driver. * Important details about its implementation * should go in these comments. * * @author Harry Q. Bovik (hqbovik) * @author Fred Hacker (fhacker) * @bug No know bugs. */ #include <console.h> int putbyte( char ch ) { return ch; } void putbytes( const char *s, int len ) { } void set_term_color( int color ) { } void get_term_color( int *color ) { } void set_cursor( int row, int col ) { } void get_cursor( int *row, int *col ) { } void hide_cursor() { } void show_cursor() { } void clear_console() { } void draw_char( int row, int col, int ch, int color ) { }
/** @file kernel.c * @brief An initial kernel.c * * This file contains the kernel's * main() function. * * You should add your own comments to * replace this one. * * This is where you will eventually setup * your game board and have it run. * * @author Harry Q. Bovik (hqbovik) * @author Fred Hacker (fhacker) * @bug No known bugs. */ /* -- Includes -- */ /* libc includes. */ #include <stdio.h> /* for lprintf_kern() */ /* multiboot header file */ #include <multiboot.h> /* for boot_info */ /* memory includes. */ #include <lmm.public.h> /* for lmm_remove_free() */ /* x86 specific includes */ #include <x86/seg.h> /* for install_user_segs() */ #include <x86/pic.h> /* for pic_init() */ #include <x86/base_irq.h> /* for base_irq_master/slave */ /* * state for kernel memory allocation. */ extern lmm_t malloc_lmm; /* * Info about system gathered by the boot loader */ extern struct multiboot_info boot_info; /** @brief Kernel entrypoint. * * This is the entrypoint for your kernel. * You will use this to test and debug your * drivers and it will eventually hold the * code for your game. Right now, it is * A tight while loop. * * @return Should not return */ int main() { /* * Tell the kernel memory allocator which memory it can't use. * It already knows not to touch kernel image. */ lmm_remove_free( &malloc_lmm, (void*)USER_MEM_START, USER_MEM_SIZE ); lmm_remove_free( &malloc_lmm, (void*)0, 0x100000 ); /* * Install interrupt handlers here. */ /* * initialize the PIC so that IRQs and * exception handlers don't overlap in the IDT. */ pic_init( BASE_IRQ_MASTER_BASE, BASE_IRQ_SLAVE_BASE ); lprintf_kern( "Hello from a brand new kernel!" ); while(1); return 0; }
[Last modified Thursday September 07, 2023]