rm sol
This commit is contained in:
		
							parent
							
								
									36c8653382
								
							
						
					
					
						commit
						32ac505a9c
					
				| 
						 | 
					@ -1,39 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ROW_COUNT 8
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Main entry point.
 | 
					 | 
				
			||||||
 * @param[in] argc  The size of the argv array.
 | 
					 | 
				
			||||||
 * @param[in] argv  The command line arguments...
 | 
					 | 
				
			||||||
 * @returns Returns EXIT_SUCCESS (=0) on success, EXIT_FAILURE (=1) if there is an input error.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(char argc, char* argv){
 | 
					 | 
				
			||||||
    uint16_t i;
 | 
					 | 
				
			||||||
    double rate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    printf("Umwandlungskurs eingeben (1.00 BTC -> CHF): ");
 | 
					 | 
				
			||||||
    if (1!= scanf("%lf", &rate)){
 | 
					 | 
				
			||||||
        printf("Ungültige Eingabe! Geben Sie eine Fliesskommazahl ein.\n");
 | 
					 | 
				
			||||||
        return 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for(i = 1; i <= ROW_COUNT; i++) {
 | 
					 | 
				
			||||||
        printf("%5d CHF\t<-->\t %5.5lf BTC\n", i*200, (double)i*200/rate);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,25 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Main entry point.
 | 
					 | 
				
			||||||
 * @param[in] argc  The size of the argv array.
 | 
					 | 
				
			||||||
 * @param[in] argv  The command line arguments...
 | 
					 | 
				
			||||||
 * @returns Returns EXIT_SUCCESS (=0) on success.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(char argc, char* argv[]) {
 | 
					 | 
				
			||||||
    printf("hello world.\n");
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,47 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Main entry point.
 | 
					 | 
				
			||||||
 * @param[in] argc  The size of the argv array.
 | 
					 | 
				
			||||||
 * @param[in] argv  The command line arguments...
 | 
					 | 
				
			||||||
 * @returns Returns EXIT_SUCCESS (=0) on success, EXIT_FAILURE (=1) there is an expression syntax error.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(char argc, char* argv[]) {
 | 
					 | 
				
			||||||
    uint16_t char_count = 0, word_count = 0;
 | 
					 | 
				
			||||||
    char c;
 | 
					 | 
				
			||||||
    uint8_t is_word = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    printf("Eingabe: ");
 | 
					 | 
				
			||||||
    c=getchar();
 | 
					 | 
				
			||||||
    while('\n' != c){
 | 
					 | 
				
			||||||
        char_count++;
 | 
					 | 
				
			||||||
        if(c != ' ' && c !='\t'){
 | 
					 | 
				
			||||||
            if(! is_word){
 | 
					 | 
				
			||||||
                is_word = 1;
 | 
					 | 
				
			||||||
                word_count++;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            is_word = 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        c = getchar();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    printf("%d Zeichen, %d W\u00F6rter\n", char_count, word_count);
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,125 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Lösungsskizzen
 | 
					 | 
				
			||||||
## Aufgabe 1
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 *  Tage Pro Monat
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  Das Programm liest einen Monat (1-12) und ein Jahr (1600-2400) ein und
 | 
					 | 
				
			||||||
 *  gibt die Anzahl der Tage dieses Monats aus.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  @author Gerrit Burkert, Adaptation bazz
 | 
					 | 
				
			||||||
 *  @version 15-FEB-2013, 16-OCT-2017, 17-OCT-2019, 16-FEB-2022
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ERROR_IN_MONTH 1
 | 
					 | 
				
			||||||
#define ERROR_IN_YEAR 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
///// Student Code
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Konstante Werte fuer die Monate
 | 
					 | 
				
			||||||
// ===============================
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum { JAN=1, FEB, MAR, APR, MAI, JUN, JUL, AUG, SEP, OKT, NOV, DEZ };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Eingabe pruefen (0 ist vom atoi als Fehelcode verwendet und darf nicht verwendet werden) 
 | 
					 | 
				
			||||||
// ===============
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int gibIntWert(char *name, int von, int bis) {
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	int wert;
 | 
					 | 
				
			||||||
	char wertS[20]; //
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
    	printf("%s:     ", name);
 | 
					 | 
				
			||||||
    	fgets(wertS, 20, stdin);
 | 
					 | 
				
			||||||
    	wert = atoi(wertS);
 | 
					 | 
				
			||||||
    	if (wert < von || wert > bis) {
 | 
					 | 
				
			||||||
        	printf("Der Wert muss zwischen %d und %d sein.\n", von, bis);
 | 
					 | 
				
			||||||
    	} else {
 | 
					 | 
				
			||||||
    		break; 
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} while(1);
 | 
					 | 
				
			||||||
	return wert;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Schaltjahr bestimmen
 | 
					 | 
				
			||||||
// ==================== 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int istSchaltjahr(int jahr){
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if ( (jahr % 400 == 0) || ( (jahr %100 != 0) && (jahr % 4 ==0) ) )
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Berechnung Anzahl Tage pro Monat
 | 
					 | 
				
			||||||
// ================================
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int tageProMonat(int jahr, int monat) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int anzTage;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // Tage pro Monat bestimmen
 | 
					 | 
				
			||||||
    switch (monat) {
 | 
					 | 
				
			||||||
	   
 | 
					 | 
				
			||||||
        // Monate mit 31 Tagen 
 | 
					 | 
				
			||||||
        case JAN: case MAR: case MAI: case JUL: case AUG: case OKT: case DEZ:
 | 
					 | 
				
			||||||
            anzTage = 31;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // Monate mit 30 Tagen 
 | 
					 | 
				
			||||||
        case APR: case JUN: case SEP: case NOV:
 | 
					 | 
				
			||||||
            anzTage = 30;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // Februar: 28 oder 29 Tage 
 | 
					 | 
				
			||||||
        case FEB:
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
            if (istSchaltjahr(jahr)) {
 | 
					 | 
				
			||||||
                anzTage = 29;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                anzTage = 28;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return anzTage;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
///// END Student Code
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int main (int argc, char *argv[]) {
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    int monat, jahr;
 | 
					 | 
				
			||||||
     
 | 
					 | 
				
			||||||
    //  Monat einlesen und Bereich ueberpruefen
 | 
					 | 
				
			||||||
    monat = gibIntWert("Monat", 1, 12);
 | 
					 | 
				
			||||||
    jahr  = gibIntWert("Jahr", 1600, 9999);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
    //  Ausgabe zum Test
 | 
					 | 
				
			||||||
    printf("Monat: %d, Jahr: %d \n", monat, jahr);    
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    //  Ausgabe zum Test (hier mit dem ternaeren Operator "?:")
 | 
					 | 
				
			||||||
    printf("%d ist %s Schaltjahr\n", jahr, istSchaltjahr(jahr) ? "ein" : "kein");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Ausgabe
 | 
					 | 
				
			||||||
	printf("Der Monat %02d-%d hat %d Tage.\n", monat, jahr, tageProMonat(jahr, monat));
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
## Aufgabe 2
 | 
					 | 
				
			||||||
Alter bestehender Boilerplate Code
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,88 +0,0 @@
 | 
				
			||||||
/*****************************************************************************
 | 
					 | 
				
			||||||
    M. Thaler, Jan. 2000
 | 
					 | 
				
			||||||
    Datei           read.java
 | 
					 | 
				
			||||||
    Funktion:       Unsigned int Zahl via Bytestream von stdin einlesen.
 | 
					 | 
				
			||||||
                    Es wird zuerst eine Zeile eingelesen und dann konvertiert.
 | 
					 | 
				
			||||||
                    Die eingelesene Zeile darf nur eine Zahl enthalten
 | 
					 | 
				
			||||||
                    (mit optionalen Leerzeichen vor/nach der Zahl).
 | 
					 | 
				
			||||||
    Returns:        Die konvertierte Zahl
 | 
					 | 
				
			||||||
                    oder -1 (PARSE_ERROR) wenn keine Zahl oder zu gross
 | 
					 | 
				
			||||||
                    oder -2 (READ_ERROR) wenn Fehler beim einlesen.
 | 
					 | 
				
			||||||
    Korrekturen:    - Maerz 2002: M. Thaler, H. Fierz, Mar. 2002
 | 
					 | 
				
			||||||
                      liest bis EOL oder EOF, korrekter Rueckgabewert
 | 
					 | 
				
			||||||
                    - Sept 2016: A. Gieriet
 | 
					 | 
				
			||||||
                      Refactored (sprechende Variablen-Namen,
 | 
					 | 
				
			||||||
                                  MS Windows Support, 0 Wert erlaubt,
 | 
					 | 
				
			||||||
                                  Leerzeichen Support,
 | 
					 | 
				
			||||||
                                  "magic" Numbers durch Symbole ersetzt,
 | 
					 | 
				
			||||||
                                  maxResult Parameter, etc.)
 | 
					 | 
				
			||||||
******************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class read {
 | 
					 | 
				
			||||||
    public int getInt(int maxResult)
 | 
					 | 
				
			||||||
        throws java.io.IOException
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // end of input
 | 
					 | 
				
			||||||
        int EOF   = -1; // end of file
 | 
					 | 
				
			||||||
        int EOL   = 10; // end of line
 | 
					 | 
				
			||||||
        // abnormal return values
 | 
					 | 
				
			||||||
        int PARSE_ERROR = -1;
 | 
					 | 
				
			||||||
        int READ_ERROR  = -2;
 | 
					 | 
				
			||||||
        // ASCII Codes
 | 
					 | 
				
			||||||
        int ASCII_SPACE   = 32; // ' '
 | 
					 | 
				
			||||||
        int ASCII_DIGIT_0 = 48; // '0'
 | 
					 | 
				
			||||||
        int ASCII_DIGIT_9 = 57; // '9'
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // conversion buffer
 | 
					 | 
				
			||||||
        int NO_POS = -1;
 | 
					 | 
				
			||||||
        int BUFFERSIZE = 10;
 | 
					 | 
				
			||||||
        byte[] buffer = new byte[BUFFERSIZE];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int result = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // read line: up to EOL or EOF (i.e. error while reading)
 | 
					 | 
				
			||||||
        int bytes = 0;
 | 
					 | 
				
			||||||
        int input = System.in.read();
 | 
					 | 
				
			||||||
        while ((input != EOL) && (input != EOF)) { // read whole line
 | 
					 | 
				
			||||||
            if (bytes < BUFFERSIZE) { // only buffer first n characters
 | 
					 | 
				
			||||||
                buffer[bytes] = (byte)input;
 | 
					 | 
				
			||||||
                bytes++;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                result = PARSE_ERROR; // exceed buffer size, continue read line
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            input = System.in.read();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (input == EOF) {
 | 
					 | 
				
			||||||
            result = READ_ERROR;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // check for numbers: skip leading and trailing spaces
 | 
					 | 
				
			||||||
        // (i.e. this includes all control chars below the space ASCII code)
 | 
					 | 
				
			||||||
        int pos = 0;
 | 
					 | 
				
			||||||
        while((pos < bytes) && (buffer[pos] <= ASCII_SPACE)) pos++; // skip SP
 | 
					 | 
				
			||||||
        int posOfFirstDigit = pos;
 | 
					 | 
				
			||||||
        int posOfLastDigit = NO_POS;
 | 
					 | 
				
			||||||
        while ((pos < bytes)
 | 
					 | 
				
			||||||
               && (buffer[pos] >= ASCII_DIGIT_0)
 | 
					 | 
				
			||||||
               && (buffer[pos] <= ASCII_DIGIT_9))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            posOfLastDigit = pos;
 | 
					 | 
				
			||||||
            pos++;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        while((pos < bytes) && (buffer[pos] <= ASCII_SPACE)) pos++; // skip SP
 | 
					 | 
				
			||||||
        // produce return value
 | 
					 | 
				
			||||||
        if (result != 0) {
 | 
					 | 
				
			||||||
            // previously detected read or parse error given
 | 
					 | 
				
			||||||
        } else if ((pos != bytes) || (posOfLastDigit == NO_POS)) {
 | 
					 | 
				
			||||||
            result = PARSE_ERROR;
 | 
					 | 
				
			||||||
        } else { // convert number
 | 
					 | 
				
			||||||
            for(int i = posOfFirstDigit; i <= posOfLastDigit; i++) {
 | 
					 | 
				
			||||||
                result = result * 10 + (buffer[i] - ASCII_DIGIT_0);
 | 
					 | 
				
			||||||
                if (result > maxResult) {
 | 
					 | 
				
			||||||
                    result = PARSE_ERROR;
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return result;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,32 +0,0 @@
 | 
				
			||||||
/*****************************************************************************
 | 
					 | 
				
			||||||
    M. Thaler, Jan. 2000
 | 
					 | 
				
			||||||
    Datei:          rectang.java
 | 
					 | 
				
			||||||
    Funktion:       Bestimmt, ob Dreieck rechtwinklig ist.
 | 
					 | 
				
			||||||
    Returns:        true wenn rechtwinklig, sonst false.
 | 
					 | 
				
			||||||
    Korrekturen:    - Sept 2016, A. Gieriet
 | 
					 | 
				
			||||||
                      Refactored (sprechende Variablen Namen, etc.)
 | 
					 | 
				
			||||||
******************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class rectang {
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    public boolean Rectangular(int a, int b, int c) {
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        int aS = a*a;
 | 
					 | 
				
			||||||
        int bS = b*b;
 | 
					 | 
				
			||||||
        int cS = c*c;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        boolean isRightAngled;
 | 
					 | 
				
			||||||
        if ((a == 0) && (b == 0) && (c == 0))
 | 
					 | 
				
			||||||
            isRightAngled = false;
 | 
					 | 
				
			||||||
        else if ((aS + bS) == cS)
 | 
					 | 
				
			||||||
            isRightAngled = true;
 | 
					 | 
				
			||||||
        else if ((aS + cS) == bS)
 | 
					 | 
				
			||||||
            isRightAngled = true;
 | 
					 | 
				
			||||||
        else if ((bS + cS) == aS)
 | 
					 | 
				
			||||||
            isRightAngled = true;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            isRightAngled = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return isRightAngled;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,73 +0,0 @@
 | 
				
			||||||
/*****************************************************************************
 | 
					 | 
				
			||||||
    M. Thaler, Jan. 2000
 | 
					 | 
				
			||||||
    Datei:          triangle.java
 | 
					 | 
				
			||||||
    Funktion:       Die drei Seiten eines Dreiecks einlesen und bestimmen ob
 | 
					 | 
				
			||||||
                    das Dreieck rechtwinklig ist.
 | 
					 | 
				
			||||||
    Returns:        Nichts.
 | 
					 | 
				
			||||||
    Korrekturen:    - Maerz 2002, M. Thaler, H. Fierz
 | 
					 | 
				
			||||||
                      Abfrage bei unkorrekter Eingabe wiederholen
 | 
					 | 
				
			||||||
                    - Sept 2016, A. Gieriet
 | 
					 | 
				
			||||||
                      Refactored (sprechende Variablen-Namen,
 | 
					 | 
				
			||||||
                                  "magic" Numbers durch Symbole ersetzt, etc.)
 | 
					 | 
				
			||||||
******************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class triangle {
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    public static void main(String[] args)
 | 
					 | 
				
			||||||
        throws java.io.IOException
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        int READ_ERROR = -2;
 | 
					 | 
				
			||||||
        int MAX_NUMBER = 1000;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        read ReadInt = new read();
 | 
					 | 
				
			||||||
        rectang Rect = new rectang();
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        while (true) {
 | 
					 | 
				
			||||||
            System.out.println("\nDreiecksbestimmung (CTRL-C: Abbruch)\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            int word = 0;
 | 
					 | 
				
			||||||
            int a = 0;
 | 
					 | 
				
			||||||
            int b = 0;
 | 
					 | 
				
			||||||
            int c = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            do {
 | 
					 | 
				
			||||||
                System.out.print("Seite a: ");
 | 
					 | 
				
			||||||
                word = ReadInt.getInt(MAX_NUMBER);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            while ((word < 0) && (word != READ_ERROR));
 | 
					 | 
				
			||||||
            if (word >= 0)
 | 
					 | 
				
			||||||
                a = word;
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            do {
 | 
					 | 
				
			||||||
                System.out.print("Seite b: ");
 | 
					 | 
				
			||||||
                word = ReadInt.getInt(MAX_NUMBER);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            while ((word < 0) && (word != READ_ERROR));
 | 
					 | 
				
			||||||
            if (word >= 0)
 | 
					 | 
				
			||||||
                b = word;
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            do {
 | 
					 | 
				
			||||||
                System.out.print("Seite c: ");
 | 
					 | 
				
			||||||
                word = ReadInt.getInt(MAX_NUMBER);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            while ((word < 0) && (word != READ_ERROR));
 | 
					 | 
				
			||||||
            if (word >= 0)
 | 
					 | 
				
			||||||
                c = word;
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if (Rect.Rectangular(a, b, c) == true)
 | 
					 | 
				
			||||||
                System.out.println("-> Dreieck " + a + "-" + b + "-" + c
 | 
					 | 
				
			||||||
                                   + " ist rechtwinklig");
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                System.out.println("-> Dreieck " + a + "-" + b + "-" + c
 | 
					 | 
				
			||||||
                                   + " ist nicht rechtwinklig");
 | 
					 | 
				
			||||||
            System.out.println("\n");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        System.out.println("\n\nbye bye\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,94 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include "read.h"
 | 
					 | 
				
			||||||
#include "trace.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//#define EOF (-1) // end of file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// end-of-line
 | 
					 | 
				
			||||||
#define EOL 10 // end of line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// abnormal return values
 | 
					 | 
				
			||||||
/// parse-error
 | 
					 | 
				
			||||||
#define PARSE_ERROR (-1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ASCII Codes
 | 
					 | 
				
			||||||
/// ascii code for space
 | 
					 | 
				
			||||||
#define ASCII_SPACE   ' '
 | 
					 | 
				
			||||||
/// ascii code for 0
 | 
					 | 
				
			||||||
#define ASCII_DIGIT_0 '0'
 | 
					 | 
				
			||||||
/// ascii code for 9
 | 
					 | 
				
			||||||
#define ASCII_DIGIT_9 '9'
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
// conversion buffer
 | 
					 | 
				
			||||||
/// no buffer position sentry
 | 
					 | 
				
			||||||
#define NO_POS (-1)
 | 
					 | 
				
			||||||
/// buffer size
 | 
					 | 
				
			||||||
#define BUFFERSIZE (10)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int getInt(int maxResult)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    TRACE("getInt(%d)", maxResult);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    char buffer[BUFFERSIZE] = { 0 };
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    int result = 0;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // read line: up to EOL or EOF (i.e. error while reading)
 | 
					 | 
				
			||||||
    int bytes = 0;
 | 
					 | 
				
			||||||
    int input = getchar();
 | 
					 | 
				
			||||||
    while ((input != EOL) && (input != EOF)) { // read whole line
 | 
					 | 
				
			||||||
        if (bytes < BUFFERSIZE) { // only buffer first n characters
 | 
					 | 
				
			||||||
            buffer[bytes] = (char)input;
 | 
					 | 
				
			||||||
            bytes++;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            result = PARSE_ERROR; // exceed buffer size, continue read line
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        input = getchar();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (input == EOF) {
 | 
					 | 
				
			||||||
        result = READ_ERROR;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // check for numbers: skip leading and trailing spaces
 | 
					 | 
				
			||||||
    // (i.e. this includes all control chars below the space ASCII code)
 | 
					 | 
				
			||||||
    int pos = 0;
 | 
					 | 
				
			||||||
    while((pos < bytes) && (buffer[pos] <= ASCII_SPACE)) pos++; // skip SP
 | 
					 | 
				
			||||||
    int posOfFirstDigit = pos;
 | 
					 | 
				
			||||||
    int posOfLastDigit = NO_POS;
 | 
					 | 
				
			||||||
    while ((pos < bytes)
 | 
					 | 
				
			||||||
           && (buffer[pos] >= ASCII_DIGIT_0)
 | 
					 | 
				
			||||||
           && (buffer[pos] <= ASCII_DIGIT_9))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            posOfLastDigit = pos;
 | 
					 | 
				
			||||||
            pos++;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    while((pos < bytes) && (buffer[pos] <= ASCII_SPACE)) pos++; // skip SP
 | 
					 | 
				
			||||||
    // produce return value
 | 
					 | 
				
			||||||
    if (result != 0) {
 | 
					 | 
				
			||||||
        // previously detected read or parse error given
 | 
					 | 
				
			||||||
    } else if ((pos != bytes) || (posOfLastDigit == NO_POS)) {
 | 
					 | 
				
			||||||
        result = PARSE_ERROR;
 | 
					 | 
				
			||||||
    } else { // convert number
 | 
					 | 
				
			||||||
        for(int i = posOfFirstDigit; i <= posOfLastDigit; i++) {
 | 
					 | 
				
			||||||
            result = result * 10 + (buffer[i] - ASCII_DIGIT_0);
 | 
					 | 
				
			||||||
            if (result > maxResult) {
 | 
					 | 
				
			||||||
                result = PARSE_ERROR;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,27 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#ifndef READ_H
 | 
					 | 
				
			||||||
#define READ_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// I/O error which leads to aborting.
 | 
					 | 
				
			||||||
#define READ_ERROR (-2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief     Reads a line from stdin and tries to parse it as number (with optional leading and trailing spaces).
 | 
					 | 
				
			||||||
 * @param[in] maxResult  gives the limit for the number to be read.
 | 
					 | 
				
			||||||
 * @returns   the succesfully read and parsed number or a negative value if in error (READ_ERROR in case of I/O error).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int getInt(int maxResult);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,38 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "rectang.h"
 | 
					 | 
				
			||||||
#include "trace.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int rectangular(int a, int b, int c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    TRACE("rectangular(%d, %d, %d)", a, b, c);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    int aS = a*a;
 | 
					 | 
				
			||||||
    int bS = b*b;
 | 
					 | 
				
			||||||
    int cS = c*c;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    int isRightAngled;
 | 
					 | 
				
			||||||
    if ((a == 0) && (b == 0) && (c == 0))
 | 
					 | 
				
			||||||
        isRightAngled = 0;
 | 
					 | 
				
			||||||
    else if ((aS + bS) == cS)
 | 
					 | 
				
			||||||
        isRightAngled = 1;
 | 
					 | 
				
			||||||
    else if ((aS + cS) == bS)
 | 
					 | 
				
			||||||
        isRightAngled = 1;
 | 
					 | 
				
			||||||
    else if ((bS + cS) == aS)
 | 
					 | 
				
			||||||
        isRightAngled = 1;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        isRightAngled = 0;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return isRightAngled;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,26 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#ifndef RECTANG_H
 | 
					 | 
				
			||||||
#define RECTANG_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief     checks if the three lengths give a right-angled triangle.
 | 
					 | 
				
			||||||
 * @param[in] a 1st side
 | 
					 | 
				
			||||||
 * @param[in] b 2nd side
 | 
					 | 
				
			||||||
 * @param[in] c 3rd side
 | 
					 | 
				
			||||||
 * @returns 1 if right-angled, 0 otherwise
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int rectangular(int a, int b, int c);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,26 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#ifndef TRACE_H
 | 
					 | 
				
			||||||
#define TRACE_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  TRACE macro.
 | 
					 | 
				
			||||||
 * @param[in] MSG  "..." format string literal.
 | 
					 | 
				
			||||||
 * @param[in] ...  optional arguments to the format string.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define TRACE(MSG, ...) do { (void)fprintf(stderr, "TRACE: " MSG "\n", ##__VA_ARGS__); } while(0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,78 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include "read.h"
 | 
					 | 
				
			||||||
#include "rectang.h"
 | 
					 | 
				
			||||||
#include "trace.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// max side length
 | 
					 | 
				
			||||||
#define MAX_NUMBER 1000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Main entry point.
 | 
					 | 
				
			||||||
 * @returns Returns EXIT_SUCCESS (=0) on success, EXIT_FAILURE (=1) on failure.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    TRACE("main()");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while (1) {
 | 
					 | 
				
			||||||
        (void)printf("\nDreiecksbestimmung (CTRL-C: Abbruch)\n\n");
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        int word = 0;
 | 
					 | 
				
			||||||
        int a = 0;
 | 
					 | 
				
			||||||
        int b = 0;
 | 
					 | 
				
			||||||
        int c = 0;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        do {
 | 
					 | 
				
			||||||
            (void)printf("Seite a: ");
 | 
					 | 
				
			||||||
            word = getInt(MAX_NUMBER);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        while ((word < 0) && (word != READ_ERROR));
 | 
					 | 
				
			||||||
        if (word >= 0)
 | 
					 | 
				
			||||||
            a = word;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        do {
 | 
					 | 
				
			||||||
            (void)printf("Seite b: ");
 | 
					 | 
				
			||||||
            word = getInt(MAX_NUMBER);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        while ((word < 0) && (word != READ_ERROR));
 | 
					 | 
				
			||||||
        if (word >= 0)
 | 
					 | 
				
			||||||
            b = word;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        do {
 | 
					 | 
				
			||||||
            (void)printf("Seite c: ");
 | 
					 | 
				
			||||||
            word = getInt(MAX_NUMBER);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        while ((word < 0) && (word != READ_ERROR));
 | 
					 | 
				
			||||||
        if (word >= 0)
 | 
					 | 
				
			||||||
            c = word;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (rectangular(a, b, c))
 | 
					 | 
				
			||||||
            (void)printf("-> Dreieck %d-%d-%d ist rechtwinklig\n", a, b, c);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            (void)printf("-> Dreieck %d-%d-%d ist nicht rechtwinklig\n", a, b, c);
 | 
					 | 
				
			||||||
        (void)printf("\n\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    (void)printf("\n\nbye bye\n\n");
 | 
					 | 
				
			||||||
    return EXIT_SUCCESS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,12 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
a
 | 
					 | 
				
			||||||
 a
 | 
					 | 
				
			||||||
  a
 | 
					 | 
				
			||||||
  3
 | 
					 | 
				
			||||||
4444
 | 
					 | 
				
			||||||
 4444
 | 
					 | 
				
			||||||
  44444444444444
 | 
					 | 
				
			||||||
               4
 | 
					 | 
				
			||||||
  4
 | 
					 | 
				
			||||||
											5
 | 
					 | 
				
			||||||
					5
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,12 +0,0 @@
 | 
				
			||||||
3
 | 
					 | 
				
			||||||
4
 | 
					 | 
				
			||||||
6
 | 
					 | 
				
			||||||
5
 | 
					 | 
				
			||||||
4
 | 
					 | 
				
			||||||
4
 | 
					 | 
				
			||||||
3
 | 
					 | 
				
			||||||
5
 | 
					 | 
				
			||||||
5
 | 
					 | 
				
			||||||
33
 | 
					 | 
				
			||||||
43
 | 
					 | 
				
			||||||
55
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,12 +0,0 @@
 | 
				
			||||||
3
 | 
					 | 
				
			||||||
4
 | 
					 | 
				
			||||||
5
 | 
					 | 
				
			||||||
5
 | 
					 | 
				
			||||||
4
 | 
					 | 
				
			||||||
3
 | 
					 | 
				
			||||||
3
 | 
					 | 
				
			||||||
5
 | 
					 | 
				
			||||||
4
 | 
					 | 
				
			||||||
33
 | 
					 | 
				
			||||||
44
 | 
					 | 
				
			||||||
55
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,205 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include "CUnit/Basic.h"
 | 
					 | 
				
			||||||
#include "test_utils.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef TARGET // must be given by the make file --> see test target
 | 
					 | 
				
			||||||
#error missing TARGET define
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief The name of the STDOUT text file.
 | 
					 | 
				
			||||||
#define OUTFILE "stdout.txt"
 | 
					 | 
				
			||||||
/// @brief The name of the STDERR text file.
 | 
					 | 
				
			||||||
#define ERRFILE "stderr.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief The stimulus for the right-angled triangles
 | 
					 | 
				
			||||||
#define INFILE_RIGHT_ANGLED "stim-right-angled.input"
 | 
					 | 
				
			||||||
/// @brief The stimulus for the not right-angled triangles
 | 
					 | 
				
			||||||
#define INFILE_NOT_RIGHT_ANGLED "stim-not-right-angled.input"
 | 
					 | 
				
			||||||
/// @brief The stimulus for input errors
 | 
					 | 
				
			||||||
#define INFILE_ERROR "stim-error.input"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// setup & cleanup
 | 
					 | 
				
			||||||
static int setup(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	remove_file_if_exists(OUTFILE);
 | 
					 | 
				
			||||||
	remove_file_if_exists(ERRFILE);
 | 
					 | 
				
			||||||
	return 0; // success
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int teardown(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// Do nothing.
 | 
					 | 
				
			||||||
	// Especially: do not remove result files - they are removed in int setup(void) *before* running a test.
 | 
					 | 
				
			||||||
	return 0; // success
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// tests
 | 
					 | 
				
			||||||
static void test_right_angled(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const char *out_txt[] = {
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite b: Seite c: -> Dreieck 3-4-5 ist rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite b: Seite c: -> Dreieck 5-4-3 ist rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite b: Seite c: -> Dreieck 3-5-4 ist rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite b: Seite c: -> Dreieck 33-44-55 ist rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: \n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"bye bye\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// act
 | 
					 | 
				
			||||||
	int exit_code = system(XSTR(TARGET) " 1>" OUTFILE " 2>" ERRFILE " <" INFILE_RIGHT_ANGLED);
 | 
					 | 
				
			||||||
	// assert
 | 
					 | 
				
			||||||
	CU_ASSERT_EQUAL(exit_code, 0);
 | 
					 | 
				
			||||||
	assert_lines(OUTFILE, out_txt, sizeof(out_txt)/sizeof(*out_txt));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_not_right_angled(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const char *out_txt[] = {
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite b: Seite c: -> Dreieck 3-4-6 ist nicht rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite b: Seite c: -> Dreieck 5-4-4 ist nicht rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite b: Seite c: -> Dreieck 3-5-5 ist nicht rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite b: Seite c: -> Dreieck 33-43-55 ist nicht rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: \n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"bye bye\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// act
 | 
					 | 
				
			||||||
	int exit_code = system(XSTR(TARGET) " 1>" OUTFILE " 2>" ERRFILE " <" INFILE_NOT_RIGHT_ANGLED);
 | 
					 | 
				
			||||||
	// assert
 | 
					 | 
				
			||||||
	CU_ASSERT_EQUAL(exit_code, 0);
 | 
					 | 
				
			||||||
	assert_lines(OUTFILE, out_txt, sizeof(out_txt)/sizeof(*out_txt));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_trace(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const char *err_txt[] = {
 | 
					 | 
				
			||||||
		"TRACE: main()\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: rectangular(3, 4, 6)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: rectangular(5, 4, 4)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: rectangular(3, 5, 5)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
		"TRACE: rectangular(33, 43, 55)\n",
 | 
					 | 
				
			||||||
		"TRACE: getInt(1000)\n",
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// act
 | 
					 | 
				
			||||||
	int exit_code = system(XSTR(TARGET) " 1>" OUTFILE " 2>" ERRFILE " <" INFILE_NOT_RIGHT_ANGLED);
 | 
					 | 
				
			||||||
	// assert
 | 
					 | 
				
			||||||
	CU_ASSERT_EQUAL(exit_code, 0);
 | 
					 | 
				
			||||||
	assert_lines(ERRFILE, err_txt, sizeof(err_txt)/sizeof(*err_txt));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_error(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const char *out_txt[] = {
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: Seite a: Seite a: Seite a: Seite a: Seite b: Seite b: Seite b: Seite b: Seite b: Seite c: Seite c: -> Dreieck 3-4-5 ist rechtwinklig\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Dreiecksbestimmung (CTRL-C: Abbruch)\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"Seite a: \n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
		"bye bye\n",
 | 
					 | 
				
			||||||
		"\n",
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	// act
 | 
					 | 
				
			||||||
	int exit_code = system(XSTR(TARGET) " 1>" OUTFILE " 2>" ERRFILE " <" INFILE_ERROR);
 | 
					 | 
				
			||||||
	// assert
 | 
					 | 
				
			||||||
	CU_ASSERT_EQUAL(exit_code, 0);
 | 
					 | 
				
			||||||
	assert_lines(OUTFILE, out_txt, sizeof(out_txt)/sizeof(*out_txt));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Registers and runs the tests.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// setup, run, teardown
 | 
					 | 
				
			||||||
	TestMainBasic("Triangle", setup, teardown
 | 
					 | 
				
			||||||
				  , test_right_angled
 | 
					 | 
				
			||||||
				  , test_not_right_angled
 | 
					 | 
				
			||||||
				  , test_trace
 | 
					 | 
				
			||||||
				  , test_error
 | 
					 | 
				
			||||||
				  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,57 +0,0 @@
 | 
				
			||||||
SNP_SHARED_MAKEFILE := $(if $(SNP_SHARED_MAKEFILE),$(SNP_SHARED_MAKEFILE),"~/snp/shared.mk")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TARGET     := bin/dep2dot
 | 
					 | 
				
			||||||
SOURCES    := src/main.c src/data.c src/output.c
 | 
					 | 
				
			||||||
TSTSOURCES := tests/tests.c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
include $(SNP_SHARED_MAKEFILE)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# DEPFILES :=  ... define a list of png file names: %.c -> %.c.png
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
DEPFILES   := $(SOURCES:%.c=%.c.png)
 | 
					 | 
				
			||||||
# END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# define dep target as .PHONEY
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
.PHONY: dep
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# define dep target depending on FULLTARGET and DEPFILES above
 | 
					 | 
				
			||||||
# action: echo some text telling that the target is done using $@ - the echo command shall not be echoed before execution
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
dep: $(FULLTARGET) $(DEPFILES)
 | 
					 | 
				
			||||||
	@echo "### $@ done ###"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# define new suffix rule for %.png depending on %.dot
 | 
					 | 
				
			||||||
# action: dot -Tpng $< >$@ || $(RM) $@
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
%.png: %.dot
 | 
					 | 
				
			||||||
	dot -Tpng $< >$@ || $(RM) $@
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# define new suffix rule for %.dot depending on %.dep
 | 
					 | 
				
			||||||
# action: call $(TARGET) $(@:.dot=) <$< >$@ || $(RM) $@
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
%.dot: %.dep
 | 
					 | 
				
			||||||
	$(TARGET) $(@:.dot=) <$< >$@ || $(RM) $@
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# converts any .c file into a .c.dep file by means of GCC -H switch
 | 
					 | 
				
			||||||
# note: it removes intermediate files which were created as side effect
 | 
					 | 
				
			||||||
%.c.dep: %.c
 | 
					 | 
				
			||||||
	$(COMPILE.c) -H -o $@.x $< 2>$@ && $(RM) $@.x $@.d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# cleanup all results, including the ones od creating the dependencies
 | 
					 | 
				
			||||||
dep-clean: clean
 | 
					 | 
				
			||||||
	$(RM) $(DEPFILES) $(wildcard src/*.dep src/*.dot)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,8 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @mainpage SNP - P04 Modularisation
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @section Purpose
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This is a lab for splitting functionality into multiple modules.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,149 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief  Implementation of the dependency file access.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "data.h"
 | 
					 | 
				
			||||||
#include "error.h"
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <libgen.h>
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MAX_PATH_LEN     512  ///< @brief  Arbitrarily chosen maximum accepted path lenght.
 | 
					 | 
				
			||||||
#define MAX_LINE_LEN     512  ///< @brief  Arbitrarily chosen maximum accepted line length
 | 
					 | 
				
			||||||
#define MAX_DIRS         64   ///< @brief  Arbitrarily chosen maximum number of supported individual directories per dependency file.
 | 
					 | 
				
			||||||
#define MAX_FILES        256  ///< @brief  Arbitrarily chosen maximum number of supported individual denendency entries.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief          Declaration of POSIX (but not C99) function.
 | 
					 | 
				
			||||||
 * @param  s [IN]  The string to duplicate on the heap memory.
 | 
					 | 
				
			||||||
 * @return         The duplicated string.
 | 
					 | 
				
			||||||
 * @remark         Since the Makefile calls gcc with -std=c99, non-C99 POSIX and GNU extensions are excluded - the glibc, though, provides the function to the linker.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
char *strdup(const char *s); // not stdc99, but available in the glibc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                Initialized the data structure before the data is to be read from th edependency file.
 | 
					 | 
				
			||||||
 * @param  data [INOUT]  The address of the instance to initialize.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void init(data_t *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(data);
 | 
					 | 
				
			||||||
	memset(data, 0, sizeof(data_t));
 | 
					 | 
				
			||||||
	data->dirs = malloc(MAX_DIRS * sizeof(dir_t));
 | 
					 | 
				
			||||||
	if (!data->dirs) FATAL("no memory left");
 | 
					 | 
				
			||||||
	data->files = malloc(MAX_FILES * sizeof(file_t));
 | 
					 | 
				
			||||||
	if (!data->files) FATAL("no memory left");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                Updates the directory list with the given data.
 | 
					 | 
				
			||||||
 * @param  data [INOUT]  The instance to update.
 | 
					 | 
				
			||||||
 * @param  path [IN]     The file path of a dependency entry as given by the dependency file.
 | 
					 | 
				
			||||||
 * @return               The index of the directory entry (either an existing matching one or a newly added one).
 | 
					 | 
				
			||||||
 * @remark               Extracts the directory part by means of dirname() from the given path and looks up an existing entry or adds a new one.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static size_t get_or_add_dir(data_t *data, const char *path)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(data);
 | 
					 | 
				
			||||||
	assert(path);
 | 
					 | 
				
			||||||
	// The function dirname() gives no guarantee to not modify the parameter, therefore, need to produce a copy before calling dirname().
 | 
					 | 
				
			||||||
	// Likewise, the returned value may refer to the passed paremater, therefore, a copy is made from the return value.
 | 
					 | 
				
			||||||
	char *dup = strdup(path);
 | 
					 | 
				
			||||||
	if (!dup) FATAL("no memory left");
 | 
					 | 
				
			||||||
	char *name = strdup(dirname(dup));
 | 
					 | 
				
			||||||
	if (!name) FATAL("no memory left");
 | 
					 | 
				
			||||||
	free(dup);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// search for a matching entry...
 | 
					 | 
				
			||||||
	size_t i = 0;
 | 
					 | 
				
			||||||
	while(i < data->n_dirs && strcmp(data->dirs[i].name, name) != 0) {
 | 
					 | 
				
			||||||
		i++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (i >= MAX_DIRS) FATAL("too many directories");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (i == data->n_dirs) { // no match found: add
 | 
					 | 
				
			||||||
		// handover the allocated name to the owning new directory entry
 | 
					 | 
				
			||||||
		dir_t dir = { .name = name };
 | 
					 | 
				
			||||||
		// append the new directory entry
 | 
					 | 
				
			||||||
		data->dirs[data->n_dirs] = dir;
 | 
					 | 
				
			||||||
		data->n_dirs++;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// release the name since match found, and therefore, no need to keep the allocated name anymore
 | 
					 | 
				
			||||||
		free(name);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return i;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                Add a file entry from the dependency file to the data structure.
 | 
					 | 
				
			||||||
 * @param  data [INOUT]  The data container instance.
 | 
					 | 
				
			||||||
 * @param  path [IN]     The path of one file entry from the dependency file.
 | 
					 | 
				
			||||||
 * @param  level [IN]    The dependency level of the file entry from the dependency file.
 | 
					 | 
				
			||||||
 * @remark               The sequence of entries in the dependency file is relevant - it implies direct dependencies.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void add_file(data_t *data, const char *path, size_t level)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(data);
 | 
					 | 
				
			||||||
	assert(path);
 | 
					 | 
				
			||||||
	// The function basename() gives no guarantee to not modify the parameter, therefore, need to produce a copy before calling basename().
 | 
					 | 
				
			||||||
	// Likewise, the returned value may refer to the passed paremater, therefore, a copy is made from the return value.
 | 
					 | 
				
			||||||
	char *dup = strdup(path);
 | 
					 | 
				
			||||||
	if (!dup) FATAL("no memory left");
 | 
					 | 
				
			||||||
	char *name = strdup(basename(dup));
 | 
					 | 
				
			||||||
	if (!name) FATAL("no memory left");
 | 
					 | 
				
			||||||
	free(dup);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (data->n_files >= MAX_FILES) FATAL("too many files");
 | 
					 | 
				
			||||||
	// produce a file entry
 | 
					 | 
				
			||||||
	file_t file = { .name = name, .dir = get_or_add_dir(data, path), .level = level };
 | 
					 | 
				
			||||||
	data->files[data->n_files] = file;
 | 
					 | 
				
			||||||
	data->n_files++;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                Processes one dependency line of the dependency file.
 | 
					 | 
				
			||||||
 * @param  data [INOUT]  The data container instance.
 | 
					 | 
				
			||||||
 * @param  line [IN]     The line to parse and store in data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void process_line(data_t *data, const char line[])
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	size_t len = strlen(line);
 | 
					 | 
				
			||||||
	assert(len > 0);
 | 
					 | 
				
			||||||
	assert(line[0] == '.');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// read level
 | 
					 | 
				
			||||||
	size_t i = strspn(line, ".");
 | 
					 | 
				
			||||||
	size_t level = i;
 | 
					 | 
				
			||||||
	// skip spaces
 | 
					 | 
				
			||||||
	i += strspn(line+i, " \t");
 | 
					 | 
				
			||||||
	// take rest as path and add the file to the records
 | 
					 | 
				
			||||||
	add_file(data, line+i, level);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * The public interface. 
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const data_t data_read_all(const char *root)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	data_t data;
 | 
					 | 
				
			||||||
	init(&data);
 | 
					 | 
				
			||||||
	// add as first file the root for the given dependencies
 | 
					 | 
				
			||||||
	add_file(&data, root, 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	char line[MAX_LINE_LEN] = { 0 };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// read all stdin line and only process dependency lines (those starting on a '.')
 | 
					 | 
				
			||||||
	clearerr(stdin);
 | 
					 | 
				
			||||||
	while(fgets(line, MAX_LINE_LEN, stdin)) {
 | 
					 | 
				
			||||||
		size_t len = strlen(line);
 | 
					 | 
				
			||||||
		if (len > 0 && line[len-1] == '\n' && line[0] == '.') { // only dependency lines
 | 
					 | 
				
			||||||
			line[len-1] = '\0';
 | 
					 | 
				
			||||||
			process_line(&data, line);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,72 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief  Access to the GCC produced dependency data (via -H command line option).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// begin of include guard
 | 
					 | 
				
			||||||
// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
#ifndef _DATA_H_
 | 
					 | 
				
			||||||
#define _DATA_H_
 | 
					 | 
				
			||||||
// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// includes which are needed in this header file
 | 
					 | 
				
			||||||
// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
#include <stddef.h>
 | 
					 | 
				
			||||||
// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  Directory container for file entries of the dependency file.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
	const char *name; ///< @brief the path name of the directory as given by the GCC produced dependency file.
 | 
					 | 
				
			||||||
} dir_t;
 | 
					 | 
				
			||||||
// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  File container for the file entries of the dependency file.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
	const char *name; ///< @brief  The base name of the file from the GGC produced dependency file (i.e. the plain name, without any directory path).
 | 
					 | 
				
			||||||
	size_t dir;       ///< @brief  The index of the directory entry which represents the path as given by the dependency file.
 | 
					 | 
				
			||||||
	size_t level;     ///< @brief  The level as read out from the dependecy file.
 | 
					 | 
				
			||||||
} file_t;
 | 
					 | 
				
			||||||
// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  Overall container for all directories and all files from the dependency file.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    size_t n_dirs;  ///< @brief  The number of valid entries in the dirs list.
 | 
					 | 
				
			||||||
	dir_t *dirs;    ///< @brief  The list of directories.
 | 
					 | 
				
			||||||
	size_t n_files; ///< @brief  The number of valid entries in the files list.
 | 
					 | 
				
			||||||
	file_t *files;  ///< @brief  The list of files from the dependency file (the sequence is relevant to determine the dependencies).
 | 
					 | 
				
			||||||
} data_t;
 | 
					 | 
				
			||||||
// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief            Entry function to read the deendency data from stdin.
 | 
					 | 
				
			||||||
 * @param root [IN]  The name of the root file (the deoendency file does not mention the root file, so, it has to be passed from outside).
 | 
					 | 
				
			||||||
 * @return           The container of the read data from stdin. See the documentation on gcc -H for details on the dependencies, etc.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
const data_t data_read_all(const char *root);
 | 
					 | 
				
			||||||
// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// end of include guard
 | 
					 | 
				
			||||||
// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
#endif // _DATA_H_
 | 
					 | 
				
			||||||
// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,17 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief  Error handling convenience functions.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#ifndef _ERROR_H_
 | 
					 | 
				
			||||||
#define _ERROR_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stddef.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  Prints the message to stderr and terminates with EXIT_FAILURE.
 | 
					 | 
				
			||||||
 * @param  MSG [IN]  The "..." *string literal* to emit as error - no format parameters nor variables supported.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define FATAL(MSG) do { fprintf(stderr, "ERROR: %s\n", MSG); exit(EXIT_FAILURE); } while(0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // _ERROR_H_
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,36 +0,0 @@
 | 
				
			||||||
 /* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab P04 dep2dot
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "error.h"
 | 
					 | 
				
			||||||
#include "data.h"
 | 
					 | 
				
			||||||
#include "output.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief   main function
 | 
					 | 
				
			||||||
 * @param   argc [in] number of entries in argv
 | 
					 | 
				
			||||||
 * @param   argv [in] program name plus command line arguments
 | 
					 | 
				
			||||||
 * @returns returns success if valid date is given, failure otherwise
 | 
					 | 
				
			||||||
 * @remark  Prerequisit to convert the resulting DOT file on the shell: sodo apt install graphviz
 | 
					 | 
				
			||||||
 * @remark  Convert: gcc -H ... file.c ... 2>file.dep ; dep2dot file.c <file.dep >file.dot && dot -Tpng file.dot >file.png
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(int argc, const char *argv[])
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (argc < 2) FATAL("missing arguments\nusage: dep2dot file.c <file.dep >file.dot   # from gcc -H ... file.c ... 2>file.dep\n");
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	output_dot(data_read_all(argv[1]));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return EXIT_SUCCESS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,95 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Provides output functions for various file formats.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "output.h"
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  Writes the node name of the given file.
 | 
					 | 
				
			||||||
 * @param  file [IN]  The file for which to write the node name.
 | 
					 | 
				
			||||||
 * @remark The dependency data contain duplicates of file entries - the node name must be unique for the path and the *basename* of the files.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void print_node(file_t file)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printf("\"%s (cluster_c%zd)\"", file.name, file.dir);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  Recursively writes the individual direct dependencies for the file given by curr.
 | 
					 | 
				
			||||||
 * @param  files [IN] The array of all files - the sequence is relevant.
 | 
					 | 
				
			||||||
 * @param  len [IN]   The lenght of the files array, i.e. the upper limit for curr values and the subsequent index values.
 | 
					 | 
				
			||||||
 * @param  curr [IN]  The index into files for the current root for dependencies: curr -> x, curr -> y, ...
 | 
					 | 
				
			||||||
 * @return            Returns the index into files for the next file to process (i.e. curr value for the next call to this function).
 | 
					 | 
				
			||||||
 * @remark            For a given *curr* file, all following files are with depth level + 1 are direct include files.
 | 
					 | 
				
			||||||
 * @remark            All files with a higher level are *indirect* include files, thus *direct* includes from files processed by recursive calls.
 | 
					 | 
				
			||||||
 * @remark            The list of direct includes to the *curr* file terminates with a level equal of less the the *curr* one (or when the list is exchausted).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static size_t dependencies(file_t files[], size_t len, size_t curr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(curr < len);
 | 
					 | 
				
			||||||
	size_t level = files[curr].level;
 | 
					 | 
				
			||||||
	size_t file = curr + 1;
 | 
					 | 
				
			||||||
	while(file < len && files[file].level > level) {
 | 
					 | 
				
			||||||
		if (files[file].level == level + 1) {
 | 
					 | 
				
			||||||
			// Write to stdout "  file -> include;\n" where file and include are the DOT node names of the respective files
 | 
					 | 
				
			||||||
			// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
			printf("  ");
 | 
					 | 
				
			||||||
			print_node(files[curr]);
 | 
					 | 
				
			||||||
			printf(" -> ");
 | 
					 | 
				
			||||||
			print_node(files[file]);
 | 
					 | 
				
			||||||
			printf(";\n");
 | 
					 | 
				
			||||||
			// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
			file = dependencies(files, len, file);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			file++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return file;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Public interface
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void output_dot(const data_t data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printf("digraph dep {\n");
 | 
					 | 
				
			||||||
	// nodes
 | 
					 | 
				
			||||||
	printf("  node [shape=box]\n");
 | 
					 | 
				
			||||||
	for (size_t file = 0; file < data.n_files; file++) {
 | 
					 | 
				
			||||||
		// Write to stdout "  file [label=\"name\"];\n" where file is the DOT node name and name is the file name
 | 
					 | 
				
			||||||
		// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
		printf("  ");
 | 
					 | 
				
			||||||
		print_node(data.files[file]);
 | 
					 | 
				
			||||||
		printf(" [label=\"%s\"];\n", data.files[file].name);
 | 
					 | 
				
			||||||
		// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// directory clusters
 | 
					 | 
				
			||||||
	for (size_t dir = 0; dir < data.n_dirs; dir++) {
 | 
					 | 
				
			||||||
		printf("  subgraph cluster_c%zd {\n", dir);
 | 
					 | 
				
			||||||
		printf("    label=\"%s\"; %s\n", data.dirs[dir].name, strncmp(data.dirs[dir].name, "/usr/", 5) == 0 ? "style=filled; color=lightgrey;" : "color=black;");
 | 
					 | 
				
			||||||
		for (size_t file = 0; file < data.n_files; file++) {
 | 
					 | 
				
			||||||
			if (data.files[file].dir == dir) {
 | 
					 | 
				
			||||||
				// Write to stdout "    file;\n" where file is the DOT node name
 | 
					 | 
				
			||||||
				// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
				printf("    ");
 | 
					 | 
				
			||||||
				print_node(data.files[file]);
 | 
					 | 
				
			||||||
				printf(";\n");
 | 
					 | 
				
			||||||
				// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		printf("  }\n");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// dependencies
 | 
					 | 
				
			||||||
	size_t curr = 0;
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		curr = dependencies(data.files, data.n_files, curr);
 | 
					 | 
				
			||||||
	} while(curr < data.n_files);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	printf("}\n");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,20 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief  Provides output functions for various file formats.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
// define proper header file here, with include gaurd, etc.
 | 
					 | 
				
			||||||
// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
#ifndef _OUTPUT_H_
 | 
					 | 
				
			||||||
#define _OUTPUT_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "data.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief           Produces DOT output of the dependencies given in data.
 | 
					 | 
				
			||||||
 * @param data [IN] Container of the dependenciy data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void output_dot(const data_t data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // _OUTPUT_H_
 | 
					 | 
				
			||||||
// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
Test File
 | 
					 | 
				
			||||||
. dir1/h1_1
 | 
					 | 
				
			||||||
.. dir1/h1_1_2
 | 
					 | 
				
			||||||
. dir1/h1_2
 | 
					 | 
				
			||||||
. dir2/h2_1
 | 
					 | 
				
			||||||
.. dir1/h1_1
 | 
					 | 
				
			||||||
Done
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,2 +0,0 @@
 | 
				
			||||||
Test File
 | 
					 | 
				
			||||||
Done
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,140 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Test suite for the given package.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <sys/wait.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#include <CUnit/Basic.h>
 | 
					 | 
				
			||||||
#include "test_utils.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef TARGET // must be given by the make file --> see test target
 | 
					 | 
				
			||||||
#error missing TARGET define
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief alias for EXIT_SUCCESS
 | 
					 | 
				
			||||||
#define OK   EXIT_SUCCESS
 | 
					 | 
				
			||||||
/// @brief alias for EXIT_FAILURE
 | 
					 | 
				
			||||||
#define FAIL EXIT_FAILURE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief The name of the STDOUT text file.
 | 
					 | 
				
			||||||
#define OUTFILE "stdout.txt"
 | 
					 | 
				
			||||||
/// @brief The name of the STDERR text file.
 | 
					 | 
				
			||||||
#define ERRFILE "stderr.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief test data file
 | 
					 | 
				
			||||||
#define IN_NO_DEP "no_dep.input"
 | 
					 | 
				
			||||||
/// @brief test data file
 | 
					 | 
				
			||||||
#define IN_DEP "dep.input"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// setup & cleanup
 | 
					 | 
				
			||||||
static int setup(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	remove_file_if_exists(OUTFILE);
 | 
					 | 
				
			||||||
	remove_file_if_exists(ERRFILE);
 | 
					 | 
				
			||||||
	return 0; // success
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int teardown(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// Do nothing.
 | 
					 | 
				
			||||||
	// Especially: do not remove result files - they are removed in int setup(void) *before* running a test.
 | 
					 | 
				
			||||||
	return 0; // success
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// tests
 | 
					 | 
				
			||||||
static void test_fail_no_arg(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// arrange & act & assert
 | 
					 | 
				
			||||||
	CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " >" OUTFILE " 2>" ERRFILE)), FAIL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_no_dep(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const char *out_txt[] = {
 | 
					 | 
				
			||||||
		"digraph dep {\n",
 | 
					 | 
				
			||||||
		"  node [shape=box]\n",
 | 
					 | 
				
			||||||
		"  \"root (cluster_c0)\" [label=\"root\"];\n",
 | 
					 | 
				
			||||||
		"  subgraph cluster_c0 {\n",
 | 
					 | 
				
			||||||
		"    label=\".\"; color=black;\n",
 | 
					 | 
				
			||||||
		"    \"root (cluster_c0)\";\n",
 | 
					 | 
				
			||||||
		"  }\n",
 | 
					 | 
				
			||||||
		"}\n",
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert
 | 
					 | 
				
			||||||
	CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " root <" IN_NO_DEP " >" OUTFILE " 2>" ERRFILE)), OK);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// assert
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	assert_lines(OUTFILE, out_txt, sizeof(out_txt)/sizeof(*out_txt));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_dep(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const char *out_txt[] = {
 | 
					 | 
				
			||||||
		"digraph dep {\n",
 | 
					 | 
				
			||||||
		"  node [shape=box]\n",
 | 
					 | 
				
			||||||
		"  \"root (cluster_c0)\" [label=\"root\"];\n",
 | 
					 | 
				
			||||||
		"  \"h1_1 (cluster_c1)\" [label=\"h1_1\"];\n",
 | 
					 | 
				
			||||||
		"  \"h1_1_2 (cluster_c1)\" [label=\"h1_1_2\"];\n",
 | 
					 | 
				
			||||||
		"  \"h1_2 (cluster_c1)\" [label=\"h1_2\"];\n",
 | 
					 | 
				
			||||||
		"  \"h2_1 (cluster_c2)\" [label=\"h2_1\"];\n",
 | 
					 | 
				
			||||||
		"  \"h1_1 (cluster_c1)\" [label=\"h1_1\"];\n",
 | 
					 | 
				
			||||||
		"  subgraph cluster_c0 {\n",
 | 
					 | 
				
			||||||
		"    label=\".\"; color=black;\n",
 | 
					 | 
				
			||||||
		"    \"root (cluster_c0)\";\n",
 | 
					 | 
				
			||||||
		"  }\n",
 | 
					 | 
				
			||||||
		"  subgraph cluster_c1 {\n",
 | 
					 | 
				
			||||||
		"    label=\"dir1\"; color=black;\n",
 | 
					 | 
				
			||||||
		"    \"h1_1 (cluster_c1)\";\n",
 | 
					 | 
				
			||||||
		"    \"h1_1_2 (cluster_c1)\";\n",
 | 
					 | 
				
			||||||
		"    \"h1_2 (cluster_c1)\";\n",
 | 
					 | 
				
			||||||
		"    \"h1_1 (cluster_c1)\";\n",
 | 
					 | 
				
			||||||
		"  }\n",
 | 
					 | 
				
			||||||
		"  subgraph cluster_c2 {\n",
 | 
					 | 
				
			||||||
		"    label=\"dir2\"; color=black;\n",
 | 
					 | 
				
			||||||
		"    \"h2_1 (cluster_c2)\";\n",
 | 
					 | 
				
			||||||
		"  }\n",
 | 
					 | 
				
			||||||
		"  \"root (cluster_c0)\" -> \"h1_1 (cluster_c1)\";\n",
 | 
					 | 
				
			||||||
		"  \"h1_1 (cluster_c1)\" -> \"h1_1_2 (cluster_c1)\";\n",
 | 
					 | 
				
			||||||
		"  \"root (cluster_c0)\" -> \"h1_2 (cluster_c1)\";\n",
 | 
					 | 
				
			||||||
		"  \"root (cluster_c0)\" -> \"h2_1 (cluster_c2)\";\n",
 | 
					 | 
				
			||||||
		"  \"h2_1 (cluster_c2)\" -> \"h1_1 (cluster_c1)\";\n",
 | 
					 | 
				
			||||||
		"}\n",
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert
 | 
					 | 
				
			||||||
	CU_ASSERT_EQUAL(WEXITSTATUS(system(XSTR(TARGET) " root <" IN_DEP " >" OUTFILE " 2>" ERRFILE)), OK);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// assert
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	assert_lines(OUTFILE, out_txt, sizeof(out_txt)/sizeof(*out_txt));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Registers and runs the tests.
 | 
					 | 
				
			||||||
 * @returns success (0) or one of the CU_ErrorCode (>0)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// setup, run, teardown
 | 
					 | 
				
			||||||
	TestMainBasic("lab test", setup, teardown
 | 
					 | 
				
			||||||
				  , test_fail_no_arg
 | 
					 | 
				
			||||||
				  , test_no_dep
 | 
					 | 
				
			||||||
				  , test_dep
 | 
					 | 
				
			||||||
				  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,9 +0,0 @@
 | 
				
			||||||
SNP_SHARED_MAKEFILE := $(if $(SNP_SHARED_MAKEFILE),$(SNP_SHARED_MAKEFILE),"~/snp/shared.mk")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TARGET     := bin/tic-tac-toe
 | 
					 | 
				
			||||||
MODULES    := src/model.c src/view.c src/control.c
 | 
					 | 
				
			||||||
SOURCES    := src/main.c $(MODULES)
 | 
					 | 
				
			||||||
TSTSOURCES := tests/tests.c $(MODULES)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
include $(SNP_SHARED_MAKEFILE)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,8 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @mainpage SNP - P05 Tic Tac Toe Game
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @section Purpose
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This is a lab on usage of arrays.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,154 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief  Implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "control.h"
 | 
					 | 
				
			||||||
#include "model.h"
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief            Conversion from control field number (1...9) to 0-based model position (row, col).
 | 
					 | 
				
			||||||
 * @param cell [IN]  Field number (1...9).
 | 
					 | 
				
			||||||
 * @return           Returns the position of the field.
 | 
					 | 
				
			||||||
 * @remark           Asserts proper field range.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static model_pos_t get_pos(size_t cell)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(1 <= cell && cell <= 9);
 | 
					 | 
				
			||||||
    model_pos_t pos = { (cell - 1) / 3, (cell - 1) % 3 };
 | 
					 | 
				
			||||||
    return pos;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief              Conversion from control player to model state.
 | 
					 | 
				
			||||||
 * @param player [IN]  Control player value to convert.
 | 
					 | 
				
			||||||
 * @return             Returns the matching model state.
 | 
					 | 
				
			||||||
 * @remark             No assertion is done - defaults to model_state_none.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static model_state_t get_state(control_player_t player)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    switch(player) {
 | 
					 | 
				
			||||||
    case control_player_a: return model_state_a;
 | 
					 | 
				
			||||||
    case control_player_b: return model_state_b;
 | 
					 | 
				
			||||||
    default:               return model_state_none;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief           Conversion from 0-based model position (row, col) to control field number (1...9).
 | 
					 | 
				
			||||||
 * @param  pos [IN] 0-based model position (row,col).
 | 
					 | 
				
			||||||
 * @return          The control filed number (1...9)
 | 
					 | 
				
			||||||
 * @remark          Asserts proper position range.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static size_t get_cell(model_pos_t pos)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(pos.row < 3);
 | 
					 | 
				
			||||||
    assert(pos.col < 3);
 | 
					 | 
				
			||||||
    return 1 + pos.row * 3 + pos.col;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief              Conversion from model state to control player.
 | 
					 | 
				
			||||||
 * @param  state [IN]  Model state to convert
 | 
					 | 
				
			||||||
 * @return             Returns the matching control player value.
 | 
					 | 
				
			||||||
 * @remark             No assertion is done - defaults to control_no_player.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static control_player_t get_player(model_state_t state)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    switch(state) {
 | 
					 | 
				
			||||||
    case model_state_a: return control_player_a;  
 | 
					 | 
				
			||||||
    case model_state_b: return control_player_b;
 | 
					 | 
				
			||||||
    default:            return control_no_player;
 | 
					 | 
				
			||||||
    }   
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                   Queries if a move is possible.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT] The instance which holds the state.
 | 
					 | 
				
			||||||
 * @return                  Returns 0 if no move is possible any more, otherwise 1.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int control_can_move(control_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    return model_can_move(instance->model);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
void control_init(control_t *instance, model_t *model)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    assert(model);
 | 
					 | 
				
			||||||
    instance->player = control_player_a;
 | 
					 | 
				
			||||||
    instance->model = model;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
void control_move(control_t *instance, size_t cell)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    if (model_move(instance->model, get_pos(cell), get_state(instance->player))) {
 | 
					 | 
				
			||||||
        if (control_can_move(instance)) {
 | 
					 | 
				
			||||||
            switch(instance->player) {
 | 
					 | 
				
			||||||
            case control_player_a:
 | 
					 | 
				
			||||||
                instance->player = control_player_b;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case control_player_b:
 | 
					 | 
				
			||||||
                instance->player = control_player_a;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            instance->player = control_no_player;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
control_player_t control_get_winner(control_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    return get_player(model_get_winner(instance->model));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
control_player_t control_get_player(control_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    return instance->player;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
control_player_t control_get_state(control_t *instance, size_t cell)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    return get_player(model_get_state(instance->model, get_pos(cell)));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
control_line_t control_get_win(control_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    if (control_get_winner(instance) == control_no_player) {
 | 
					 | 
				
			||||||
        control_line_t no_win = { 0 };
 | 
					 | 
				
			||||||
        return no_win;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    model_line_t line = model_get_win_line(instance->model);
 | 
					 | 
				
			||||||
    assert(line.dir != model_dir_none);
 | 
					 | 
				
			||||||
    size_t start_cell = get_cell(line.start);
 | 
					 | 
				
			||||||
    switch(line.dir) {
 | 
					 | 
				
			||||||
    case model_dir_h:
 | 
					 | 
				
			||||||
        return (control_line_t) { { start_cell, start_cell + 1, start_cell + 2 } };
 | 
					 | 
				
			||||||
    case model_dir_v:
 | 
					 | 
				
			||||||
        return (control_line_t) { { start_cell, start_cell + 3, start_cell + 6 } };
 | 
					 | 
				
			||||||
    case model_dir_d:
 | 
					 | 
				
			||||||
        if (start_cell == 1) {
 | 
					 | 
				
			||||||
            return (control_line_t) { { start_cell, start_cell + 4, start_cell + 8 } };
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return (control_line_t) { { start_cell, start_cell + 2, start_cell + 6 } };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        return (control_line_t) { { 1, 1, 1 } };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,80 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief  MVC - agent between model and view
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#ifndef _CONTROL_H_
 | 
					 | 
				
			||||||
#define _CONTROL_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "model.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  The selection of possible players.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    control_no_player, ///< none of the players
 | 
					 | 
				
			||||||
    control_player_a,  ///< first player
 | 
					 | 
				
			||||||
    control_player_b,  ///< second player
 | 
					 | 
				
			||||||
} control_player_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  Sequence of winning cell numbers in increasing cell numbers.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    size_t line[3]; ///< the sequence of cells (1...9) or 0 in the first element if no win
 | 
					 | 
				
			||||||
} control_line_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  The instance type.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    control_player_t player; ///< the current player
 | 
					 | 
				
			||||||
    model_t *model;          ///< the reference to the model
 | 
					 | 
				
			||||||
} control_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Constructor: initialize the instance memory.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @param  model    [IN]     Dependency Injection of the model instance.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void control_init(control_t *instance, model_t *model);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Performs a move on the board.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @param  cell    [IN]      The affected field (1...9)
 | 
					 | 
				
			||||||
 * @remark                   Silently ignores a move if it is not allowed (e.g. if already completed or the field is already played, etc.).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void control_move(control_t *instance, size_t cell);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Queries the winning player.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @returns                  Returns the winning player (if any).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
control_player_t control_get_winner(control_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Queries the next player.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @returns                  Returns the next player (if any).
 | 
					 | 
				
			||||||
 * @remark                   This is updated by the control_move() function.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
control_player_t control_get_player(control_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Queries the state of a field.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @param  cell [IN]         The affected field of the board (1...9).
 | 
					 | 
				
			||||||
 * @returns                  Returns the player which played this field (if any).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
control_player_t control_get_state(control_t *instance, size_t cell);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Gets the winning fields (if any).
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @returns                  Returns the field numbers in increasing order (1...9) which win the game (if any).
 | 
					 | 
				
			||||||
 * @remark                   If there is no winner (yet), the first entry in the result is 0.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
control_line_t control_get_win(control_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // _CONTROL_H_
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,39 +0,0 @@
 | 
				
			||||||
 /* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab P04 dep2dot
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "view.h"
 | 
					 | 
				
			||||||
#include "model.h"
 | 
					 | 
				
			||||||
#include "control.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief   main function
 | 
					 | 
				
			||||||
 * @param   argc [in] number of entries in argv
 | 
					 | 
				
			||||||
 * @param   argv [in] program name plus command line arguments
 | 
					 | 
				
			||||||
 * @returns returns success if valid date is given, failure otherwise
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(int argc, const char *argv[])
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    view_t view;
 | 
					 | 
				
			||||||
    control_t control;
 | 
					 | 
				
			||||||
    model_t model;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    model_init(&model);
 | 
					 | 
				
			||||||
    control_init(&control, &model);
 | 
					 | 
				
			||||||
    view_init(&view, &control);
 | 
					 | 
				
			||||||
    view_run(&view);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return EXIT_SUCCESS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,154 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief  Implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "model.h"
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief       Asserts that the position is in range.
 | 
					 | 
				
			||||||
 * @param [IN]  The position to check.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void assert_pos(model_pos_t pos)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(pos.row < MODEL_SIZE);
 | 
					 | 
				
			||||||
    assert(pos.col < MODEL_SIZE);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Sets the field on the board to the given state.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @param  pos      [IN]     The affected field.
 | 
					 | 
				
			||||||
 * @param  state    [IN]     The new state of the field.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void set_state(model_t *instance, model_pos_t pos, model_state_t state)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert_pos(pos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Instructions to the students:
 | 
					 | 
				
			||||||
    // set the field of the board to the new state
 | 
					 | 
				
			||||||
    // BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
    instance->board[pos.row][pos.col] = state;
 | 
					 | 
				
			||||||
    // END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
model_pos_t model_pos(size_t row, size_t col)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return (model_pos_t){row, col};
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
void model_init(model_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Instructions to the students:
 | 
					 | 
				
			||||||
    // set all fields of the board to model_state_none
 | 
					 | 
				
			||||||
    // BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
    for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
        for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
            instance->board[row][col] = model_state_none;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
model_state_t model_get_state(model_t *instance, model_pos_t pos)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    assert_pos(pos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Instructions to the students:
 | 
					 | 
				
			||||||
    // replace the stub implementation my access to the field at the given position.
 | 
					 | 
				
			||||||
    // BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
    return instance->board[pos.row][pos.col]; // stub return model_state_none;
 | 
					 | 
				
			||||||
    // END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
model_line_t model_get_win_line(model_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    model_state_t anchor;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // horizontal
 | 
					 | 
				
			||||||
    for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
        anchor = model_get_state(instance, model_pos(row, 0));
 | 
					 | 
				
			||||||
        if (anchor != model_state_none
 | 
					 | 
				
			||||||
            && anchor == model_get_state(instance, model_pos(row, 1))
 | 
					 | 
				
			||||||
            && anchor == model_get_state(instance, model_pos(row, 2))) {
 | 
					 | 
				
			||||||
            return (model_line_t) { model_dir_h, { row, 0 } };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // vertical
 | 
					 | 
				
			||||||
    for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
        anchor = model_get_state(instance, model_pos(0, col));
 | 
					 | 
				
			||||||
        if (anchor != model_state_none
 | 
					 | 
				
			||||||
            && anchor == model_get_state(instance, model_pos(1, col))
 | 
					 | 
				
			||||||
            && anchor == model_get_state(instance, model_pos(2, col))) {
 | 
					 | 
				
			||||||
            return (model_line_t) { model_dir_v, { 0, col } };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // diagonal
 | 
					 | 
				
			||||||
    anchor = model_get_state(instance, model_pos(1, 1));
 | 
					 | 
				
			||||||
    if (anchor != model_state_none) {
 | 
					 | 
				
			||||||
        if (anchor == model_get_state(instance, model_pos(0, 0)) && anchor == model_get_state(instance, model_pos(2, 2))) {
 | 
					 | 
				
			||||||
            return (model_line_t) { model_dir_d, { 0, 0 } };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (anchor == model_get_state(instance, model_pos(2, 0)) && anchor == model_get_state(instance, model_pos(0, 2))) {
 | 
					 | 
				
			||||||
            return (model_line_t) { model_dir_d, { 0, 2 } };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // fallback
 | 
					 | 
				
			||||||
    return (model_line_t) { model_dir_none, { 0, 0 } }; 
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
model_state_t model_get_winner(model_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    model_line_t line = model_get_win_line(instance);
 | 
					 | 
				
			||||||
    return line.dir == model_dir_none
 | 
					 | 
				
			||||||
        ? model_state_none
 | 
					 | 
				
			||||||
        : model_get_state(instance, model_pos(line.start.row, line.start.col))
 | 
					 | 
				
			||||||
        ;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
int model_can_move(model_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    if (model_get_winner(instance) == model_state_none) {
 | 
					 | 
				
			||||||
        // Instructions to the students:
 | 
					 | 
				
			||||||
        // scan all fields: return 1 with first field which equals model_state_none
 | 
					 | 
				
			||||||
        // BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
        for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
            for (size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
                if (instance->board[row][col] == model_state_none) {
 | 
					 | 
				
			||||||
                    return 1;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
int model_move(model_t *instance, model_pos_t pos, model_state_t state)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    assert_pos(pos);
 | 
					 | 
				
			||||||
    if (model_get_state(instance, pos) == model_state_none && model_can_move(instance)) {
 | 
					 | 
				
			||||||
        set_state(instance, pos, state);
 | 
					 | 
				
			||||||
        return 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,108 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief MVC - Model instance
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#ifndef _MODEL_H_
 | 
					 | 
				
			||||||
#define _MODEL_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MODEL_SIZE  3  ///< size of the game to avoid magic numbers in the code (not meant to modify)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief The position on the board.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    size_t row;   ///< The row (0-based).
 | 
					 | 
				
			||||||
    size_t col;   ///< The column (0-based).
 | 
					 | 
				
			||||||
} model_pos_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  Winner line direction - the winner line is given together with the start position.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    model_dir_none,  ///< no winner line
 | 
					 | 
				
			||||||
    model_dir_h,     ///< horizontal
 | 
					 | 
				
			||||||
    model_dir_v,     ///< vertical
 | 
					 | 
				
			||||||
    model_dir_d,     ///< diagonal
 | 
					 | 
				
			||||||
} model_dir_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  The Winner line (if any).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    model_dir_t dir;     ///< the winner line direction (if any)
 | 
					 | 
				
			||||||
    model_pos_t start;   ///< the start position of the winner line
 | 
					 | 
				
			||||||
} model_line_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  The state of a field.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    model_state_none,   ///< field available to play
 | 
					 | 
				
			||||||
    model_state_a,      ///< field already played
 | 
					 | 
				
			||||||
    model_state_b,      ///< field already played
 | 
					 | 
				
			||||||
} model_state_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  The instance type.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    model_state_t board[MODEL_SIZE][MODEL_SIZE];   ///< the play board
 | 
					 | 
				
			||||||
} model_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief           Convert to row and col to position.
 | 
					 | 
				
			||||||
 * @param row [IN]  position parameter
 | 
					 | 
				
			||||||
 * @param col [IN]  position parameter
 | 
					 | 
				
			||||||
 * @return          Returns the position given be row and col parameters.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
model_pos_t model_pos(size_t row, size_t col);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Constructor: initialize the instance memory.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void model_init(model_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Queries the state of the given field.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @param  pos      [IN]     The affected field.
 | 
					 | 
				
			||||||
 * @return                   Returns the state of the field.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
model_state_t model_get_state(model_t *instance, model_pos_t pos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Queries the winner (if any).
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @return                   Returns the wining player or model_state_none if no winner (yet).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
model_state_t model_get_winner(model_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Queries if a move is possible (i.e. not won yet and any field available?).
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @return                   Returns 0 if no move possible, 1 otherwise.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int model_can_move(model_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Do a move if possible.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @param  pos [IN]          The field to play.
 | 
					 | 
				
			||||||
 * @param  state [IN]        The new state (only model_state_a and model_state_b allowed).
 | 
					 | 
				
			||||||
 * @return                   Returns if the attempt to move was successful.
 | 
					 | 
				
			||||||
 * @remark                   Does only succeed if not yet won and if the field is available.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int model_move(model_t *instance, model_pos_t pos, model_state_t state);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Gets the winner line (if any).
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @returns                  The line which wins (if any).
 | 
					 | 
				
			||||||
 * @remark                   The start position is 0/0, 1/0, 2/0 for horizontal, 0/0, 0/1, 0/2 for vertical, 0/0, 0/2 for diagonal.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
model_line_t model_get_win_line(model_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // _MODEL_H_
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,255 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief  Implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "view.h"
 | 
					 | 
				
			||||||
#include "control.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <assert.h>   // assert()
 | 
					 | 
				
			||||||
#include <stdio.h>    // various i/o
 | 
					 | 
				
			||||||
#include <ctype.h>    // isdigit()
 | 
					 | 
				
			||||||
#include <unistd.h>   // STDIN_FILENO, isatty()
 | 
					 | 
				
			||||||
#include <termios.h>  // tcgetattr(), tcsetattr()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define EXIT '0'               ///< the UI exit request
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CLS        "\033[2J"   ///< ANSI termial CSI sequence for clear screen
 | 
					 | 
				
			||||||
#define AVAILABLE  "\033[40m"  ///< ANSI termial CSI sequence for available fields (black)
 | 
					 | 
				
			||||||
#define PLAYER_A   "\033[42m"  ///< ANSI termial CSI sequence for one player (green)
 | 
					 | 
				
			||||||
#define PLAYER_B   "\033[41m"  ///< ANSI termial CSI sequence for the other player (red)
 | 
					 | 
				
			||||||
#define GAP        "\033[47m"  ///< ANSI termial CSI sequence for boarder (white)
 | 
					 | 
				
			||||||
#define RESET      "\033[0m"   ///< ANSI termial CSI sequence to reset all settings
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CELL_WIDTH  10         ///< rendering parameter: columns per cell
 | 
					 | 
				
			||||||
#define CELL_HEIGHT 5          ///< rendering parameter: rows per cell
 | 
					 | 
				
			||||||
#define GAP_WIDTH   4          ///< rendering parameter: columns per border
 | 
					 | 
				
			||||||
#define GAP_HEIGHT  2          ///< rendering parameter: rows per boarder
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define SIZE        3              ///< size of the game to avoid magic numbers in the code (not meant to modify)
 | 
					 | 
				
			||||||
#define CELLS       (SIZE * SIZE)  ///< size of the game to avoid magic numbers in the code (not meant to modify)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief            Position the cursor for further output.
 | 
					 | 
				
			||||||
 * @param  row [IN]  position parameter
 | 
					 | 
				
			||||||
 * @param  col [IN]  position parameter
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void goto_pos(size_t row, size_t col)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    printf("\033[%zd;%zdH", row, col);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief              Displays a sequence of spaces at the given position in the given background color.
 | 
					 | 
				
			||||||
 * @param  row [IN]    position parameter
 | 
					 | 
				
			||||||
 * @param  col [IN]    position parameter
 | 
					 | 
				
			||||||
 * @param  width [IN]  how many spaces to write
 | 
					 | 
				
			||||||
 * @param  color [IN]  the format string before writing the spaces (intent: background color)
 | 
					 | 
				
			||||||
 * @remark             After writing the spaces, the format is reset.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static size_t show_bar(size_t row, size_t col, size_t width, const char* color)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    goto_pos(row, col);
 | 
					 | 
				
			||||||
    printf("%s", color);
 | 
					 | 
				
			||||||
    for(size_t col = 0; col < width; col++) {
 | 
					 | 
				
			||||||
        putchar(' ');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    printf(RESET);
 | 
					 | 
				
			||||||
    return col + width;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief              Displays a horizontal border over the whole board width.
 | 
					 | 
				
			||||||
 * @param  row [IN]    position parameter
 | 
					 | 
				
			||||||
 * @param  col [IN]    position parameter
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static size_t show_h_gap(size_t row, size_t col) {
 | 
					 | 
				
			||||||
    for(size_t i = 0; i < GAP_HEIGHT; i++) {
 | 
					 | 
				
			||||||
        show_bar(row+i, col, GAP_WIDTH + CELL_WIDTH + GAP_WIDTH, GAP);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return row + GAP_HEIGHT;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief              Writes for the call at position y/x the given number with the given background color.
 | 
					 | 
				
			||||||
 * @param  y [IN]      position parameter: the upper left row of the cell
 | 
					 | 
				
			||||||
 * @param  x [IN]      position parameter: the upper left column of the cell
 | 
					 | 
				
			||||||
 * @param  n [IN]      the number to write as text
 | 
					 | 
				
			||||||
 * @param  color [IN]  the format string before writing the text (intent: background color)
 | 
					 | 
				
			||||||
 * @remark             After writing the number, the format is reset.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void show_cell_nr(size_t y, size_t x, size_t n, const char *color)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    size_t cy = (y + y + CELL_HEIGHT)/2;
 | 
					 | 
				
			||||||
    size_t cx = (x + x + CELL_WIDTH - 2)/2;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    goto_pos(cy, cx);
 | 
					 | 
				
			||||||
    printf("%s", color);
 | 
					 | 
				
			||||||
    printf("%2zd", n);
 | 
					 | 
				
			||||||
    printf(RESET);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief              Renders the given cell with the given background color, including the surrounding border.
 | 
					 | 
				
			||||||
 * @param  n [IN]      the cell number (0...CELLS-1)
 | 
					 | 
				
			||||||
 * @param  color [IN]  the format string for the cell content (intent: background color)
 | 
					 | 
				
			||||||
 * @remark             After writing the number, the format is reset.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void show_cell(size_t n, const char *color)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // goto upper-left corner of a cell (the cell starts with an upper and left gap)
 | 
					 | 
				
			||||||
    size_t y = 1 + n / SIZE * (GAP_HEIGHT + CELL_HEIGHT);
 | 
					 | 
				
			||||||
    size_t x = 1 + n % SIZE * (GAP_WIDTH  + CELL_WIDTH);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    size_t row = show_h_gap(y, x);
 | 
					 | 
				
			||||||
    for(size_t i = 0; i < CELL_HEIGHT; i++) {
 | 
					 | 
				
			||||||
        size_t col = x;
 | 
					 | 
				
			||||||
        col = show_bar(row, col, GAP_WIDTH, GAP);
 | 
					 | 
				
			||||||
        col = show_bar(row, col, CELL_WIDTH, color);
 | 
					 | 
				
			||||||
        col = show_bar(row, col, GAP_WIDTH, GAP);
 | 
					 | 
				
			||||||
        row++;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    row = show_h_gap(row, x);
 | 
					 | 
				
			||||||
    show_cell_nr(y + GAP_HEIGHT, x + GAP_WIDTH, n + 1, color);
 | 
					 | 
				
			||||||
    goto_pos(row, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief               Renders the given player's name in the given background color.
 | 
					 | 
				
			||||||
 * @param  player [IN]  the player to render (select the background color and the name of the player
 | 
					 | 
				
			||||||
 * @remark              After writing the content, the format is reset.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void print_player(control_player_t player)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    switch(player) {
 | 
					 | 
				
			||||||
    case control_player_a:
 | 
					 | 
				
			||||||
        printf(PLAYER_A);
 | 
					 | 
				
			||||||
        printf("Player A");
 | 
					 | 
				
			||||||
        printf(RESET);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case control_player_b:
 | 
					 | 
				
			||||||
        printf(PLAYER_B);
 | 
					 | 
				
			||||||
        printf("Player B");
 | 
					 | 
				
			||||||
        printf(RESET);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        printf(RESET);
 | 
					 | 
				
			||||||
        printf("none");
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief               Displays a label followed by the given player.
 | 
					 | 
				
			||||||
 * @param  row [IN]     position parameter
 | 
					 | 
				
			||||||
 * @param  col [IN]     position parameter
 | 
					 | 
				
			||||||
 * @param  label [IN]   the profixing label
 | 
					 | 
				
			||||||
 * @param  player [IN]  the player to display
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void show_player(size_t row, size_t col, const char *label, control_player_t player)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    goto_pos(row, col);
 | 
					 | 
				
			||||||
    printf(RESET);
 | 
					 | 
				
			||||||
    col += printf("%s", label);
 | 
					 | 
				
			||||||
    goto_pos(row, col);
 | 
					 | 
				
			||||||
    print_player(player);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief              Renders the winner and the next player.
 | 
					 | 
				
			||||||
 * @param winner [IN]  the winning player (if any)
 | 
					 | 
				
			||||||
 * @param next [IN]    the next player (if any)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void show_status(control_player_t winner, control_player_t next)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    size_t y = GAP_HEIGHT;
 | 
					 | 
				
			||||||
    size_t x = SIZE * (GAP_WIDTH + CELL_WIDTH) + GAP_WIDTH + GAP_WIDTH;
 | 
					 | 
				
			||||||
    size_t row = y;
 | 
					 | 
				
			||||||
    size_t col = x;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    show_player(row, col, "Winner is:      ", winner);
 | 
					 | 
				
			||||||
    row += 2;
 | 
					 | 
				
			||||||
    show_player(row, col, "Next player is: ", next);
 | 
					 | 
				
			||||||
    row += 2;
 | 
					 | 
				
			||||||
    row += 2;
 | 
					 | 
				
			||||||
    goto_pos(row, col);
 | 
					 | 
				
			||||||
    printf("0:    exit");
 | 
					 | 
				
			||||||
    row += 2;
 | 
					 | 
				
			||||||
    goto_pos(row, col);
 | 
					 | 
				
			||||||
    printf("1..9: play field");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                 Renders the board from the status given by the control instance.
 | 
					 | 
				
			||||||
 * @param  instance [IN]  the instance which holds the control instance
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void show(view_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    assert(instance->control);
 | 
					 | 
				
			||||||
    puts(CLS);
 | 
					 | 
				
			||||||
    show_status(control_get_winner(instance->control), control_get_player(instance->control));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for(size_t i = 0; i < CELLS; i++) {
 | 
					 | 
				
			||||||
        const char *color = AVAILABLE;
 | 
					 | 
				
			||||||
        switch(control_get_state(instance->control, i+1)) {
 | 
					 | 
				
			||||||
        case control_player_a:
 | 
					 | 
				
			||||||
            color = PLAYER_A;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case control_player_b:
 | 
					 | 
				
			||||||
            color = PLAYER_B;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        show_cell(i, color);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  Processes the input and dsiplays the result.
 | 
					 | 
				
			||||||
 * @param  the instance which holds the control instance
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void notifier_loop(view_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    show(instance);
 | 
					 | 
				
			||||||
    int c = getchar();
 | 
					 | 
				
			||||||
    while(c != EOF && c != EXIT) {
 | 
					 | 
				
			||||||
        if (isdigit(c)) {
 | 
					 | 
				
			||||||
            control_move(instance->control, c-'0');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        show(instance);
 | 
					 | 
				
			||||||
        c = getchar();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
void view_init(view_t *instance, control_t *control)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(instance);
 | 
					 | 
				
			||||||
    assert(control);
 | 
					 | 
				
			||||||
    instance->control = control;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// public API function which is documented in the header file.
 | 
					 | 
				
			||||||
void view_run(view_t *instance)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (isatty(STDIN_FILENO)) { // in case of an interactive terminal, the exhoing and buffering is disabled
 | 
					 | 
				
			||||||
        // declare non POSIX function, which is available in glibc, but not in strinct C99 mode
 | 
					 | 
				
			||||||
        void cfmakeraw(struct termios *termios_p);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // replace original tty IO state...
 | 
					 | 
				
			||||||
        struct termios orig;
 | 
					 | 
				
			||||||
        struct termios raw;
 | 
					 | 
				
			||||||
        cfmakeraw(&raw);
 | 
					 | 
				
			||||||
        tcgetattr(STDIN_FILENO, &orig);
 | 
					 | 
				
			||||||
        tcsetattr(STDIN_FILENO, TCSANOW, &raw);
 | 
					 | 
				
			||||||
        // ...do the work...
 | 
					 | 
				
			||||||
        notifier_loop(instance);
 | 
					 | 
				
			||||||
        // ...and finalle restore original tty IO state
 | 
					 | 
				
			||||||
        tcsetattr(STDIN_FILENO, TCSANOW, &orig);
 | 
					 | 
				
			||||||
    } else { // if not an interactive terminal, no tweaking with IO is done
 | 
					 | 
				
			||||||
        notifier_loop(instance);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,31 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief MVC - View instance
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#ifndef _VIEW_H_
 | 
					 | 
				
			||||||
#define _VIEW_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "control.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief  The instance type.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    control_t *control; ///< the instance knows of the control instance
 | 
					 | 
				
			||||||
} view_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Constructor: initialize the instance memory.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @param  control  [IN]     Dependency Injection of the control instance.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void view_init(view_t *instance, control_t *control);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief                    Starts the notifyer loop: accepts input and displays the results.
 | 
					 | 
				
			||||||
 * @param  instance [INOUT]  The instance which holds the state.
 | 
					 | 
				
			||||||
 * @remark                   Does only return when termination is requested through the UI.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void view_run(view_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // _VIEW_H_
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,445 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Test suite for the given package.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <sys/wait.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#include <CUnit/Basic.h>
 | 
					 | 
				
			||||||
#include "test_utils.h"
 | 
					 | 
				
			||||||
#include "model.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef TARGET // must be given by the make file --> see test target
 | 
					 | 
				
			||||||
#error missing TARGET define
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief alias for EXIT_SUCCESS
 | 
					 | 
				
			||||||
#define OK   EXIT_SUCCESS
 | 
					 | 
				
			||||||
/// @brief alias for EXIT_FAILURE
 | 
					 | 
				
			||||||
#define FAIL EXIT_FAILURE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief The name of the STDOUT text file.
 | 
					 | 
				
			||||||
#define OUTFILE "stdout.txt"
 | 
					 | 
				
			||||||
/// @brief The name of the STDERR text file.
 | 
					 | 
				
			||||||
#define ERRFILE "stderr.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define TRACE_INDENT "\n                " ///< allow for better stdout formatting in case of error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// setup & cleanup
 | 
					 | 
				
			||||||
static int setup(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    remove_file_if_exists(OUTFILE);
 | 
					 | 
				
			||||||
    remove_file_if_exists(ERRFILE);
 | 
					 | 
				
			||||||
    return 0; // success
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int teardown(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // Do nothing.
 | 
					 | 
				
			||||||
    // Especially: do not remove result files - they are removed in int setup(void) *before* running a test.
 | 
					 | 
				
			||||||
    return 0; // success
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// test utils
 | 
					 | 
				
			||||||
static void init_model(model_t *instance, int act)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (act) printf(TRACE_INDENT "init_model:... ");
 | 
					 | 
				
			||||||
    model_init(instance);
 | 
					 | 
				
			||||||
    for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
        for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
            if (act) printf("%zd/%zd ", row, col);
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(instance->board[row][col], model_state_none);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (act) printf(TRACE_INDENT);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void print_board(model_state_t board[MODEL_SIZE][MODEL_SIZE])
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
        printf("{ ");
 | 
					 | 
				
			||||||
        for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
            printf("%d ", board[row][col]);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        printf("} ");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// tests
 | 
					 | 
				
			||||||
static void test_model_init(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // check void model_init(model_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // arrange
 | 
					 | 
				
			||||||
    model_t model;
 | 
					 | 
				
			||||||
    // act & assert
 | 
					 | 
				
			||||||
    init_model(&model, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_model_get_state(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // check: model_state_t model_get_state(model_t *instance, model_pos_t pos);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "initial state:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
            for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
                printf("%zd/%zd ", row, col);
 | 
					 | 
				
			||||||
                CU_ASSERT_EQUAL_FATAL(model_get_state(&model, model_pos(row, col)), model_state_none);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_none, model_state_a,    model_state_b    },
 | 
					 | 
				
			||||||
            { model_state_a,    model_state_b,    model_state_none },
 | 
					 | 
				
			||||||
            { model_state_b,    model_state_none, model_state_a    },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "modified state:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
            for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
                printf("%zd/%zd ", row, col);
 | 
					 | 
				
			||||||
                CU_ASSERT_EQUAL_FATAL(model_get_state(&model, model_pos(row, col)), board[row][col]);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    printf(TRACE_INDENT);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_model_get_winner(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // check: model_state_t model_get_winner(model_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "initial no winner:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_get_winner(&model), model_state_none);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_none, model_state_a,    model_state_b    },
 | 
					 | 
				
			||||||
            { model_state_a,    model_state_b,    model_state_none },
 | 
					 | 
				
			||||||
            { model_state_b,    model_state_none, model_state_a    },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "winner:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_get_winner(&model), model_state_b);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    printf(TRACE_INDENT);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_model_can_move(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // check: int model_can_move(model_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "initial can move:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_none, model_state_a,    model_state_a    },
 | 
					 | 
				
			||||||
            { model_state_a,    model_state_b,    model_state_none },
 | 
					 | 
				
			||||||
            { model_state_b,    model_state_none, model_state_b    },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "can move while not yet done nor win:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_none, model_state_a,    model_state_b    },
 | 
					 | 
				
			||||||
            { model_state_a,    model_state_b,    model_state_none },
 | 
					 | 
				
			||||||
            { model_state_b,    model_state_none, model_state_a    },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "cannot move after win:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_b, model_state_a, model_state_a },
 | 
					 | 
				
			||||||
            { model_state_a, model_state_b, model_state_b },
 | 
					 | 
				
			||||||
            { model_state_b, model_state_a, model_state_a },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "cannot move when all done:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    printf(TRACE_INDENT);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_model_move(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // check: int model_move(model_t *instance, model_pos_t pos, model_state_t state);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "initial move:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        model_pos_t pos_a = model_pos(0, 0);
 | 
					 | 
				
			||||||
        printf("%zd/%zd ", pos_a.row, pos_a.col);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_a, model_state_a), 1);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_a, model_state_a), 0);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_a, model_state_b), 0);
 | 
					 | 
				
			||||||
        model_pos_t pos_b = model_pos(2, 2);
 | 
					 | 
				
			||||||
        printf("%zd/%zd ", pos_b.row, pos_b.col);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_b, model_state_b), 1);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_b, model_state_b), 0);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_b, model_state_a), 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_none, model_state_a,    model_state_a    },
 | 
					 | 
				
			||||||
            { model_state_a,    model_state_b,    model_state_none },
 | 
					 | 
				
			||||||
            { model_state_b,    model_state_none, model_state_b    },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "can move while not yet done nor win:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        model_pos_t pos = model_pos(2, 1);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_a), 1);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_a), 0);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_b), 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_none, model_state_a,    model_state_b    },
 | 
					 | 
				
			||||||
            { model_state_a,    model_state_b,    model_state_none },
 | 
					 | 
				
			||||||
            { model_state_b,    model_state_none, model_state_a    },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "cannot move after win:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        model_pos_t pos = model_pos(2, 1);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_a), 0);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_b), 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_b, model_state_a, model_state_a },
 | 
					 | 
				
			||||||
            { model_state_a, model_state_b, model_state_b },
 | 
					 | 
				
			||||||
            { model_state_b, model_state_a, model_state_a },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "cannot move when all done:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
            for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
                model_pos_t pos = model_pos(row, col);
 | 
					 | 
				
			||||||
                printf("%zd/%zd ", row, col);
 | 
					 | 
				
			||||||
                CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_a), 0);
 | 
					 | 
				
			||||||
                CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_b), 0);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    printf(TRACE_INDENT);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_model_get_win_line(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // check: model_line_t model_get_win_line(model_t *instance);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "initial no winner:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        model_line_t no_win = model_get_win_line(&model);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(no_win.dir, model_dir_none);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_none, model_state_a,    model_state_a    },
 | 
					 | 
				
			||||||
            { model_state_a,    model_state_b,    model_state_none },
 | 
					 | 
				
			||||||
            { model_state_b,    model_state_none, model_state_b    },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "no winner while not yet done nor win:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        model_line_t no_win = model_get_win_line(&model);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(no_win.dir, model_dir_none);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = {
 | 
					 | 
				
			||||||
            { model_state_b, model_state_a, model_state_a },
 | 
					 | 
				
			||||||
            { model_state_a, model_state_b, model_state_b },
 | 
					 | 
				
			||||||
            { model_state_b, model_state_a, model_state_a },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        memcpy(model.board, board, sizeof(board));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "no winner when all done:... ");
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        model_line_t no_win = model_get_win_line(&model);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(no_win.dir, model_dir_none);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
            // arrange
 | 
					 | 
				
			||||||
            model_t model;
 | 
					 | 
				
			||||||
            init_model(&model, 0);
 | 
					 | 
				
			||||||
            for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
                CU_ASSERT_EQUAL_FATAL(model_move(&model, model_pos(row, col), model_state_a), 1);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // act & assert
 | 
					 | 
				
			||||||
            printf(TRACE_INDENT "row winner:... ");
 | 
					 | 
				
			||||||
            print_board(model.board);
 | 
					 | 
				
			||||||
            model_line_t win = model_get_win_line(&model);
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(win.dir, model_dir_h);
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(win.start.row, row);
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(win.start.col, 0);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        for(size_t col = 0; col < MODEL_SIZE; col++) {
 | 
					 | 
				
			||||||
            // arrange
 | 
					 | 
				
			||||||
            model_t model;
 | 
					 | 
				
			||||||
            init_model(&model, 0);
 | 
					 | 
				
			||||||
            for(size_t row = 0; row < MODEL_SIZE; row++) {
 | 
					 | 
				
			||||||
                CU_ASSERT_EQUAL_FATAL(model_move(&model, model_pos(row, col), model_state_a), 1);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // act & assert
 | 
					 | 
				
			||||||
            printf(TRACE_INDENT "column winner:... ");
 | 
					 | 
				
			||||||
            print_board(model.board);
 | 
					 | 
				
			||||||
            model_line_t win = model_get_win_line(&model);
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(win.dir, model_dir_v);
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(win.start.row, 0);
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(win.start.col, col);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "diagonal left-right winner:... ");
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        for(size_t i = 0; i < MODEL_SIZE; i++) {
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(model_move(&model, model_pos(i, i), model_state_a), 1);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        model_line_t win = model_get_win_line(&model);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(win.dir, model_dir_d);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(win.start.row, 0);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(win.start.col, 0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        printf(TRACE_INDENT "diagonal right-left winner:... ");
 | 
					 | 
				
			||||||
        // arrange
 | 
					 | 
				
			||||||
        model_t model;
 | 
					 | 
				
			||||||
        init_model(&model, 0);
 | 
					 | 
				
			||||||
        for(size_t i = 0; i < MODEL_SIZE; i++) {
 | 
					 | 
				
			||||||
            CU_ASSERT_EQUAL_FATAL(model_move(&model, model_pos(MODEL_SIZE - 1 - i, i), model_state_a), 1);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // act & assert
 | 
					 | 
				
			||||||
        print_board(model.board);
 | 
					 | 
				
			||||||
        model_line_t win = model_get_win_line(&model);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(win.dir, model_dir_d);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(win.start.row, 0);
 | 
					 | 
				
			||||||
        CU_ASSERT_EQUAL_FATAL(win.start.col, MODEL_SIZE - 1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    printf(TRACE_INDENT);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Registers and runs the tests.
 | 
					 | 
				
			||||||
 * @returns success (0) or one of the CU_ErrorCode (>0)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // setup, run, teardown
 | 
					 | 
				
			||||||
    TestMainBasic("lab test", setup, teardown
 | 
					 | 
				
			||||||
                  , test_model_init
 | 
					 | 
				
			||||||
                  , test_model_get_state
 | 
					 | 
				
			||||||
                  , test_model_get_winner
 | 
					 | 
				
			||||||
                  , test_model_can_move
 | 
					 | 
				
			||||||
                  , test_model_move
 | 
					 | 
				
			||||||
                  , test_model_get_win_line
 | 
					 | 
				
			||||||
                  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,13 +0,0 @@
 | 
				
			||||||
SNP_SHARED_MAKEFILE := $(if $(SNP_SHARED_MAKEFILE),$(SNP_SHARED_MAKEFILE),"~/snp/shared.mk")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TARGET     := bin/personen-verwaltung
 | 
					 | 
				
			||||||
# BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
MODULES    := src/person.c src/list.c
 | 
					 | 
				
			||||||
# END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
SOURCES    := src/main.c $(MODULES)
 | 
					 | 
				
			||||||
TSTSOURCES := tests/tests.c $(MODULES)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
include $(SNP_SHARED_MAKEFILE)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# CFLAGS  += -Werror
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,8 +0,0 @@
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @mainpage SNP - P07 Linked List
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @section Purpose
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This is a lab on usage of arrays.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,103 +0,0 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#include "list.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static node_t anchor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int is_anchor(const node_t *node)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return node == &anchor;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void remove_next(node_t *at)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(at);
 | 
					 | 
				
			||||||
	assert(at->next);
 | 
					 | 
				
			||||||
	if (!is_anchor(at->next)) {
 | 
					 | 
				
			||||||
		node_t *next = at->next->next;
 | 
					 | 
				
			||||||
		free(at->next);
 | 
					 | 
				
			||||||
		at->next = next;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static node_t *find_insert(const person_t *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(p);
 | 
					 | 
				
			||||||
	node_t *last = &anchor;
 | 
					 | 
				
			||||||
	for(node_t *n = anchor.next; !is_anchor(n); last = n, n = n->next) {
 | 
					 | 
				
			||||||
		int res = person_compare(&(n->content), p);
 | 
					 | 
				
			||||||
		if (res == 0) {
 | 
					 | 
				
			||||||
			return NULL; // *** EARLY RETURN ***// // already part of the list
 | 
					 | 
				
			||||||
		} else if (res > 0) {
 | 
					 | 
				
			||||||
			break; // the predecessor is the insert point
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return last;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static node_t *find_remove(const person_t *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(p);
 | 
					 | 
				
			||||||
	node_t *last = &anchor;
 | 
					 | 
				
			||||||
	for(node_t *n = anchor.next; !is_anchor(n); last = n, n = n->next) {
 | 
					 | 
				
			||||||
		int res = person_compare(&(n->content), p);
 | 
					 | 
				
			||||||
		if (res == 0) {
 | 
					 | 
				
			||||||
			break; // the predecessor is the remove point
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return is_anchor(last->next) ? NULL : last;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const node_t *list_anchor(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return &anchor;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const node_t *list_init()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	anchor.next = &anchor;
 | 
					 | 
				
			||||||
	return &anchor;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int list_insert(const person_t *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	node_t *at = find_insert(p);
 | 
					 | 
				
			||||||
	node_t *insert = NULL;
 | 
					 | 
				
			||||||
	if (at) {
 | 
					 | 
				
			||||||
		insert = malloc(sizeof(node_t));
 | 
					 | 
				
			||||||
		if (insert) {
 | 
					 | 
				
			||||||
			insert->content = *p;
 | 
					 | 
				
			||||||
			insert->next = at->next;
 | 
					 | 
				
			||||||
			at->next = insert;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return at && insert;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int list_remove(const person_t *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	node_t *at = find_remove(p);
 | 
					 | 
				
			||||||
	if (at) {
 | 
					 | 
				
			||||||
		remove_next(at);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return at != NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void list_clear(void)	
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	node_t *n = &anchor;
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		remove_next(n);
 | 
					 | 
				
			||||||
	} while (!is_anchor(n->next));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void list_show(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	node_t *n = &anchor;
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		if (!is_anchor(n)) printf("%20s %20s %u\n", n->content.name, n->content.first_name, n->content.age);
 | 
					 | 
				
			||||||
		n = n->next;
 | 
					 | 
				
			||||||
	} while(!is_anchor(n));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,17 +0,0 @@
 | 
				
			||||||
#ifndef _LIST_H_
 | 
					 | 
				
			||||||
#define _LIST_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "person.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct node {
 | 
					 | 
				
			||||||
	person_t content; // in diesem Knoten gespeicherte Person
 | 
					 | 
				
			||||||
	struct node *next;  // Pointer auf den nächsten Knoten in der Liste
 | 
					 | 
				
			||||||
} node_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const node_t *list_init();
 | 
					 | 
				
			||||||
int list_insert(const person_t *p);
 | 
					 | 
				
			||||||
int list_remove(const person_t *p);
 | 
					 | 
				
			||||||
void list_clear(void);
 | 
					 | 
				
			||||||
void list_show(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // _LIST_H_
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,68 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Lab implementation
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "person.h"
 | 
					 | 
				
			||||||
#include "list.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Main entry point.
 | 
					 | 
				
			||||||
 * @param[in] argc  The size of the argv array.
 | 
					 | 
				
			||||||
 * @param[in] argv  The command line arguments...
 | 
					 | 
				
			||||||
 * @returns Returns EXIT_SUCCESS (=0) on success, EXIT_FAILURE (=1) there is an expression syntax error.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(int argc, char* argv[])
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
	list_init();
 | 
					 | 
				
			||||||
	person_t p;
 | 
					 | 
				
			||||||
	int show_menu = 1;
 | 
					 | 
				
			||||||
	while(1) {
 | 
					 | 
				
			||||||
		if (show_menu) printf("I(nsert), R(emove), S(how), C(lear), E(nd)\n");
 | 
					 | 
				
			||||||
		show_menu = 1;
 | 
					 | 
				
			||||||
		int op = getchar();
 | 
					 | 
				
			||||||
		switch(op) {
 | 
					 | 
				
			||||||
		case 'I': case 'i':
 | 
					 | 
				
			||||||
			if (!person_read(&p) || !list_insert(&p)) {
 | 
					 | 
				
			||||||
				printf("failed to insert person\n");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 'R': case 'r':
 | 
					 | 
				
			||||||
			if (!person_read(&p) || !list_remove(&p)) {
 | 
					 | 
				
			||||||
				printf("failed to remove person\n");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 'S': case 's':
 | 
					 | 
				
			||||||
			list_show();
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 'C': case 'c':
 | 
					 | 
				
			||||||
			list_clear();
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case EOF:
 | 
					 | 
				
			||||||
		case 'E': case 'e':
 | 
					 | 
				
			||||||
			return EXIT_SUCCESS; // *** EARLY RETURN *** //
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case ' ': case '\n':
 | 
					 | 
				
			||||||
			show_menu = 0;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			printf("Unknown command: %c\n", op);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
    return EXIT_SUCCESS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,22 +0,0 @@
 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "person.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int person_compare(const person_t *a, const person_t *b)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(a);
 | 
					 | 
				
			||||||
	assert(b);
 | 
					 | 
				
			||||||
	int res = strncmp(a->name, b->name, NAME_LEN);
 | 
					 | 
				
			||||||
	if (res == 0) res = strncmp(a->first_name, b->first_name, NAME_LEN);
 | 
					 | 
				
			||||||
	if (res == 0) res = a->age - b->age;
 | 
					 | 
				
			||||||
	return res;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int person_read(person_t *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	assert(p);
 | 
					 | 
				
			||||||
	assert(NAME_LEN == 20);
 | 
					 | 
				
			||||||
	return scanf("%19s %19s %u", p->name, p->first_name, &(p->age)) == 3;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,26 +0,0 @@
 | 
				
			||||||
#ifndef _PERSON_H_
 | 
					 | 
				
			||||||
#define _PERSON_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define NAME_LEN 20
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
	char name[NAME_LEN];
 | 
					 | 
				
			||||||
	char first_name[NAME_LEN];
 | 
					 | 
				
			||||||
	unsigned int age;
 | 
					 | 
				
			||||||
} person_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Compares two persons in this sequence: 1st=name, 2nd=first_name, 3rd=age
 | 
					 | 
				
			||||||
 * @param a [IN] const reference to 1st person in the comparison
 | 
					 | 
				
			||||||
 * @param b [IN] const reference to 2nd person in the comparison
 | 
					 | 
				
			||||||
 * @return =0 if all record fields are the same
 | 
					 | 
				
			||||||
 *         >0 if all previous fields are the same, but for this field, a is greater
 | 
					 | 
				
			||||||
 *         <0 if all previous fields are the same, but for this field, b is greater
 | 
					 | 
				
			||||||
 * @remark strncmp() is used for producing the result of string field comparisons
 | 
					 | 
				
			||||||
 * @remark a->age – b->age is used for producing the result of age comparison
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int person_compare(const person_t *a, const person_t *b);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int person_read(person_t *p);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // _PERSON_H_
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,299 +0,0 @@
 | 
				
			||||||
/* ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * --  _____       ______  _____                                              -
 | 
					 | 
				
			||||||
 * -- |_   _|     |  ____|/ ____|                                             -
 | 
					 | 
				
			||||||
 * --   | |  _ __ | |__  | (___    Institute of Embedded Systems              -
 | 
					 | 
				
			||||||
 * --   | | | '_ \|  __|  \___ \   Zuercher Hochschule Winterthur             -
 | 
					 | 
				
			||||||
 * --  _| |_| | | | |____ ____) |  (University of Applied Sciences)           -
 | 
					 | 
				
			||||||
 * -- |_____|_| |_|______|_____/   8401 Winterthur, Switzerland               -
 | 
					 | 
				
			||||||
 * ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * @brief Test suite for the given package.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <sys/wait.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#include <CUnit/Basic.h>
 | 
					 | 
				
			||||||
#include "test_utils.h"
 | 
					 | 
				
			||||||
#include "person.h"
 | 
					 | 
				
			||||||
#include "list.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef TARGET // must be given by the make file --> see test target
 | 
					 | 
				
			||||||
#error missing TARGET define
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief alias for EXIT_SUCCESS
 | 
					 | 
				
			||||||
#define OK   EXIT_SUCCESS
 | 
					 | 
				
			||||||
/// @brief alias for EXIT_FAILURE
 | 
					 | 
				
			||||||
#define FAIL EXIT_FAILURE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// @brief The name of the STDOUT text file.
 | 
					 | 
				
			||||||
#define OUTFILE "stdout.txt"
 | 
					 | 
				
			||||||
/// @brief The name of the STDERR text file.
 | 
					 | 
				
			||||||
#define ERRFILE "stderr.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define TRACE_INDENT "\n                " ///< allow for better stdout formatting in case of error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// setup & cleanup
 | 
					 | 
				
			||||||
static int setup(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    remove_file_if_exists(OUTFILE);
 | 
					 | 
				
			||||||
    remove_file_if_exists(ERRFILE);
 | 
					 | 
				
			||||||
    return 0; // success
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int teardown(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // Do nothing.
 | 
					 | 
				
			||||||
    // Especially: do not remove result files - they are removed in int setup(void) *before* running a test.
 | 
					 | 
				
			||||||
    return 0; // success
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// tests
 | 
					 | 
				
			||||||
static void test_person_compare(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	person_t a = { "a", "a", 1 };
 | 
					 | 
				
			||||||
	person_t b = { "a", "a", 2 };
 | 
					 | 
				
			||||||
	person_t c = { "a", "b", 1 };
 | 
					 | 
				
			||||||
	person_t d = { "a", "b", 2 };
 | 
					 | 
				
			||||||
	person_t e = { "b", "a", 1 };
 | 
					 | 
				
			||||||
	person_t f = { "b", "a", 2 };
 | 
					 | 
				
			||||||
	person_t g = { "b", "b", 1 };
 | 
					 | 
				
			||||||
	person_t h = { "b", "b", 2 };
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&a, &a) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&a, &b) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&a, &c) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&a, &d) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&a, &e) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&a, &f) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&a, &g) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&a, &h) < 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&b, &a) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&b, &b) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&b, &c) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&b, &d) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&b, &e) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&b, &f) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&b, &g) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&b, &h) < 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&c, &a) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&c, &b) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&c, &c) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&c, &d) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&c, &e) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&c, &f) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&c, &g) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&c, &h) < 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&d, &a) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&d, &b) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&d, &c) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&d, &d) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&d, &e) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&d, &f) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&d, &g) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&d, &h) < 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&e, &a) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&e, &b) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&e, &c) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&e, &d) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&e, &e) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&e, &f) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&e, &g) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&e, &h) < 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&f, &a) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&f, &b) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&f, &c) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&f, &d) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&f, &e) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&f, &f) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&f, &g) < 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&f, &h) < 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&g, &a) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&g, &b) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&g, &c) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&g, &d) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&g, &e) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&g, &f) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&g, &g) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&g, &h) < 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&h, &a) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&h, &b) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&h, &c) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&h, &d) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&h, &e) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&h, &f) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&h, &g) > 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&h, &h) == 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_list_insert(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const node_t *anchor = list_init();
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// act & assert: insert one
 | 
					 | 
				
			||||||
	person_t p1 = { "a", "b", 123 };
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p1));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert: insert a second after first
 | 
					 | 
				
			||||||
	person_t p2 = { "a", "b", 124 };
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p2));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p2) == 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert: insert a second before first
 | 
					 | 
				
			||||||
	person_t p3 = { "a", "b", 122 };
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p3));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p3) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->next->next->content), &p2) == 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert: reject inserting same
 | 
					 | 
				
			||||||
	CU_ASSERT_FALSE(list_insert(&p1));
 | 
					 | 
				
			||||||
	// unchanged
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next->next);
 | 
					 | 
				
			||||||
	// unchanged
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p3) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->next->next->content), &p2) == 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_list_remove(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const node_t *anchor = list_init();
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// act & assert: remove one
 | 
					 | 
				
			||||||
	person_t p1 = { "a", "b", 123 };
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p1));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	// remove same
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE_FATAL(list_remove(&p1));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert: failed to remove
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p1));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	// remove not found
 | 
					 | 
				
			||||||
	person_t p2 = { "a", "b", 124 };
 | 
					 | 
				
			||||||
	CU_ASSERT_FALSE_FATAL(list_remove(&p2));
 | 
					 | 
				
			||||||
	// unchanged
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert: remove last
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p2));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p2) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE_FATAL(list_remove(&p2));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert: remove first
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p2));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p2) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE_FATAL(list_remove(&p1));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p2) == 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_list_clear(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// BEGIN-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
	// arrange
 | 
					 | 
				
			||||||
	const node_t *anchor = list_init();
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert: empty list
 | 
					 | 
				
			||||||
	list_clear();
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// act & assert: clear list of one
 | 
					 | 
				
			||||||
	person_t p1 = { "a", "b", 123 };
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p1));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	list_clear();
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// act & assert: clear list of two
 | 
					 | 
				
			||||||
	person_t p2 = { "a", "b", 124 };
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p1));
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(list_insert(&p2));
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_NOT_EQUAL(anchor, anchor->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next->next->next);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->content), &p1) == 0);
 | 
					 | 
				
			||||||
	CU_ASSERT_TRUE(person_compare(&(anchor->next->next->content), &p2) == 0);
 | 
					 | 
				
			||||||
	list_clear();
 | 
					 | 
				
			||||||
	CU_ASSERT_PTR_EQUAL(anchor, anchor->next);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// END-STUDENTS-TO-ADD-CODE
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Registers and runs the tests.
 | 
					 | 
				
			||||||
 * @returns success (0) or one of the CU_ErrorCode (>0)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int main(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // setup, run, teardown
 | 
					 | 
				
			||||||
    TestMainBasic("lab test", setup, teardown
 | 
					 | 
				
			||||||
                  , test_person_compare
 | 
					 | 
				
			||||||
                  , test_list_insert
 | 
					 | 
				
			||||||
                  , test_list_remove
 | 
					 | 
				
			||||||
                  , test_list_clear
 | 
					 | 
				
			||||||
                  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,76 +0,0 @@
 | 
				
			||||||
digraph ProcessHierarchie {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P1[label="P01\nfork()"];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P11[label="P01\nfork()"];
 | 
					 | 
				
			||||||
  P12[label="P02\nfork()"];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P111[label="P01\nfork()"];
 | 
					 | 
				
			||||||
  P112[label="P03\nfork()"];
 | 
					 | 
				
			||||||
  P121[label="P02\nfork()"];
 | 
					 | 
				
			||||||
  P122[label="P04\nfork()"];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P1111[label="P01\nfork()"];
 | 
					 | 
				
			||||||
  P1112[label="P05\nfork()"];
 | 
					 | 
				
			||||||
  P1121[label="P03\nfork()"];
 | 
					 | 
				
			||||||
  P1122[label="P06\nfork()"];
 | 
					 | 
				
			||||||
  P1211[label="P02\nfork()"];
 | 
					 | 
				
			||||||
  P1212[label="P07\nfork()"];
 | 
					 | 
				
			||||||
  P1221[label="P04\nfork()"];
 | 
					 | 
				
			||||||
  P1222[label="P08\nfork()"];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P11111[label="P01"];
 | 
					 | 
				
			||||||
  P11112[label="P09"];
 | 
					 | 
				
			||||||
  P11121[label="P05"];
 | 
					 | 
				
			||||||
  P11122[label="P10"];
 | 
					 | 
				
			||||||
  P11211[label="P03"];
 | 
					 | 
				
			||||||
  P11212[label="P11"];
 | 
					 | 
				
			||||||
  P11221[label="P06"];
 | 
					 | 
				
			||||||
  P11222[label="P12"];
 | 
					 | 
				
			||||||
  P12111[label="P02"];
 | 
					 | 
				
			||||||
  P12112[label="P13"];
 | 
					 | 
				
			||||||
  P12121[label="P07"];
 | 
					 | 
				
			||||||
  P12122[label="P14"];
 | 
					 | 
				
			||||||
  P12211[label="P04"];
 | 
					 | 
				
			||||||
  P12212[label="P15"];
 | 
					 | 
				
			||||||
  P12221[label="P08"];
 | 
					 | 
				
			||||||
  P12222[label="P16"];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P1 -> P11
 | 
					 | 
				
			||||||
  P1 -> P12
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P11 -> P111
 | 
					 | 
				
			||||||
  P11 -> P112
 | 
					 | 
				
			||||||
  P12 -> P121
 | 
					 | 
				
			||||||
  P12 -> P122
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P111 -> P1111
 | 
					 | 
				
			||||||
  P111 -> P1112
 | 
					 | 
				
			||||||
  P112 -> P1121
 | 
					 | 
				
			||||||
  P112 -> P1122
 | 
					 | 
				
			||||||
  P121 -> P1211
 | 
					 | 
				
			||||||
  P121 -> P1212
 | 
					 | 
				
			||||||
  P122 -> P1221
 | 
					 | 
				
			||||||
  P122 -> P1222
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  P1111 -> P11111
 | 
					 | 
				
			||||||
  P1111 -> P11112
 | 
					 | 
				
			||||||
  P1112 -> P11121
 | 
					 | 
				
			||||||
  P1112 -> P11122
 | 
					 | 
				
			||||||
  P1121 -> P11211
 | 
					 | 
				
			||||||
  P1121 -> P11212
 | 
					 | 
				
			||||||
  P1122 -> P11221
 | 
					 | 
				
			||||||
  P1122 -> P11222
 | 
					 | 
				
			||||||
  P1211 -> P12111
 | 
					 | 
				
			||||||
  P1211 -> P12112
 | 
					 | 
				
			||||||
  P1212 -> P12121
 | 
					 | 
				
			||||||
  P1212 -> P12122
 | 
					 | 
				
			||||||
  P1221 -> P12211
 | 
					 | 
				
			||||||
  P1221 -> P12212
 | 
					 | 
				
			||||||
  P1222 -> P12221
 | 
					 | 
				
			||||||
  P1222 -> P12222
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { rank="same"; P11; P12; }
 | 
					 | 
				
			||||||
#  { rank="same"; P1; P11; P111; P1111; P11111; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 77 KiB  | 
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue