From 141b10c9c9a1519cf143f8eaba7494ae98a3012a Mon Sep 17 00:00:00 2001 From: Riley Smith Date: Sun, 17 Nov 2024 02:18:25 -0800 Subject: [PATCH] clean up codebase, add github action to run test --- .github/workflows/run_tests.yml | 21 + .gitlab-ci.yml | 39 - lab-5/Makefile => Makefile | 0 README.md | 73 +- lab-5/expr.c => expr.c | 0 lab-5/expr.h => expr.h | 0 lab-2/LANGUAGE.md | 144 -- lab-2/README.md | 99 - lab-2/hello-world.cbl | 6 - lab-2/program.c | 1 - lab-2/quadratic-snippet.cbl | 35 - lab-2/sorting-snippet.cbl | 55 - lab-3/README.md | 73 - lab-3/main.c | 30 - lab-3/main_test.c | 577 ------ lab-3/samples/quadratic-snippet.cbl | 34 - lab-3/samples/sorting-snippet.cbl | 55 - lab-3/scanner | Bin 71688 -> 0 bytes lab-3/scanner.flex | 69 - lab-3/token.h | 56 - lab-3/utest.h | 1668 ----------------- lab-4/Makefile | 29 - lab-4/README.md | 94 - lab-4/main.c | 11 - lab-4/main_test.c | 122 -- lab-4/parser.bison | 190 -- lab-4/samples/hello-world.cbl | 5 - lab-4/samples/quadratic-snippet.cbl | 33 - lab-4/samples/sorting-snippet.cbl | 54 - lab-4/scanner.flex | 64 - lab-4/utest.h | 1668 ----------------- lab-5/README.md | 107 -- lab-5/samples/hello-world.cbl | 5 - lab-5/samples/only-variables.cbl | 24 - lab-5/main.c => main.c | 0 lab-5/main_test.c => main_test.c | 0 lab-5/parser.bison => parser.bison | 0 lab-5/parser.bison.new => parser.bison.new | 0 lab-5/parser_test.c => parser_test.c | 0 {lab-5/samples => samples}/addition.cbl | 0 {lab-5/samples => samples}/assignment.cbl | 0 {lab-5/samples => samples}/branching.cbl | 0 .../hello-world-multiple-args.cbl | 0 {lab-3/samples => samples}/hello-world.cbl | 0 {lab-5/samples => samples}/looping.cbl | 0 {lab-4/samples => samples}/only-variables.cbl | 0 .../outputs/addition_evaluate.txt | 0 .../outputs/addition_print.txt | 0 .../outputs/assignment_evaluate.txt | 0 .../outputs/assignment_print.txt | 0 .../outputs/branching_evaluate.txt | 0 .../outputs/branching_print.txt | 0 .../outputs/hello-world_evaluate.txt | 0 .../outputs/hello-world_print.txt | 0 .../outputs/looping_evaluate.txt | 0 .../outputs/looping_print.txt | 0 .../outputs/quadratic_evaluate.txt | 0 .../outputs/quadratic_print.txt | 0 .../outputs/sorting_evaluate.txt | 0 .../outputs/sorting_print.txt | 0 .../samples => samples}/quadratic-snippet.cbl | 0 .../samples => samples}/sorting-snippet.cbl | 0 lab-5/scanner.flex => scanner.flex | 0 lab-5/scanner_test.c => scanner_test.c | 2 +- lab-5/symbol_map.c => symbol_map.c | 0 lab-5/symbol_map.h => symbol_map.h | 0 lab-5/token.h => token.h | 0 lab-5/utest.h => utest.h | 0 68 files changed, 27 insertions(+), 5416 deletions(-) create mode 100644 .github/workflows/run_tests.yml delete mode 100644 .gitlab-ci.yml rename lab-5/Makefile => Makefile (100%) rename lab-5/expr.c => expr.c (100%) rename lab-5/expr.h => expr.h (100%) delete mode 100644 lab-2/LANGUAGE.md delete mode 100644 lab-2/README.md delete mode 100644 lab-2/hello-world.cbl delete mode 100644 lab-2/program.c delete mode 100644 lab-2/quadratic-snippet.cbl delete mode 100644 lab-2/sorting-snippet.cbl delete mode 100644 lab-3/README.md delete mode 100644 lab-3/main.c delete mode 100644 lab-3/main_test.c delete mode 100644 lab-3/samples/quadratic-snippet.cbl delete mode 100644 lab-3/samples/sorting-snippet.cbl delete mode 100755 lab-3/scanner delete mode 100644 lab-3/scanner.flex delete mode 100644 lab-3/token.h delete mode 100644 lab-3/utest.h delete mode 100644 lab-4/Makefile delete mode 100644 lab-4/README.md delete mode 100644 lab-4/main.c delete mode 100644 lab-4/main_test.c delete mode 100644 lab-4/parser.bison delete mode 100644 lab-4/samples/hello-world.cbl delete mode 100644 lab-4/samples/quadratic-snippet.cbl delete mode 100644 lab-4/samples/sorting-snippet.cbl delete mode 100644 lab-4/scanner.flex delete mode 100644 lab-4/utest.h delete mode 100644 lab-5/README.md delete mode 100644 lab-5/samples/hello-world.cbl delete mode 100644 lab-5/samples/only-variables.cbl rename lab-5/main.c => main.c (100%) rename lab-5/main_test.c => main_test.c (100%) rename lab-5/parser.bison => parser.bison (100%) rename lab-5/parser.bison.new => parser.bison.new (100%) rename lab-5/parser_test.c => parser_test.c (100%) rename {lab-5/samples => samples}/addition.cbl (100%) rename {lab-5/samples => samples}/assignment.cbl (100%) rename {lab-5/samples => samples}/branching.cbl (100%) rename {lab-5/samples => samples}/hello-world-multiple-args.cbl (100%) rename {lab-3/samples => samples}/hello-world.cbl (100%) rename {lab-5/samples => samples}/looping.cbl (100%) rename {lab-4/samples => samples}/only-variables.cbl (100%) rename {lab-5/samples => samples}/outputs/addition_evaluate.txt (100%) rename {lab-5/samples => samples}/outputs/addition_print.txt (100%) rename {lab-5/samples => samples}/outputs/assignment_evaluate.txt (100%) rename {lab-5/samples => samples}/outputs/assignment_print.txt (100%) rename {lab-5/samples => samples}/outputs/branching_evaluate.txt (100%) rename {lab-5/samples => samples}/outputs/branching_print.txt (100%) rename {lab-5/samples => samples}/outputs/hello-world_evaluate.txt (100%) rename {lab-5/samples => samples}/outputs/hello-world_print.txt (100%) rename {lab-5/samples => samples}/outputs/looping_evaluate.txt (100%) rename {lab-5/samples => samples}/outputs/looping_print.txt (100%) rename {lab-5/samples => samples}/outputs/quadratic_evaluate.txt (100%) rename {lab-5/samples => samples}/outputs/quadratic_print.txt (100%) rename {lab-5/samples => samples}/outputs/sorting_evaluate.txt (100%) rename {lab-5/samples => samples}/outputs/sorting_print.txt (100%) rename {lab-5/samples => samples}/quadratic-snippet.cbl (100%) rename {lab-5/samples => samples}/sorting-snippet.cbl (100%) rename lab-5/scanner.flex => scanner.flex (100%) rename lab-5/scanner_test.c => scanner_test.c (99%) rename lab-5/symbol_map.c => symbol_map.c (100%) rename lab-5/symbol_map.h => symbol_map.h (100%) rename lab-5/token.h => token.h (100%) rename lab-5/utest.h => utest.h (100%) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml new file mode 100644 index 0000000..708de47 --- /dev/null +++ b/.github/workflows/run_tests.yml @@ -0,0 +1,21 @@ +name: Run Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu + steps: + - uses: actions/checkout@v2 + # setup build-essentials & flex & bison + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install build-essential flex bison + - name: Run tests + run: | + make run_tests diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index d7f06be..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,39 +0,0 @@ ---- -lab_3_tests: - stage: test - image: gitlab.cs.wallawalla.edu:5050/cs_department/docker-images/cpp - script: - - apt update - - apt install -y flex bison - - bison --version - - cd lab-3 - - echo "Lab 3 - Flex" - - flex -o scanner.c scanner.flex - - echo "Lab 3 - Compile Tests" - - gcc main_test.c scanner.c -o scanner_test.out - - echo "Lab 3 - Run Tests" - - ./scanner_test.out - -lab_4_tests: - stage: test - image: gitlab.cs.wallawalla.edu:5050/cs_department/docker-images/cpp - script: - - apt update - - apt install -y flex bison - - bison --version - - cd lab-4 - - echo "Lab 4 - Bison Parser" - - make test - - ./parser_test.out - -lab_5_tests: - stage: test - image: gitlab.cs.wallawalla.edu:5050/cs_department/docker-images/cpp - script: - - apt update - - apt install -y flex bison - - bison --version - - cd lab-5 - - echo "Lab 5 - Interpreter" - - make test - - ./interpreter_test.out diff --git a/lab-5/Makefile b/Makefile similarity index 100% rename from lab-5/Makefile rename to Makefile diff --git a/README.md b/README.md index 62ab427..359367d 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,9 @@ -# Language Interpreter Lab +# COBOL Interpreter Lab -The project has been set up for Flex and Bison. -You must add your language definitions to the _lab-2_ folder. -Each lab has a separate folder where you will continue working on your scanner, parser, and interpreter. -The Unit Test will be automatically run when you commit to Gitlab. +## Overview -## Forking the Repository +During my compilers and languages class at Walla Walla University, my group chose to make a COBOL interpreter. -To create a fork of this repository, click on the *fork* button on the original repository at . -Copy the URL of your forked repository by clicking the clipboard icon next to it. -The URL should look something like: +This is the resulting project. -```shell -git@gitlab.cs.wallawalla.edu:YourUsername/language-interpreter-lab.git -``` - -Once you have forked the repository, you must set its visibility level to private so that only you can see it. -To do this, - -1. Click on the gear icon at the top right of the project page in GitLab. -2. Select *Edit Project* from the drop-down menu. -3. Set the *Visibility Level* to *Private* in the *Project settings* box. -4. Scroll down until you find the green *Save changes* button and click it. - -Add your partner to the project. -From the project homepage: - -1. Click on the side menu labeled *Members*. -2. Search for your partner. -3. Give them *Maintainer* access to the project. - -## Setting Up Your Local Workspace - -Create your local workspace by cloning the repository to your machine. -Put the repository in a place that will remember. -You can clone the repository by using a command similar to this: - -```shell -git clone git@gitlab.cs.wallawalla.edu:YourUsername/language-interpreter-lab.git -``` - -If you are asked to enter a password, you need to set up your SSH key. - -```shell -ssh-keygen -more ~/.ssh/id_rsa.pub -``` - -Copy the generated public key into GitLab under your profile SSH keys - -Finally, to make sure that you can receive updates easily (see below), type the -following commands in the command window at the bottom of the Cloud 9 screen. - -```shell -git remote add upstream git@gitlab.cs.wallawalla.edu:cptr354/language-interpreter-lab.git -``` - -## Passing Tests - -Every time you commit code and push it to GitLab, the test will be automatically executed. -You can find the results by looking at the **CI/CD** menu option. -It will list the recent jobs executed and show their status. -You can find the details of each job by clicking on them. - - -## Examples - -A few repositories with code describing **b-minor** which is described in the textbook. - -* -* +> This interpreter is based on the work of Douglas Thain who created the [Compiler Book](https://www3.nd.edu/~dthain/compilerbook/) diff --git a/lab-5/expr.c b/expr.c similarity index 100% rename from lab-5/expr.c rename to expr.c diff --git a/lab-5/expr.h b/expr.h similarity index 100% rename from lab-5/expr.h rename to expr.h diff --git a/lab-2/LANGUAGE.md b/lab-2/LANGUAGE.md deleted file mode 100644 index 3511a57..0000000 --- a/lab-2/LANGUAGE.md +++ /dev/null @@ -1,144 +0,0 @@ -# Language Proposal - -### 1. Hello World - -- source used: [Cobol Emulator](https://www.jdoodle.com/execute-cobol-online) -- display the text "Hello World!" in the terminal -- https://www.tutorialspoint.com/cobol/cobol_program_structure.htm this website has useful information about the structure of the cobol language -- the Identification Division is mandatory for all programs and sub divisions have unique sentences within them and determine what is done with variables or IO in this example - - #### Input - - there is no input for this example - - #### Output - - the string "Hello World!" is sent to output via the included DISPLAY function - -### 2. Quadratic Function - -- Code altered from [Marco Biagini](https://www.quora.com/What-is-a-COBOL-program-that-will-solve-a-quadratic-equation) -- Solves a quadratic equation of the form **ax^2 + bx + c = 0** - - #### Input - - Coefficients are a fixed value with a = 1, b = 5, c = 6 - - #### Output - - EQUATION: (1x^2) + 5x + 6 = 0 - - The equation has two distinct real roots: - Root 1: -02.00 - Root 2: -03.00 - -### 3. Integer Sort - -- Code altered from [Wikibooks]https://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Bubble_sort#COBOL - -- Uses bubble sort to sort an array of integers. - #### Input - An array of integers - #### Output - The array sorted in ascending order - -### 4. Language Features - -- #### Identifiers - - All variables are declared within DATA DIVISION. Variable names accept letters(A-Z), digits(0-9), and hyphens(-). In the syntax of: - - - [PIC/PICTURE )] - [VALUE ] - - Statements in [ ] are optional. Example: - - 01 INT-VAR PIC 9(03 VALUE 123). - -- #### Special words - - - Note: Keywords are not case sensitive but good practice is to only use uppercase - - Division statements divide the structure of the code. Some examples are PROGRAM-ID, DATA DIVISION, WORKING STORAGE DIVISION, PROCEDURE DIVISION, and STOP RUN. - - DISPLAY outputs data to user - - MOVE sends data from one variable to another - - ACCEPT allows for user input to go into a variable - - Supports boolean values TRUE and FALSE - -- #### Literal - - *> This is a comment in COBOL - - - Non-numeric - - DISPLAY "This is a string in COBOL". - DISPLAY 'This is a string in COBOL'. - - Numeric - - Digits 0 - 9 - Positive numbers: +10 - Negative numbers: -10 - Decimal: 10.00 - -- #### Math Operators - - Supports additon (+), subraction (-), multiplication (\*), and division (/) and exponentation (\*\*). Equations begin with COMPUTE. - - COMPUTE total = 1 + 2 - -- #### Relational Operators - - Supports =, >, <, >=, <=, NOT = - - IF a > b - -- #### Delimiters - - Section headers and verb statements should end with a separator period (.) - - PROCEDURE DIVISION. - MOVE "Hello" TO VAR1. - - Commas (,) can separate two variables - - ADD 3 TO VAR1, VAR2. - -- #### Lists - - Supports arrays (known in COBOL as tables). Declared in DATA DIVISION. In the syntax of: - - 01 . - 02 [PIC ] - OCCURS [TO ] TIMES - [DEPENDING ON] - [DESCENDING|ASCENDING KEY IS ] - [INDEXED BY ] - - Statements in [ ] are optional. Example: - - 01 Students - 03 Student-grades PIC 9(03) OCCURS 6 TIMES. - -- #### Loops - - Loops begin with a PERFORM statement and end with END-PERFORM. Note that a separator period (.) should not used within a PERFORM block. - - PERFORM - - END-PERFORM. - -- #### Branching - Uses IF/END-IF and ELSE statements and nested statements. Note that a separator period (.) should not used within an IF statement. - IF - DISPLAY "Option 1" - ELSE - DISPLAY "Option 2" - END-IF. - -`Language Feature Sources` - -- [tutorialspoint.com](https://www.tutorialspoint.com/cobol/cobol_basic_syntax.htm) - -- [mainframestechhelp.com](https://www.mainframestechhelp.com/tutorials/cobol/) diff --git a/lab-2/README.md b/lab-2/README.md deleted file mode 100644 index 5865c6f..0000000 --- a/lab-2/README.md +++ /dev/null @@ -1,99 +0,0 @@ -# Language Proposal - -In this class we will have a series of labs focus developing and implementing an interpreter for a known language. -In this lab you will start the process by researching the language definition for your language. -You will gather code examples and language definitions for specific features. - -## Language Choices - -Please select one of the following languages (that has not been selected by someone else) for your language interpreter lab project: - - - ADA 80 - Algol 68 - COBOL - Dartmouth BASIC - Dart - F# - Fortran 77 - MUMPS - Perl - Rust - Smalltalk - Swift - - -The following are also options, but carry a 5% penalty since they are more familiar: - - - C++ - JavaScript - Ruby - - -## Code Example - -To help guide the features needed in our interpreter, please find the code to implement these tasks. - -* Hello World! -* Use the quadratic function to solve an equation -* Sort a list of integers (using any algorithm; keep it simple) - -These code snippets will be used as a test case in your interpreter. -If you did not write this code, please cite the source. - -Please create files in the `lab-2` folder to hold the snippets of code. -Use the `lab-2/LANGUAGE.md` to describe the input and output for these code snippets. - -## Review The Code Snippets - -What features are needed to implement this code? - - Identifiers - Special words - Literal - Math Operators - Relational Operators - Delimiters - Lists - Loops - Branching - -For each feature write down the definition for that feature. For example, create a list of special words (or reserved words) used by your code. -For something like Identifiers, what are the naming rules for an identifier? Please cite sources for language definition. - -A Partial Example - -An partial example report has been posted for the Python language. -See the example report: - - -## Criteria - -The following things will be looked for when grading your report: - -* Code Snippet — Hello World code, input, and resulting output -* Code Snippet — Quadratic equation code, input, and resulting output -* Code Snippet — Integer sorting code, input, and resulting output -* Language Features — List of required language features -* Language Definitions — For each feature, define the syntax and rules to implement the feature -* Report skills — Easy to follow and writing quality - -Your report and code should be in a forked project from . Follow the `README.md` to configure your project. - -## Grading Rubric - -The grading will be over the following categories. - -Points Description ------------ ------------------------------------ -20 points Code Snippet — Quadratic equation -20 points Code Snippet — Integer sorting -10 points Language Features -40 points Language Definitions -10 points Report formatting and readability - -## Turn In - -Please submit the URL of your gitlab project to D2L's Brightspace with your report. -On gitlab update the `lab-2` folder to have your report and code snippets before the due date. diff --git a/lab-2/hello-world.cbl b/lab-2/hello-world.cbl deleted file mode 100644 index 3c78e9b..0000000 --- a/lab-2/hello-world.cbl +++ /dev/null @@ -1,6 +0,0 @@ -IDENTIFICATION DIVISION. -PROGRAM-ID. HELLO-WORLD. -PROCEDURE DIVISION. - DISPLAY "Hello World!" -STOP RUN. -if \ No newline at end of file diff --git a/lab-2/program.c b/lab-2/program.c deleted file mode 100644 index 4e490aa..0000000 --- a/lab-2/program.c +++ /dev/null @@ -1 +0,0 @@ -2+3 \ No newline at end of file diff --git a/lab-2/quadratic-snippet.cbl b/lab-2/quadratic-snippet.cbl deleted file mode 100644 index ab76e40..0000000 --- a/lab-2/quadratic-snippet.cbl +++ /dev/null @@ -1,35 +0,0 @@ - *> Code altered from https://www.quora.com/What-is-a-COBOL-program-that-will-solve-a-quadratic-equation - *> Program finds the roots to a simple quadratic equation - - IDENTIFICATION DIVISION. - PROGRAM-ID. QuadraticSolver. - DATA DIVISION. - WORKING-STORAGE SECTION. - 77 a PIC S9(5)V9(5) COMP-3 VALUE 1. - 77 b PIC S9(5)V9(5) COMP-3 VALUE 5. - 77 c PIC S9(5)V9(5) COMP-3 VALUE 6. - 77 discriminant PIC S9(5)V9(5) COMP-3. - 77 root1 PIC S9(5)V9(5) COMP-3. - 77 root2 PIC S9(5)V9(5) COMP-3. - 77 square-root-discriminant PIC S9(5)V9(5) COMP-3. - - PROCEDURE DIVISION. *> program begins here - DISPLAY "EQUATION: (1x^2) + 5x + 6 = 0" - COMPUTE discriminant = (b ** 2) - (4 * a * c) - - IF discriminant > 0 - COMPUTE square-root-discriminant = FUNCTION SQRT(discriminant) - COMPUTE root1 = (-b + square-root-discriminant) / (2 * a) - COMPUTE root2 = (-b - square-root-discriminant) / (2 * a) - DISPLAY "The equation has two distinct real roots: " - DISPLAY "Root 1: " root1 - DISPLAY "Root 2: " root2 - - ELSE IF discriminant = 0 - COMPUTE root1 = -b / (2 * a) - DISPLAY "The equation has one real root: " - DISPLAY "Root: " root1 - ELSE - DISPLAY "The equation has no real roots." - - STOP RUN. diff --git a/lab-2/sorting-snippet.cbl b/lab-2/sorting-snippet.cbl deleted file mode 100644 index a0eae92..0000000 --- a/lab-2/sorting-snippet.cbl +++ /dev/null @@ -1,55 +0,0 @@ -IDENTIFICATION DIVISION. -PROGRAM-ID. sorting. -DATA DIVISION. -WORKING-STORAGE SECTION. - 01 WS-SORT-AREA. - 05 WS-SORT-TABLE. - 10 WS-SORT-ROW PIC X(10) OCCURS 100. - 05 WS-TEMP-ROW PIC X(10). - 05 WS-ROW-MAX PIC S9(4) COMP VALUE 100. - 05 WS-SORT-MAX PIC S9(4) COMP. - 05 WS-I PIC S9(4) COMP. - 05 WS-J PIC S9(4) COMP. - 05 WS-INDEX PIC S9(4) COMP. - -PROCEDURE DIVISION. -*> * Initialize test data - MOVE "30" TO WS-SORT-ROW(1) - MOVE "10" TO WS-SORT-ROW(2) - MOVE "50" TO WS-SORT-ROW(3) - MOVE "20" TO WS-SORT-ROW(4) - MOVE "40" TO WS-SORT-ROW(5) - MOVE 5 TO WS-SORT-MAX - -*> * Display original array - DISPLAY "Original Array Contents:" - DISPLAY "---------------------" - PERFORM VARYING WS-INDEX FROM 1 BY 1 - UNTIL WS-INDEX > WS-SORT-MAX - DISPLAY "Element " WS-INDEX ": " WS-SORT-ROW(WS-INDEX) - END-PERFORM - DISPLAY SPACE - -*> * Simplified bubble sort - PERFORM VARYING WS-I FROM 1 BY 1 - UNTIL WS-I > WS-SORT-MAX - 1 - PERFORM VARYING WS-J FROM 1 BY 1 - UNTIL WS-J > WS-SORT-MAX - WS-I - IF WS-SORT-ROW(WS-J) > WS-SORT-ROW(WS-J + 1) - MOVE WS-SORT-ROW(WS-J) TO WS-TEMP-ROW - MOVE WS-SORT-ROW(WS-J + 1) TO WS-SORT-ROW(WS-J) - MOVE WS-TEMP-ROW TO WS-SORT-ROW(WS-J + 1) - END-IF - END-PERFORM - END-PERFORM - -*> * Display sorted array - DISPLAY "Sorted Array Contents:" - DISPLAY "--------------------" - PERFORM VARYING WS-INDEX FROM 1 BY 1 - UNTIL WS-INDEX > WS-SORT-MAX - DISPLAY "Element " WS-INDEX ": " WS-SORT-ROW(WS-INDEX) - END-PERFORM. - - STOP RUN. - \ No newline at end of file diff --git a/lab-3/README.md b/lab-3/README.md deleted file mode 100644 index ca7420e..0000000 --- a/lab-3/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Flex Scanner - -Create a scanner for your sample programs. -See the [example lab for Python](https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab-python). - -## Language Scanner - -Add the tokens needed to scan your sample code files. - -In addition include the following: - -* All the math operations (+,-,/,* etc.) -* All boolean expression (==,>,< etc.) -* All relational operators (not,and,or) -* ... - -## Testing the Language Scanner - -Write unit test for your sample code. -The sample program uses `utest.h` which is a simple c unit test framework. -The documentation can be found at . - -The `main.c` has been replaced with unit test code. -Your task is to create one unit test for each sample file. - -When you submit the code to GitLab, the CI should automatically compile and run your test code. -To recieve full credit, the tests must pass when run through GitLab CI. - -## Build Process - -To build the `scanner.c` run the following **flex** command. - -```sh -flex -o scanner.c scanner.flex -``` - -Then build the `main.c` and `scanner.c` using **gcc**. - -```sh -gcc main_test.c scanner.c -o scanner_test.out -``` - -Then execute the test suite using `./scanner_test.out`. - -```sh -./scanner_test.out -``` - -## Scanner Only - -```sh -flex -o scanner.c scanner.flex -gcc main.c scanner.c -o scanner.out -./scanner.out -``` - - -## Grading Rubric - -The grading will be over the following categories. - -Points Description ------------ ------------------------------------ -30 points Tests for individual language tokens -10 points Ability to scan — Hello world -20 points Ability to scan — Quadratic equation -20 points Ability to scan — Integer sorting -20 points Passes continuous integration - -## Turn In - -Please submit the URL of your gitlab project to D2L's Brightspace with your report. -On gitlab update the `lab-3` folder to have your report and code snippets before the due date. diff --git a/lab-3/main.c b/lab-3/main.c deleted file mode 100644 index 78770a1..0000000 --- a/lab-3/main.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "token.h" -#include -#include - -extern FILE *yyin; -extern int yylex(); -extern char *yytext; - -int main(int argc, char *argv[]) { - FILE *file; - const char *filename = "samples/quadratic-snippet.cbl"; - - // Check if a filename is provided as a command-line argument - if (argc > 1) { - filename = argv[1]; - } - - // Open the file - yyin = fopen(filename, "r"); - if (!yyin) { - printf("could not open file!\n"); - return 1; - } - while (1) { - token_t t = yylex(); - if (t == TOKEN_EOF) - break; - printf("token: %d, text: %s\n", t, yytext); - } -} diff --git a/lab-3/main_test.c b/lab-3/main_test.c deleted file mode 100644 index 8f22d24..0000000 --- a/lab-3/main_test.c +++ /dev/null @@ -1,577 +0,0 @@ -#include "token.h" -// https://github.com/sheredom/utest.h/blob/master/utest.h -#include "utest.h" -#include - -typedef struct yy_buffer_state *YY_BUFFER_STATE; -extern void yyrestart(FILE * input_file); -extern YY_BUFFER_STATE yy_scan_buffer(char *str, int i); -extern void yy_delete_buffer(YY_BUFFER_STATE buffer); -extern FILE *yyin; -extern int yylex(); -extern char *yytext; - -UTEST_MAIN(); - -struct token_st { - token_t t; - char *p; -}; - -UTEST(scanner, hello) { - struct token_st tokens[] = { - {TOKEN_KEYWORD_IDENTIFICATION, "IDENTIFICATION"}, - {TOKEN_KEYWORD_DIVISION, "DIVISION"}, - {TOKEN_DOT, "."}, - {TOKEN_PROGRAM_ID, "PROGRAM-ID"}, - {TOKEN_DOT, "."}, - {TOKEN_IDENT, "HELLO-WORLD"}, - {TOKEN_DOT, "."}, - {TOKEN_PROCEDURE, "PROCEDURE"}, - {TOKEN_KEYWORD_DIVISION, "DIVISION"}, - {TOKEN_DOT, "."}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "'Hello World!'"}, - {TOKEN_STOP, "STOP"}, - {TOKEN_RUN, "RUN"}, - {TOKEN_DOT, "."}, - {TOKEN_EOF, ""}, - }; - - - yyin = fopen("samples/hello-world.cbl", "r"); - ASSERT_TRUE(yyin); - int index = 0; - token_t t; - do { - // printf("index: %d token: %d text: %s\n", index, t, yytext); - ASSERT_EQ(tokens[index].t, (t = yylex())); - ASSERT_STREQ(tokens[index].p, yytext); - ++index; - } while (t != TOKEN_EOF); -} - -UTEST(scanner, quadratic) { - struct token_st tokens[] = { - {TOKEN_KEYWORD_IDENTIFICATION, "IDENTIFICATION"}, - {TOKEN_KEYWORD_DIVISION, "DIVISION"}, - {TOKEN_DOT, "."}, - {TOKEN_PROGRAM_ID, "PROGRAM-ID"}, - {TOKEN_DOT, "."}, - {TOKEN_IDENT, "QuadraticSolver"}, - {TOKEN_DOT, "."}, - {TOKEN_KEYWORD_DATA, "DATA"}, - {TOKEN_KEYWORD_DIVISION, "DIVISION"}, - {TOKEN_DOT, "."}, - - {TOKEN_WORKING_STORAGE, "WORKING-STORAGE"}, - {TOKEN_KEYWORD_SECTION, "SECTION"}, - {TOKEN_DOT, "."}, - - {TOKEN_INTEGER, "77"}, - {TOKEN_IDENT, "a"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, // Check later - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_IMPLIED_DECIMAL, "V9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_3, "COMP-3"}, - {TOKEN_KEYWORD_VALUE, "VALUE"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_DOT, "."}, - - {TOKEN_INTEGER, "77"}, - {TOKEN_IDENT, "b"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_IMPLIED_DECIMAL, "V9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_3, "COMP-3"}, - {TOKEN_KEYWORD_VALUE, "VALUE"}, - {TOKEN_INTEGER, "5"}, - {TOKEN_DOT, "."}, - - {TOKEN_INTEGER, "77"}, - {TOKEN_IDENT, "c"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_IMPLIED_DECIMAL, "V9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_3, "COMP-3"}, - {TOKEN_KEYWORD_VALUE, "VALUE"}, - {TOKEN_INTEGER, "6"}, - {TOKEN_DOT, "."}, - - {TOKEN_INTEGER, "77"}, - {TOKEN_IDENT, "discriminant"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_IMPLIED_DECIMAL, "V9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_3, "COMP-3"}, - {TOKEN_DOT, "."}, - - {TOKEN_INTEGER, "77"}, - {TOKEN_IDENT, "root1"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_IMPLIED_DECIMAL, "V9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_3, "COMP-3"}, - {TOKEN_DOT, "."}, - - {TOKEN_INTEGER, "77"}, - {TOKEN_IDENT, "root2"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_IMPLIED_DECIMAL, "V9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_3, "COMP-3"}, - {TOKEN_DOT, "."}, - - {TOKEN_INTEGER, "77"}, - {TOKEN_IDENT, "square-root-discriminant"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_IMPLIED_DECIMAL, "V9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_3, "COMP-3"}, - {TOKEN_DOT, "."}, - - // {TOKEN_EOF, ""}, - - {TOKEN_PROCEDURE, "PROCEDURE"}, - {TOKEN_KEYWORD_DIVISION, "DIVISION"}, - {TOKEN_DOT, "."}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"EQUATION: (1x^2) + 5x + 6 = 0\""}, - {TOKEN_KEYWORD_COMPUTE, "COMPUTE"}, - {TOKEN_IDENT, "discriminant"}, - {TOKEN_EQUAL, "="}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "b"}, - {TOKEN_EXPONENTIAL, "**"}, - {TOKEN_INTEGER, "2"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_SUB, "-"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "4"}, - {TOKEN_MULTIPLY, "*"}, - {TOKEN_IDENT, "a"}, - {TOKEN_MULTIPLY, "*"}, - {TOKEN_IDENT, "c"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - - // {TOKEN_EOF, ""}, - - {TOKEN_IF, "IF"}, - {TOKEN_IDENT, "discriminant"}, - {TOKEN_GREATER_THAN, ">"}, - {TOKEN_INTEGER, "0"}, - - {TOKEN_KEYWORD_COMPUTE, "COMPUTE"}, - {TOKEN_IDENT, "square-root-discriminant"}, - {TOKEN_EQUAL, "="}, - {TOKEN_KEYWORD_FUNCTION, "FUNCTION"}, - {TOKEN_IDENT, "SQRT"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "discriminant"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - - - {TOKEN_KEYWORD_COMPUTE, "COMPUTE"}, - {TOKEN_IDENT, "root1"}, - {TOKEN_EQUAL, "="}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_SUB, "-"}, - {TOKEN_IDENT, "b"}, - {TOKEN_ADD, "+"}, - {TOKEN_IDENT, "square-root-discriminant"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_DIVIDE, "/"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "2"}, - {TOKEN_MULTIPLY, "*"}, - {TOKEN_IDENT, "a"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - - {TOKEN_KEYWORD_COMPUTE, "COMPUTE"}, - {TOKEN_IDENT, "root2"}, - {TOKEN_EQUAL, "="}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_SUB, "-"}, - {TOKEN_IDENT, "b"}, - {TOKEN_SUB, "-"}, - {TOKEN_IDENT, "square-root-discriminant"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_DIVIDE, "/"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "2"}, - {TOKEN_MULTIPLY, "*"}, - {TOKEN_IDENT, "a"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"The equation has two distinct real roots: \""}, - - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"Root 1: \""}, - {TOKEN_IDENT, "root1"}, - - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"Root 2: \""}, - {TOKEN_IDENT, "root2"}, - - // {TOKEN_EOF, ""}, - - {TOKEN_ELSE, "ELSE"}, - {TOKEN_IF, "IF"}, - {TOKEN_IDENT, "discriminant"}, - {TOKEN_EQUAL, "="}, - {TOKEN_INTEGER, "0"}, - - {TOKEN_KEYWORD_COMPUTE, "COMPUTE"}, - {TOKEN_IDENT, "root1"}, - {TOKEN_EQUAL, "="}, - {TOKEN_SUB, "-"}, - {TOKEN_IDENT, "b"}, - {TOKEN_DIVIDE, "/"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "2"}, - {TOKEN_MULTIPLY, "*"}, - {TOKEN_IDENT, "a"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - - - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"The equation has one real root: \""}, - - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"Root: \""}, - {TOKEN_IDENT, "root1"}, - - - {TOKEN_ELSE, "ELSE"}, - - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"The equation has no real roots.\""}, - {TOKEN_END_IF, "END-IF"}, - - // {TOKEN_EOF, ""}, - - {TOKEN_STOP, "STOP"}, - {TOKEN_RUN, "RUN"}, - {TOKEN_DOT, "."}, - {TOKEN_EOF, ""}, - }; - - yyin = fopen("samples/quadratic-snippet.cbl", "r"); - ASSERT_TRUE(yyin); - int index = 0; - token_t t; - do { - printf("index: %d token: %d text: %s\n", index, t, yytext); - ASSERT_EQ(tokens[index].t, (t = yylex())); - ASSERT_STREQ(tokens[index].p, yytext); - ++index; - } while (t != TOKEN_EOF); -} - -UTEST(scanner, sorting) { - struct token_st tokens[] = { - {TOKEN_KEYWORD_IDENTIFICATION, "IDENTIFICATION"}, - {TOKEN_KEYWORD_DIVISION, "DIVISION"}, - {TOKEN_DOT, "."}, - {TOKEN_PROGRAM_ID, "PROGRAM-ID"}, - {TOKEN_DOT, "."}, - {TOKEN_IDENT, "sorting"}, - {TOKEN_DOT, "."}, - {TOKEN_KEYWORD_DATA, "DATA"}, - {TOKEN_KEYWORD_DIVISION, "DIVISION"}, - {TOKEN_DOT, "."}, - {TOKEN_WORKING_STORAGE, "WORKING-STORAGE"}, - {TOKEN_KEYWORD_SECTION, "SECTION"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "01"}, - {TOKEN_IDENT, "WS-SORT-AREA"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "05"}, - {TOKEN_IDENT, "WS-SORT-TABLE"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "10"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_ALPHANUMERIC, "X"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "10"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_KEYWORD_OCCURS, "OCCURS"}, - {TOKEN_INTEGER, "100"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "05"}, - {TOKEN_IDENT, "WS-TEMP-ROW"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_ALPHANUMERIC, "X"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "10"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "05"}, - {TOKEN_IDENT, "WS-ROW-MAX"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "4"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_0, "COMP"}, - {TOKEN_KEYWORD_VALUE, "VALUE"}, - {TOKEN_INTEGER, "100"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "05"}, - {TOKEN_IDENT, "WS-SORT-MAX"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "4"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_0, "COMP"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "05"}, - {TOKEN_IDENT, "WS-I"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "4"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_0, "COMP"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "05"}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "4"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_0, "COMP"}, - {TOKEN_DOT, "."}, - {TOKEN_INTEGER, "05"}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_PICTURE, "PIC"}, - {TOKEN_SIGNED_NUMERIC, "S9"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "4"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_COMPUTATION_LEVEL_0, "COMP"}, - {TOKEN_DOT, "."}, - {TOKEN_PROCEDURE, "PROCEDURE"}, - {TOKEN_KEYWORD_DIVISION, "DIVISION"}, - {TOKEN_DOT, "."}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_STRING, "\"30\""}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "1"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_STRING, "\"10\""}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "2"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_STRING, "\"50\""}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "3"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_STRING, "\"20\""}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "4"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_STRING, "\"40\""}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_INTEGER, "5"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_INTEGER, "5"}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-SORT-MAX"}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"Original Array Contents:\""}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"---------------------\""}, - {TOKEN_PERFORM, "PERFORM"}, - {TOKEN_VARYING, "VARYING"}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_KEYWORD_FROM, "FROM"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_KEYWORD_BY, "BY"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_UNTIL, "UNTIL"}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_GREATER_THAN, ">"}, - {TOKEN_IDENT, "WS-SORT-MAX"}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"Element \""}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_STRING, "\": \""}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_END_PERFORM, "END-PERFORM"}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_SPACE, "SPACE"}, - {TOKEN_PERFORM, "PERFORM"}, - {TOKEN_VARYING, "VARYING"}, - {TOKEN_IDENT, "WS-I"}, - {TOKEN_KEYWORD_FROM, "FROM"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_KEYWORD_BY, "BY"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_UNTIL, "UNTIL"}, - {TOKEN_IDENT, "WS-I"}, - {TOKEN_GREATER_THAN, ">"}, - {TOKEN_IDENT, "WS-SORT-MAX"}, - {TOKEN_SUB, "-"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_PERFORM, "PERFORM"}, - {TOKEN_VARYING, "VARYING"}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_KEYWORD_FROM, "FROM"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_KEYWORD_BY, "BY"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_UNTIL, "UNTIL"}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_GREATER_THAN, ">"}, - {TOKEN_IDENT, "WS-SORT-MAX"}, - {TOKEN_SUB, "-"}, - {TOKEN_IDENT, "WS-I"}, - {TOKEN_IF, "IF"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_GREATER_THAN, ">"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_ADD, "+"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-TEMP-ROW"}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_ADD, "+"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_MOVE, "MOVE"}, - {TOKEN_IDENT, "WS-TEMP-ROW"}, - {TOKEN_KEYWORD_TO, "TO"}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "WS-J"}, - {TOKEN_ADD, "+"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_END_IF, "END-IF"}, - {TOKEN_END_PERFORM, "END-PERFORM"}, - {TOKEN_END_PERFORM, "END-PERFORM"}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"Sorted Array Contents:\""}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"--------------------\""}, - {TOKEN_PERFORM, "PERFORM"}, - {TOKEN_VARYING, "VARYING"}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_KEYWORD_FROM, "FROM"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_KEYWORD_BY, "BY"}, - {TOKEN_INTEGER, "1"}, - {TOKEN_UNTIL, "UNTIL"}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_GREATER_THAN, ">"}, - {TOKEN_IDENT, "WS-SORT-MAX"}, - {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "\"Element \""}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_STRING, "\": \""}, - {TOKEN_IDENT, "WS-SORT-ROW"}, - {TOKEN_LEFT_PARENTHESIS, "("}, - {TOKEN_IDENT, "WS-INDEX"}, - {TOKEN_RIGHT_PARENTHESIS, ")"}, - {TOKEN_END_PERFORM, "END-PERFORM"}, - {TOKEN_DOT, "."}, - {TOKEN_STOP, "STOP"}, - {TOKEN_RUN, "RUN"}, - {TOKEN_DOT, "."}, - {TOKEN_EOF, ""}, - }; - yyin = fopen("samples/sorting-snippet.cbl", "r"); - ASSERT_TRUE(yyin); - int index = 0; - token_t t; - do { - printf("index: %d token: %d text: %s\n", index, t, yytext); - ASSERT_EQ(tokens[index].t, (t = yylex())); - ASSERT_STREQ(tokens[index].p, yytext); - ++index; - } while (t != TOKEN_EOF); -} \ No newline at end of file diff --git a/lab-3/samples/quadratic-snippet.cbl b/lab-3/samples/quadratic-snippet.cbl deleted file mode 100644 index 00eb26f..0000000 --- a/lab-3/samples/quadratic-snippet.cbl +++ /dev/null @@ -1,34 +0,0 @@ - *> Code altered from https://www.quora.com/What-is-a-COBOL-program-that-will-solve-a-quadratic-equation - *> Program finds the roots to a simple quadratic equation - - IDENTIFICATION DIVISION. - PROGRAM-ID. QuadraticSolver. - DATA DIVISION. - WORKING-STORAGE SECTION. - 77 a PIC S9(5)V9(5) COMP-3 VALUE 1. - 77 b PIC S9(5)V9(5) COMP-3 VALUE 5. - 77 c PIC S9(5)V9(5) COMP-3 VALUE 6. - 77 discriminant PIC S9(5)V9(5) COMP-3. - 77 root1 PIC S9(5)V9(5) COMP-3. - 77 root2 PIC S9(5)V9(5) COMP-3. - 77 square-root-discriminant PIC S9(5)V9(5) COMP-3. - - PROCEDURE DIVISION. *> program begins here - DISPLAY "EQUATION: (1x^2) + 5x + 6 = 0" - COMPUTE discriminant = (b ** 2) - (4 * a * c) - - IF discriminant > 0 - COMPUTE square-root-discriminant = FUNCTION SQRT(discriminant) - COMPUTE root1 = (-b + square-root-discriminant) / (2 * a) - COMPUTE root2 = (-b - square-root-discriminant) / (2 * a) - DISPLAY "The equation has two distinct real roots: " - DISPLAY "Root 1: " root1 - DISPLAY "Root 2: " root2 - ELSE IF discriminant = 0 - COMPUTE root1 = -b / (2 * a) - DISPLAY "The equation has one real root: " - DISPLAY "Root: " root1 - ELSE - DISPLAY "The equation has no real roots." - END-IF - STOP RUN. diff --git a/lab-3/samples/sorting-snippet.cbl b/lab-3/samples/sorting-snippet.cbl deleted file mode 100644 index 8324e47..0000000 --- a/lab-3/samples/sorting-snippet.cbl +++ /dev/null @@ -1,55 +0,0 @@ -IDENTIFICATION DIVISION. -PROGRAM-ID. sorting. -DATA DIVISION. -WORKING-STORAGE SECTION. - 01 WS-SORT-AREA. - 05 WS-SORT-TABLE. - 10 WS-SORT-ROW PIC X(10) OCCURS 100. - 05 WS-TEMP-ROW PIC X(10). - 05 WS-ROW-MAX PIC S9(4) COMP VALUE 100. - 05 WS-SORT-MAX PIC S9(4) COMP. - 05 WS-I PIC S9(4) COMP. - 05 WS-J PIC S9(4) COMP. - 05 WS-INDEX PIC S9(4) COMP. - -PROCEDURE DIVISION. -*> Initialize test data - MOVE "30" TO WS-SORT-ROW(1) - MOVE "10" TO WS-SORT-ROW(2) - MOVE "50" TO WS-SORT-ROW(3) - MOVE "20" TO WS-SORT-ROW(4) - MOVE "40" TO WS-SORT-ROW(5) - MOVE 5 TO WS-SORT-MAX - -*> * Display original array - DISPLAY "Original Array Contents:" - DISPLAY "---------------------" - PERFORM VARYING WS-INDEX FROM 1 BY 1 - UNTIL WS-INDEX > WS-SORT-MAX - DISPLAY "Element " WS-INDEX ": " WS-SORT-ROW(WS-INDEX) - END-PERFORM - DISPLAY SPACE - -*> * Simplified bubble sort - PERFORM VARYING WS-I FROM 1 BY 1 - UNTIL WS-I > WS-SORT-MAX - 1 - PERFORM VARYING WS-J FROM 1 BY 1 - UNTIL WS-J > WS-SORT-MAX - WS-I - IF WS-SORT-ROW(WS-J) > WS-SORT-ROW(WS-J + 1) - MOVE WS-SORT-ROW(WS-J) TO WS-TEMP-ROW - MOVE WS-SORT-ROW(WS-J + 1) TO WS-SORT-ROW(WS-J) - MOVE WS-TEMP-ROW TO WS-SORT-ROW(WS-J + 1) - END-IF - END-PERFORM - END-PERFORM - -*> * Display sorted array - DISPLAY "Sorted Array Contents:" - DISPLAY "--------------------" - PERFORM VARYING WS-INDEX FROM 1 BY 1 - UNTIL WS-INDEX > WS-SORT-MAX - DISPLAY "Element " WS-INDEX ": " WS-SORT-ROW(WS-INDEX) - END-PERFORM. - - STOP RUN. - \ No newline at end of file diff --git a/lab-3/scanner b/lab-3/scanner deleted file mode 100755 index 28ce88dba2b110110b8001bc3f96f5532b1f51a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71688 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 M82*0!X0p2f2P-r~Qvd(} diff --git a/lab-3/scanner.flex b/lab-3/scanner.flex deleted file mode 100644 index 262c437..0000000 --- a/lab-3/scanner.flex +++ /dev/null @@ -1,69 +0,0 @@ -%{ -#include "token.h" -%} -%option warn -%option nodefault -%option yylineno - -NAME [a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])? -DIGIT [0-9]+ -%% - -(" "|\t|\n) /* skip whitespace */ -\*>\ ?.* -IDENTIFICATION { return TOKEN_KEYWORD_IDENTIFICATION; } -DIVISION { return TOKEN_KEYWORD_DIVISION; } -PROGRAM-ID { return TOKEN_PROGRAM_ID; } -PROCEDURE { return TOKEN_PROCEDURE; } -DATA { return TOKEN_KEYWORD_DATA; } -SECTION { return TOKEN_KEYWORD_SECTION; } -WORKING-STORAGE { return TOKEN_WORKING_STORAGE; } -DISPLAY { return TOKEN_DISPLAY; } -STOP { return TOKEN_STOP; } -RUN { return TOKEN_RUN; } -MOVE { return TOKEN_MOVE; } -TO { return TOKEN_KEYWORD_TO; } -VARYING { return TOKEN_VARYING; } -FROM { return TOKEN_KEYWORD_FROM; } -BY { return TOKEN_KEYWORD_BY; } -UNTIL { return TOKEN_UNTIL; } -PERFORM { return TOKEN_PERFORM; } -END-PERFORM { return TOKEN_END_PERFORM; } -IF { return TOKEN_IF; } -ELSE { return TOKEN_ELSE; } -END-IF { return TOKEN_END_IF; } -SPACE { return TOKEN_SPACE; } -PIC { return TOKEN_PICTURE; } -OCCURS { return TOKEN_KEYWORD_OCCURS; } -VALUE { return TOKEN_KEYWORD_VALUE; } -COMPUTE { return TOKEN_KEYWORD_COMPUTE; } -FUNCTION { return TOKEN_KEYWORD_FUNCTION; } -X { return TOKEN_ALPHANUMERIC; } -S9 { return TOKEN_SIGNED_NUMERIC; } -9 { return TOKEN_NUMERIC; } -V9 { return TOKEN_IMPLIED_DECIMAL; } -COMP { return TOKEN_COMPUTATION_LEVEL_0; } -COMP-1 { return TOKEN_COMPUTATION_LEVEL_1; } -COMP-2 { return TOKEN_COMPUTATION_LEVEL_2; } -COMP-3 { return TOKEN_COMPUTATION_LEVEL_3; } - - -\+ { return TOKEN_ADD; } -\- { return TOKEN_SUB; } -\*\* { return TOKEN_EXPONENTIAL; } -\* { return TOKEN_MULTIPLY; } -\/ { return TOKEN_DIVIDE; } -\> { return TOKEN_GREATER_THAN; } -\< { return TOKEN_LESS_THAN; } -\= { return TOKEN_EQUAL;} - -"\""[^"]*"\"" { return TOKEN_STRING; } -"\'"[^']*"\'" { return TOKEN_STRING; } -"(" { return TOKEN_LEFT_PARENTHESIS; } -")" { return TOKEN_RIGHT_PARENTHESIS; } -{NAME} { return TOKEN_IDENT; } -{DIGIT} { return TOKEN_INTEGER; } - -\. { return TOKEN_DOT; } -%% -int yywrap() { return 1; } diff --git a/lab-3/token.h b/lab-3/token.h deleted file mode 100644 index 47ce470..0000000 --- a/lab-3/token.h +++ /dev/null @@ -1,56 +0,0 @@ -typedef enum { - TOKEN_EOF = 0, - TOKEN_KEYWORD_IDENTIFICATION, - TOKEN_KEYWORD_DIVISION, - TOKEN_KEYWORD_DATA, - TOKEN_KEYWORD_SECTION, - TOKEN_PROGRAM_ID, - TOKEN_WORKING_STORAGE, - TOKEN_PROCEDURE, - TOKEN_DISPLAY, - TOKEN_STOP, - TOKEN_RUN, - TOKEN_MOVE, - TOKEN_KEYWORD_TO, - TOKEN_PERFORM, - TOKEN_VARYING, - TOKEN_KEYWORD_FROM, - TOKEN_KEYWORD_BY, - TOKEN_UNTIL, - TOKEN_END_PERFORM, - TOKEN_IF, - TOKEN_ELSE, - TOKEN_END_IF, - TOKEN_ELSE_IF, - TOKEN_SPACE, - TOKEN_KEYWORD_OCCURS, - TOKEN_KEYWORD_VALUE, - TOKEN_KEYWORD_COMPUTE, - TOKEN_KEYWORD_FUNCTION, - TOKEN_IDENT, - TOKEN_STRING, - TOKEN_INTEGER, - TOKEN_NEGATIVE_INTEGER, - TOKEN_PICTURE, - TOKEN_ALPHANUMERIC, - TOKEN_NUMERIC, - TOKEN_SIGNED_NUMERIC, - TOKEN_IMPLIED_DECIMAL, - TOKEN_LEVEL_NUM, - TOKEN_COMPUTATION_LEVEL_0, - TOKEN_COMPUTATION_LEVEL_1, - TOKEN_COMPUTATION_LEVEL_2, - TOKEN_COMPUTATION_LEVEL_3, - TOKEN_LEFT_PARENTHESIS, - TOKEN_RIGHT_PARENTHESIS, - TOKEN_DOT, - TOKEN_COMMENT, - TOKEN_ADD, - TOKEN_SUB, - TOKEN_MULTIPLY, - TOKEN_DIVIDE, - TOKEN_EQUAL, - TOKEN_GREATER_THAN, - TOKEN_LESS_THAN, - TOKEN_EXPONENTIAL, -} token_t; \ No newline at end of file diff --git a/lab-3/utest.h b/lab-3/utest.h deleted file mode 100644 index 8767600..0000000 --- a/lab-3/utest.h +++ /dev/null @@ -1,1668 +0,0 @@ -/* - The latest version of this library is available on GitHub; - https://github.com/sheredom/utest.h -*/ - -/* - This is free and unencumbered software released into the public domain. - - Anyone is free to copy, modify, publish, use, compile, sell, or - distribute this software, either in source code form or as a compiled - binary, for any purpose, commercial or non-commercial, and by any - means. - - In jurisdictions that recognize copyright laws, the author or authors - of this software dedicate any and all copyright interest in the - software to the public domain. We make this dedication for the benefit - of the public at large and to the detriment of our heirs and - successors. We intend this dedication to be an overt act of - relinquishment in perpetuity of all present and future rights to this - software under copyright law. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - For more information, please refer to -*/ - -#ifndef SHEREDOM_UTEST_H_INCLUDED -#define SHEREDOM_UTEST_H_INCLUDED - -#ifdef _MSC_VER -/* - Disable warning about not inlining 'inline' functions. -*/ -#pragma warning(disable : 4710) - -/* - Disable warning about inlining functions that are not marked 'inline'. -*/ -#pragma warning(disable : 4711) - -/* - Disable warning for alignment padding added -*/ -#pragma warning(disable : 4820) - -#if _MSC_VER > 1900 -/* - Disable warning about preprocessor macros not being defined in MSVC headers. -*/ -#pragma warning(disable : 4668) - -/* - Disable warning about no function prototype given in MSVC headers. -*/ -#pragma warning(disable : 4255) - -/* - Disable warning about pointer or reference to potentially throwing function. -*/ -#pragma warning(disable : 5039) - -/* - Disable warning about macro expansion producing 'defined' has undefined - behavior. -*/ -#pragma warning(disable : 5105) -#endif - -#if _MSC_VER > 1930 -/* - Disable warning about 'const' variable is not used. -*/ -#pragma warning(disable : 5264) -#endif - -#pragma warning(push, 1) -#endif - -#if defined(_MSC_VER) && (_MSC_VER < 1920) -typedef __int64 utest_int64_t; -typedef unsigned __int64 utest_uint64_t; -typedef unsigned __int32 utest_uint32_t; -#else -#include -typedef int64_t utest_int64_t; -typedef uint64_t utest_uint64_t; -typedef uint32_t utest_uint32_t; -#endif - -#include -#include -#include -#include -#include - -#if defined(__cplusplus) -#if defined(_MSC_VER) && !defined(_CPPUNWIND) -/* We're on MSVC and the compiler is compiling without exception support! */ -#elif !defined(_MSC_VER) && !defined(__EXCEPTIONS) -/* We're on a GCC/Clang compiler that doesn't have exception support! */ -#else -#define UTEST_HAS_EXCEPTIONS 1 -#endif -#endif - -#if defined(UTEST_HAS_EXCEPTIONS) -#include -#endif - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -#if defined(__cplusplus) -#define UTEST_C_FUNC extern "C" -#else -#define UTEST_C_FUNC -#endif - -#define UTEST_TEST_PASSED (0) -#define UTEST_TEST_FAILURE (1) -#define UTEST_TEST_SKIPPED (2) - -#if defined(__TINYC__) -#define UTEST_ATTRIBUTE(a) __attribute((a)) -#else -#define UTEST_ATTRIBUTE(a) __attribute__((a)) -#endif - -#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) - -#if defined(__MINGW64__) || defined(__MINGW32__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpragmas" -#pragma GCC diagnostic ignored "-Wunknown-pragmas" -#endif - -#if defined(_WINDOWS_) || defined(_WINDOWS_H) -typedef LARGE_INTEGER utest_large_integer; -#else -// use old QueryPerformanceCounter definitions (not sure is this needed in some -// edge cases or not) on Win7 with VS2015 these extern declaration cause "second -// C linkage of overloaded function not allowed" error -typedef union { - struct { - unsigned long LowPart; - long HighPart; - } DUMMYSTRUCTNAME; - struct { - unsigned long LowPart; - long HighPart; - } u; - utest_int64_t QuadPart; -} utest_large_integer; - -UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceCounter( - utest_large_integer *); -UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceFrequency( - utest_large_integer *); - -#if defined(__MINGW64__) || defined(__MINGW32__) -#pragma GCC diagnostic pop -#endif -#endif - -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \ - defined(__HAIKU__) -/* - slightly obscure include here - we need to include glibc's features.h, but - we don't want to just include a header that might not be defined for other - c libraries like musl. Instead we include limits.h, which we know on all - glibc distributions includes features.h -*/ -#include - -#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) -#include - -#if ((2 < __GLIBC__) || ((2 == __GLIBC__) && (17 <= __GLIBC_MINOR__))) -/* glibc is version 2.17 or above, so we can just use clock_gettime */ -#define UTEST_USE_CLOCKGETTIME -#else -#include -#include -#endif -#else // Other libc implementations -#include -#define UTEST_USE_CLOCKGETTIME -#endif - -#elif defined(__APPLE__) -#include -#endif - -#if defined(_MSC_VER) && (_MSC_VER < 1920) -#define UTEST_PRId64 "I64d" -#define UTEST_PRIu64 "I64u" -#else -#include - -#define UTEST_PRId64 PRId64 -#define UTEST_PRIu64 PRIu64 -#endif - -#if defined(__cplusplus) -#define UTEST_INLINE inline - -#if defined(__clang__) -#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") - -#define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") -#else -#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS -#define UTEST_INITIALIZER_END_DISABLE_WARNINGS -#endif - -#define UTEST_INITIALIZER(f) \ - struct f##_cpp_struct { \ - f##_cpp_struct(); \ - }; \ - UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS static f##_cpp_struct \ - f##_cpp_global UTEST_INITIALIZER_END_DISABLE_WARNINGS; \ - f##_cpp_struct::f##_cpp_struct() -#elif defined(_MSC_VER) -#define UTEST_INLINE __forceinline - -#if defined(_WIN64) -#define UTEST_SYMBOL_PREFIX -#else -#define UTEST_SYMBOL_PREFIX "_" -#endif - -#if defined(__clang__) -#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wmissing-variable-declarations\"") - -#define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") -#else -#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS -#define UTEST_INITIALIZER_END_DISABLE_WARNINGS -#endif - -#pragma section(".CRT$XCU", read) -#define UTEST_INITIALIZER(f) \ - static void __cdecl f(void); \ - UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ - __pragma(comment(linker, "/include:" UTEST_SYMBOL_PREFIX #f "_")) \ - UTEST_C_FUNC __declspec(allocate(".CRT$XCU")) void(__cdecl * \ - f##_)(void) = f; \ - UTEST_INITIALIZER_END_DISABLE_WARNINGS \ - static void __cdecl f(void) -#else -#if defined(__linux__) -#if defined(__clang__) -#if __has_warning("-Wreserved-id-macro") -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreserved-id-macro" -#endif -#endif - -#define __STDC_FORMAT_MACROS 1 - -#if defined(__clang__) -#if __has_warning("-Wreserved-id-macro") -#pragma clang diagnostic pop -#endif -#endif -#endif - -#define UTEST_INLINE inline - -#define UTEST_INITIALIZER(f) \ - static void f(void) UTEST_ATTRIBUTE(constructor); \ - static void f(void) -#endif - -#if defined(__cplusplus) -#define UTEST_CAST(type, x) static_cast(x) -#define UTEST_PTR_CAST(type, x) reinterpret_cast(x) -#define UTEST_EXTERN extern "C" -#define UTEST_NULL NULL -#else -#define UTEST_CAST(type, x) ((type)(x)) -#define UTEST_PTR_CAST(type, x) ((type)(x)) -#define UTEST_EXTERN extern -#define UTEST_NULL 0 -#endif - -#ifdef _MSC_VER -/* - io.h contains definitions for some structures with natural padding. This is - uninteresting, but for some reason MSVC's behaviour is to warn about - including this system header. That *is* interesting -*/ -#pragma warning(disable : 4820) -#pragma warning(push, 1) -#include -#pragma warning(pop) -#define UTEST_COLOUR_OUTPUT() (_isatty(_fileno(stdout))) -#else -#if defined(__EMSCRIPTEN__) -#include -#define UTEST_COLOUR_OUTPUT() false -#else -#include -#define UTEST_COLOUR_OUTPUT() (isatty(STDOUT_FILENO)) -#endif -#endif - -static UTEST_INLINE void *utest_realloc(void *const pointer, size_t new_size) { - void *const new_pointer = realloc(pointer, new_size); - - if (UTEST_NULL == new_pointer) { - free(new_pointer); - } - - return new_pointer; -} - -static UTEST_INLINE utest_int64_t utest_ns(void) { -#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) - utest_large_integer counter; - utest_large_integer frequency; - QueryPerformanceCounter(&counter); - QueryPerformanceFrequency(&frequency); - return UTEST_CAST(utest_int64_t, - (counter.QuadPart * 1000000000) / frequency.QuadPart); -#elif defined(__linux__) && defined(__STRICT_ANSI__) - return UTEST_CAST(utest_int64_t, clock()) * 1000000000 / CLOCKS_PER_SEC; -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \ - defined(__HAIKU__) - struct timespec ts; -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(__HAIKU__) - timespec_get(&ts, TIME_UTC); -#else - const clockid_t cid = CLOCK_REALTIME; -#if defined(UTEST_USE_CLOCKGETTIME) - clock_gettime(cid, &ts); -#else - syscall(SYS_clock_gettime, cid, &ts); -#endif -#endif - return UTEST_CAST(utest_int64_t, ts.tv_sec) * 1000 * 1000 * 1000 + ts.tv_nsec; -#elif __APPLE__ - return UTEST_CAST(utest_int64_t, clock_gettime_nsec_np(CLOCK_UPTIME_RAW)); -#elif __EMSCRIPTEN__ - return emscripten_performance_now() * 1000000.0; -#else -#error Unsupported platform! -#endif -} - -typedef void (*utest_testcase_t)(int *, size_t); - -struct utest_test_state_s { - utest_testcase_t func; - size_t index; - char *name; -}; - -struct utest_state_s { - struct utest_test_state_s *tests; - size_t tests_length; - FILE *output; -}; - -/* extern to the global state utest needs to execute */ -UTEST_EXTERN struct utest_state_s utest_state; - -#if defined(_MSC_VER) -#define UTEST_WEAK __forceinline -#elif defined(__MINGW32__) || defined(__MINGW64__) -#define UTEST_WEAK static UTEST_ATTRIBUTE(used) -#elif defined(__clang__) || defined(__GNUC__) || defined(__TINYC__) -#define UTEST_WEAK UTEST_ATTRIBUTE(weak) -#else -#error Non clang, non gcc, non MSVC, non tcc compiler found! -#endif - -#if defined(_MSC_VER) -#define UTEST_UNUSED -#else -#define UTEST_UNUSED UTEST_ATTRIBUTE(unused) -#endif - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wvariadic-macros" -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#define UTEST_PRINTF(...) \ - if (utest_state.output) { \ - fprintf(utest_state.output, __VA_ARGS__); \ - } \ - printf(__VA_ARGS__) -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wvariadic-macros" -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -#ifdef _MSC_VER -#define UTEST_SNPRINTF(BUFFER, N, ...) _snprintf_s(BUFFER, N, N, __VA_ARGS__) -#else -#define UTEST_SNPRINTF(...) snprintf(__VA_ARGS__) -#endif - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#if defined(__cplusplus) -/* if we are using c++ we can use overloaded methods (its in the language) */ -#define UTEST_OVERLOADABLE -#elif defined(__clang__) -/* otherwise, if we are using clang with c - use the overloadable attribute */ -#define UTEST_OVERLOADABLE UTEST_ATTRIBUTE(overloadable) -#endif - -#if defined(__cplusplus) && (__cplusplus >= 201103L) - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -#include - -template ::value> -struct utest_type_deducer final { - static void _(const T t); -}; - -template <> struct utest_type_deducer { - static void _(const signed char c) { - UTEST_PRINTF("%d", static_cast(c)); - } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned char c) { - UTEST_PRINTF("%u", static_cast(c)); - } -}; - -template <> struct utest_type_deducer { - static void _(const short s) { UTEST_PRINTF("%d", static_cast(s)); } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned short s) { - UTEST_PRINTF("%u", static_cast(s)); - } -}; - -template <> struct utest_type_deducer { - static void _(const float f) { UTEST_PRINTF("%f", static_cast(f)); } -}; - -template <> struct utest_type_deducer { - static void _(const double d) { UTEST_PRINTF("%f", d); } -}; - -template <> struct utest_type_deducer { - static void _(const long double d) { -#if defined(__MINGW32__) || defined(__MINGW64__) - /* MINGW is weird - doesn't like LF at all?! */ - UTEST_PRINTF("%f", (double)d); -#else - UTEST_PRINTF("%Lf", d); -#endif - } -}; - -template <> struct utest_type_deducer { - static void _(const int i) { UTEST_PRINTF("%d", i); } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned int i) { UTEST_PRINTF("%u", i); } -}; - -template <> struct utest_type_deducer { - static void _(const long i) { UTEST_PRINTF("%ld", i); } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned long i) { UTEST_PRINTF("%lu", i); } -}; - -template <> struct utest_type_deducer { - static void _(const long long i) { UTEST_PRINTF("%lld", i); } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned long long i) { UTEST_PRINTF("%llu", i); } -}; - -template struct utest_type_deducer { - static void _(const T *t) { - UTEST_PRINTF("%p", static_cast(const_cast(t))); - } -}; - -template struct utest_type_deducer { - static void _(T *t) { UTEST_PRINTF("%p", static_cast(t)); } -}; - -template struct utest_type_deducer { - static void _(const T t) { - UTEST_PRINTF("%llu", static_cast(t)); - } -}; - -template -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const T t) { - utest_type_deducer::_(t); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#elif defined(UTEST_OVERLOADABLE) - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(signed char c); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(signed char c) { - UTEST_PRINTF("%d", UTEST_CAST(int, c)); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned char c); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned char c) { - UTEST_PRINTF("%u", UTEST_CAST(unsigned int, c)); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f) { - UTEST_PRINTF("%f", UTEST_CAST(double, f)); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d) { - UTEST_PRINTF("%f", d); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d) { -#if defined(__MINGW32__) || defined(__MINGW64__) - /* MINGW is weird - doesn't like LF at all?! */ - UTEST_PRINTF("%f", (double)d); -#else - UTEST_PRINTF("%Lf", d); -#endif -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i) { - UTEST_PRINTF("%d", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i) { - UTEST_PRINTF("%u", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i) { - UTEST_PRINTF("%ld", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i) { - UTEST_PRINTF("%lu", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p) { - UTEST_PRINTF("%p", p); -} - -/* - long long is a c++11 extension -*/ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || \ - defined(__cplusplus) && (__cplusplus >= 201103L) || \ - (defined(__MINGW32__) || defined(__MINGW64__)) - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i) { - UTEST_PRINTF("%lld", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long unsigned int i); -UTEST_WEAK UTEST_OVERLOADABLE void -utest_type_printer(long long unsigned int i) { - UTEST_PRINTF("%llu", i); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !(defined(__MINGW32__) || defined(__MINGW64__)) || \ - defined(__TINYC__) -#define utest_type_printer(val) \ - UTEST_PRINTF(_Generic((val), signed char \ - : "%d", unsigned char \ - : "%u", short \ - : "%d", unsigned short \ - : "%u", int \ - : "%d", long \ - : "%ld", long long \ - : "%lld", unsigned \ - : "%u", unsigned long \ - : "%lu", unsigned long long \ - : "%llu", float \ - : "%f", double \ - : "%f", long double \ - : "%Lf", default \ - : _Generic((val - val), ptrdiff_t \ - : "%p", default \ - : "undef")), \ - (val)) -#else -/* - we don't have the ability to print the values we got, so we create a macro - to tell our users we can't do anything fancy -*/ -#define utest_type_printer(...) UTEST_PRINTF("undef") -#endif - -#if defined(_MSC_VER) -#define UTEST_SURPRESS_WARNING_BEGIN \ - __pragma(warning(push)) __pragma(warning(disable : 4127)) \ - __pragma(warning(disable : 4571)) __pragma(warning(disable : 4130)) -#define UTEST_SURPRESS_WARNING_END __pragma(warning(pop)) -#else -#define UTEST_SURPRESS_WARNING_BEGIN -#define UTEST_SURPRESS_WARNING_END -#endif - -#if defined(__cplusplus) && (__cplusplus >= 201103L) -#define UTEST_AUTO(x) auto -#elif !defined(__cplusplus) - -#if defined(__clang__) -/* clang-format off */ -/* had to disable clang-format here because it malforms the pragmas */ -#define UTEST_AUTO(x) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wgnu-auto-type\"") __auto_type \ - _Pragma("clang diagnostic pop") -/* clang-format on */ -#else -#define UTEST_AUTO(x) __typeof__(x + 0) -#endif - -#else -#define UTEST_AUTO(x) typeof(x + 0) -#endif - -#if defined(__clang__) -#define UTEST_STRNCMP(x, y, size) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") \ - strncmp(x, y, size) _Pragma("clang diagnostic pop") -#else -#define UTEST_STRNCMP(x, y, size) strncmp(x, y, size) -#endif - -#if defined(_MSC_VER) -#define UTEST_STRNCPY(x, y, size) strcpy_s(x, size, y) -#elif !defined(__clang__) && defined(__GNUC__) -static UTEST_INLINE char * -utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-overflow" - return strncpy(dst, src, size); -#pragma GCC diagnostic pop -} - -#define UTEST_STRNCPY(x, y, size) utest_strncpy_gcc(x, y, size) -#else -#define UTEST_STRNCPY(x, y, size) strncpy(x, y, size) -#endif - -#define UTEST_SKIP(msg) \ - do { \ - UTEST_PRINTF(" Skipped : '%s'\n", (msg)); \ - *utest_result = UTEST_TEST_SKIPPED; \ - return; \ - } while (0) - -#if defined(__clang__) -#define UTEST_COND(x, y, cond, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wlanguage-extension-token\"") \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \ - _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \ - UTEST_AUTO(x) xEval = (x); \ - UTEST_AUTO(y) yEval = (y); \ - if (!((xEval)cond(yEval))) { \ - _Pragma("clang diagnostic pop") \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : ("); \ - UTEST_PRINTF(#x ") " #cond " (" #y); \ - UTEST_PRINTF(")\n"); \ - UTEST_PRINTF(" Actual : "); \ - utest_type_printer(xEval); \ - UTEST_PRINTF(" vs "); \ - utest_type_printer(yEval); \ - UTEST_PRINTF("\n"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END -#elif defined(__GNUC__) || defined(__TINYC__) -#define UTEST_COND(x, y, cond, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - UTEST_AUTO(x) xEval = (x); \ - UTEST_AUTO(y) yEval = (y); \ - if (!((xEval)cond(yEval))) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : ("); \ - UTEST_PRINTF(#x ") " #cond " (" #y); \ - UTEST_PRINTF(")\n"); \ - UTEST_PRINTF(" Actual : "); \ - utest_type_printer(xEval); \ - UTEST_PRINTF(" vs "); \ - utest_type_printer(yEval); \ - UTEST_PRINTF("\n"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END -#else -#define UTEST_COND(x, y, cond, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - if (!((x)cond(y))) { \ - UTEST_PRINTF("%s:%i: Failure (Expected " #cond " Actual)", __FILE__, \ - __LINE__); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s", msg); \ - } \ - UTEST_PRINTF("\n"); \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END -#endif - -#define EXPECT_EQ(x, y) UTEST_COND(x, y, ==, "", 0) -#define EXPECT_EQ_MSG(x, y, msg) UTEST_COND(x, y, ==, msg, 0) -#define ASSERT_EQ(x, y) UTEST_COND(x, y, ==, "", 1) -#define ASSERT_EQ_MSG(x, y, msg) UTEST_COND(x, y, ==, msg, 1) - -#define EXPECT_NE(x, y) UTEST_COND(x, y, !=, "", 0) -#define EXPECT_NE_MSG(x, y, msg) UTEST_COND(x, y, !=, msg, 0) -#define ASSERT_NE(x, y) UTEST_COND(x, y, !=, "", 1) -#define ASSERT_NE_MSG(x, y, msg) UTEST_COND(x, y, !=, msg, 1) - -#define EXPECT_LT(x, y) UTEST_COND(x, y, <, "", 0) -#define EXPECT_LT_MSG(x, y, msg) UTEST_COND(x, y, <, msg, 0) -#define ASSERT_LT(x, y) UTEST_COND(x, y, <, "", 1) -#define ASSERT_LT_MSG(x, y, msg) UTEST_COND(x, y, <, msg, 1) - -#define EXPECT_LE(x, y) UTEST_COND(x, y, <=, "", 0) -#define EXPECT_LE_MSG(x, y, msg) UTEST_COND(x, y, <=, msg, 0) -#define ASSERT_LE(x, y) UTEST_COND(x, y, <=, "", 1) -#define ASSERT_LE_MSG(x, y, msg) UTEST_COND(x, y, <=, msg, 1) - -#define EXPECT_GT(x, y) UTEST_COND(x, y, >, "", 0) -#define EXPECT_GT_MSG(x, y, msg) UTEST_COND(x, y, >, msg, 0) -#define ASSERT_GT(x, y) UTEST_COND(x, y, >, "", 1) -#define ASSERT_GT_MSG(x, y, msg) UTEST_COND(x, y, >, msg, 1) - -#define EXPECT_GE(x, y) UTEST_COND(x, y, >=, "", 0) -#define EXPECT_GE_MSG(x, y, msg) UTEST_COND(x, y, >=, msg, 0) -#define ASSERT_GE(x, y) UTEST_COND(x, y, >=, "", 1) -#define ASSERT_GE_MSG(x, y, msg) UTEST_COND(x, y, >=, msg, 1) - -#define UTEST_TRUE(x, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const int xEval = !!(x); \ - if (!(xEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : true\n"); \ - UTEST_PRINTF(" Actual : %s\n", (xEval) ? "true" : "false"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_TRUE(x) UTEST_TRUE(x, "", 0) -#define EXPECT_TRUE_MSG(x, msg) UTEST_TRUE(x, msg, 0) -#define ASSERT_TRUE(x) UTEST_TRUE(x, "", 1) -#define ASSERT_TRUE_MSG(x, msg) UTEST_TRUE(x, msg, 1) - -#define UTEST_FALSE(x, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const int xEval = !!(x); \ - if (xEval) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : false\n"); \ - UTEST_PRINTF(" Actual : %s\n", (xEval) ? "true" : "false"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_FALSE(x) UTEST_FALSE(x, "", 0) -#define EXPECT_FALSE_MSG(x, msg) UTEST_FALSE(x, msg, 0) -#define ASSERT_FALSE(x) UTEST_FALSE(x, "", 1) -#define ASSERT_FALSE_MSG(x, msg) UTEST_FALSE(x, msg, 1) - -#define UTEST_STREQ(x, y, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const char *xEval = (x); \ - const char *yEval = (y); \ - if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ - 0 != strcmp(xEval, yEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : \"%s\"\n", xEval); \ - UTEST_PRINTF(" Actual : \"%s\"\n", yEval); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_STREQ(x, y) UTEST_STREQ(x, y, "", 0) -#define EXPECT_STREQ_MSG(x, y, msg) UTEST_STREQ(x, y, msg, 0) -#define ASSERT_STREQ(x, y) UTEST_STREQ(x, y, "", 1) -#define ASSERT_STREQ_MSG(x, y, msg) UTEST_STREQ(x, y, msg, 1) - -#define UTEST_STRNE(x, y, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const char *xEval = (x); \ - const char *yEval = (y); \ - if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ - 0 == strcmp(xEval, yEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : \"%s\"\n", xEval); \ - UTEST_PRINTF(" Actual : \"%s\"\n", yEval); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_STRNE(x, y) UTEST_STRNE(x, y, "", 0) -#define EXPECT_STRNE_MSG(x, y, msg) UTEST_STRNE(x, y, msg, 0) -#define ASSERT_STRNE(x, y) UTEST_STRNE(x, y, "", 1) -#define ASSERT_STRNE_MSG(x, y, msg) UTEST_STRNE(x, y, msg, 1) - -#define UTEST_STRNEQ(x, y, n, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const char *xEval = (x); \ - const char *yEval = (y); \ - const size_t nEval = UTEST_CAST(size_t, n); \ - if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ - 0 != UTEST_STRNCMP(xEval, yEval, nEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, nEval), xEval); \ - UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, nEval), yEval); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_STRNEQ(x, y, n) UTEST_STRNEQ(x, y, n, "", 0) -#define EXPECT_STRNEQ_MSG(x, y, n, msg) UTEST_STRNEQ(x, y, n, msg, 0) -#define ASSERT_STRNEQ(x, y, n) UTEST_STRNEQ(x, y, n, "", 1) -#define ASSERT_STRNEQ_MSG(x, y, n, msg) UTEST_STRNEQ(x, y, n, msg, 1) - -#define UTEST_STRNNE(x, y, n, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const char *xEval = (x); \ - const char *yEval = (y); \ - const size_t nEval = UTEST_CAST(size_t, n); \ - if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ - 0 == UTEST_STRNCMP(xEval, yEval, nEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, nEval), xEval); \ - UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, nEval), yEval); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_STRNNE(x, y, n) UTEST_STRNNE(x, y, n, "", 0) -#define EXPECT_STRNNE_MSG(x, y, n, msg) UTEST_STRNNE(x, y, n, msg, 0) -#define ASSERT_STRNNE(x, y, n) UTEST_STRNNE(x, y, n, "", 1) -#define ASSERT_STRNNE_MSG(x, y, n, msg) UTEST_STRNNE(x, y, n, msg, 1) - -#define UTEST_NEAR(x, y, epsilon, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const double diff = \ - utest_fabs(UTEST_CAST(double, x) - UTEST_CAST(double, y)); \ - if (diff > UTEST_CAST(double, epsilon) || utest_isnan(diff)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : %f\n", UTEST_CAST(double, x)); \ - UTEST_PRINTF(" Actual : %f\n", UTEST_CAST(double, y)); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_NEAR(x, y, epsilon) UTEST_NEAR(x, y, epsilon, "", 0) -#define EXPECT_NEAR_MSG(x, y, epsilon, msg) UTEST_NEAR(x, y, epsilon, msg, 0) -#define ASSERT_NEAR(x, y, epsilon) UTEST_NEAR(x, y, epsilon, "", 1) -#define ASSERT_NEAR_MSG(x, y, epsilon, msg) UTEST_NEAR(x, y, epsilon, msg, 1) - -#if defined(UTEST_HAS_EXCEPTIONS) -#define UTEST_EXCEPTION(x, exception_type, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - int exception_caught = 0; \ - try { \ - x; \ - } catch (const exception_type &) { \ - exception_caught = 1; \ - } catch (...) { \ - exception_caught = 2; \ - } \ - if (1 != exception_caught) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : %s exception\n", #exception_type); \ - UTEST_PRINTF(" Actual : %s\n", (2 == exception_caught) \ - ? "Unexpected exception" \ - : "No exception"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_EXCEPTION(x, exception_type) \ - UTEST_EXCEPTION(x, exception_type, "", 0) -#define EXPECT_EXCEPTION_MSG(x, exception_type, msg) \ - UTEST_EXCEPTION(x, exception_type, msg, 0) -#define ASSERT_EXCEPTION(x, exception_type) \ - UTEST_EXCEPTION(x, exception_type, "", 1) -#define ASSERT_EXCEPTION_MSG(x, exception_type, msg) \ - UTEST_EXCEPTION(x, exception_type, msg, 1) - -#define UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, \ - msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - int exception_caught = 0; \ - char *message_caught = UTEST_NULL; \ - try { \ - x; \ - } catch (const exception_type &e) { \ - const char *const what = e.what(); \ - exception_caught = 1; \ - if (0 != \ - UTEST_STRNCMP(what, exception_message, strlen(exception_message))) { \ - const size_t message_size = strlen(what) + 1; \ - message_caught = UTEST_PTR_CAST(char *, malloc(message_size)); \ - UTEST_STRNCPY(message_caught, what, message_size); \ - } \ - } catch (...) { \ - exception_caught = 2; \ - } \ - if (1 != exception_caught) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : %s exception\n", #exception_type); \ - UTEST_PRINTF(" Actual : %s\n", (2 == exception_caught) \ - ? "Unexpected exception" \ - : "No exception"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } else if (UTEST_NULL != message_caught) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : %s exception with message %s\n", \ - #exception_type, exception_message); \ - UTEST_PRINTF(" Actual message : %s\n", message_caught); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - free(message_caught); \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message) \ - UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, "", 0) -#define EXPECT_EXCEPTION_WITH_MESSAGE_MSG(x, exception_type, \ - exception_message, msg) \ - UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, msg, 0) -#define ASSERT_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message) \ - UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, "", 1) -#define ASSERT_EXCEPTION_WITH_MESSAGE_MSG(x, exception_type, \ - exception_message, msg) \ - UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, msg, 1) -#endif - -#if defined(__clang__) -#if __has_warning("-Wunsafe-buffer-usage") -#define UTEST_SURPRESS_WARNINGS_BEGIN \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wunsafe-buffer-usage\"") -#define UTEST_SURPRESS_WARNINGS_END _Pragma("clang diagnostic pop") -#else -#define UTEST_SURPRESS_WARNINGS_BEGIN -#define UTEST_SURPRESS_WARNINGS_END -#endif -#elif defined(__GNUC__) && __GNUC__ >= 8 && defined(__cplusplus) -#define UTEST_SURPRESS_WARNINGS_BEGIN \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") -#define UTEST_SURPRESS_WARNINGS_END _Pragma("GCC diagnostic pop") -#else -#define UTEST_SURPRESS_WARNINGS_BEGIN -#define UTEST_SURPRESS_WARNINGS_END -#endif - -#define UTEST(SET, NAME) \ - UTEST_SURPRESS_WARNINGS_BEGIN \ - UTEST_EXTERN struct utest_state_s utest_state; \ - static void utest_run_##SET##_##NAME(int *utest_result); \ - static void utest_##SET##_##NAME(int *utest_result, size_t utest_index) { \ - (void)utest_index; \ - utest_run_##SET##_##NAME(utest_result); \ - } \ - UTEST_INITIALIZER(utest_register_##SET##_##NAME) { \ - const size_t index = utest_state.tests_length++; \ - const char *name_part = #SET "." #NAME; \ - const size_t name_size = strlen(name_part) + 1; \ - char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ - utest_state.tests = UTEST_PTR_CAST( \ - struct utest_test_state_s *, \ - utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ - sizeof(struct utest_test_state_s) * \ - utest_state.tests_length)); \ - if (utest_state.tests) { \ - utest_state.tests[index].func = &utest_##SET##_##NAME; \ - utest_state.tests[index].name = name; \ - utest_state.tests[index].index = 0; \ - UTEST_SNPRINTF(name, name_size, "%s", name_part); \ - } else if (name) { \ - free(name); \ - } \ - } \ - UTEST_SURPRESS_WARNINGS_END \ - void utest_run_##SET##_##NAME(int *utest_result) - -#define UTEST_F_SETUP(FIXTURE) \ - static void utest_f_setup_##FIXTURE(int *utest_result, \ - struct FIXTURE *utest_fixture) - -#define UTEST_F_TEARDOWN(FIXTURE) \ - static void utest_f_teardown_##FIXTURE(int *utest_result, \ - struct FIXTURE *utest_fixture) - -#define UTEST_F(FIXTURE, NAME) \ - UTEST_SURPRESS_WARNINGS_BEGIN \ - UTEST_EXTERN struct utest_state_s utest_state; \ - static void utest_f_setup_##FIXTURE(int *, struct FIXTURE *); \ - static void utest_f_teardown_##FIXTURE(int *, struct FIXTURE *); \ - static void utest_run_##FIXTURE##_##NAME(int *, struct FIXTURE *); \ - static void utest_f_##FIXTURE##_##NAME(int *utest_result, \ - size_t utest_index) { \ - struct FIXTURE fixture; \ - (void)utest_index; \ - memset(&fixture, 0, sizeof(fixture)); \ - utest_f_setup_##FIXTURE(utest_result, &fixture); \ - if (UTEST_TEST_PASSED != *utest_result) { \ - return; \ - } \ - utest_run_##FIXTURE##_##NAME(utest_result, &fixture); \ - utest_f_teardown_##FIXTURE(utest_result, &fixture); \ - } \ - UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME) { \ - const size_t index = utest_state.tests_length++; \ - const char *name_part = #FIXTURE "." #NAME; \ - const size_t name_size = strlen(name_part) + 1; \ - char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ - utest_state.tests = UTEST_PTR_CAST( \ - struct utest_test_state_s *, \ - utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ - sizeof(struct utest_test_state_s) * \ - utest_state.tests_length)); \ - if (utest_state.tests) { \ - utest_state.tests[index].func = &utest_f_##FIXTURE##_##NAME; \ - utest_state.tests[index].name = name; \ - UTEST_SNPRINTF(name, name_size, "%s", name_part); \ - } else if (name) { \ - free(name); \ - } \ - } \ - UTEST_SURPRESS_WARNINGS_END \ - void utest_run_##FIXTURE##_##NAME(int *utest_result, \ - struct FIXTURE *utest_fixture) - -#define UTEST_I_SETUP(FIXTURE) \ - static void utest_i_setup_##FIXTURE( \ - int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) - -#define UTEST_I_TEARDOWN(FIXTURE) \ - static void utest_i_teardown_##FIXTURE( \ - int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) - -#define UTEST_I(FIXTURE, NAME, INDEX) \ - UTEST_SURPRESS_WARNINGS_BEGIN \ - UTEST_EXTERN struct utest_state_s utest_state; \ - static void utest_run_##FIXTURE##_##NAME##_##INDEX(int *, struct FIXTURE *); \ - static void utest_i_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ - size_t index) { \ - struct FIXTURE fixture; \ - memset(&fixture, 0, sizeof(fixture)); \ - utest_i_setup_##FIXTURE(utest_result, &fixture, index); \ - if (UTEST_TEST_PASSED != *utest_result) { \ - return; \ - } \ - utest_run_##FIXTURE##_##NAME##_##INDEX(utest_result, &fixture); \ - utest_i_teardown_##FIXTURE(utest_result, &fixture, index); \ - } \ - UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME##_##INDEX) { \ - size_t i; \ - utest_uint64_t iUp; \ - for (i = 0; i < (INDEX); i++) { \ - const size_t index = utest_state.tests_length++; \ - const char *name_part = #FIXTURE "." #NAME; \ - const size_t name_size = strlen(name_part) + 32; \ - char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ - utest_state.tests = UTEST_PTR_CAST( \ - struct utest_test_state_s *, \ - utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ - sizeof(struct utest_test_state_s) * \ - utest_state.tests_length)); \ - if (utest_state.tests) { \ - utest_state.tests[index].func = &utest_i_##FIXTURE##_##NAME##_##INDEX; \ - utest_state.tests[index].index = i; \ - utest_state.tests[index].name = name; \ - iUp = UTEST_CAST(utest_uint64_t, i); \ - UTEST_SNPRINTF(name, name_size, "%s/%" UTEST_PRIu64, name_part, iUp); \ - } else if (name) { \ - free(name); \ - } \ - } \ - } \ - UTEST_SURPRESS_WARNINGS_END \ - void utest_run_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ - struct FIXTURE *utest_fixture) - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -UTEST_WEAK -double utest_fabs(double d); -UTEST_WEAK -double utest_fabs(double d) { - union { - double d; - utest_uint64_t u; - } both; - both.d = d; - both.u &= 0x7fffffffffffffffu; - return both.d; -} - -UTEST_WEAK -int utest_isnan(double d); -UTEST_WEAK -int utest_isnan(double d) { - union { - double d; - utest_uint64_t u; - } both; - both.d = d; - both.u &= 0x7fffffffffffffffu; - return both.u > 0x7ff0000000000000u; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#if defined(__clang__) -#if __has_warning("-Wunsafe-buffer-usage") -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" -#endif -#endif - -UTEST_WEAK -int utest_should_filter_test(const char *filter, const char *testcase); -UTEST_WEAK int utest_should_filter_test(const char *filter, - const char *testcase) { - if (filter) { - const char *filter_cur = filter; - const char *testcase_cur = testcase; - const char *filter_wildcard = UTEST_NULL; - - while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { - if ('*' == *filter_cur) { - /* store the position of the wildcard */ - filter_wildcard = filter_cur; - - /* skip the wildcard character */ - filter_cur++; - - while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { - if ('*' == *filter_cur) { - /* - we found another wildcard (filter is something like *foo*) so we - exit the current loop, and return to the parent loop to handle - the wildcard case - */ - break; - } else if (*filter_cur != *testcase_cur) { - /* otherwise our filter didn't match, so reset it */ - filter_cur = filter_wildcard; - } - - /* move testcase along */ - testcase_cur++; - - /* move filter along */ - filter_cur++; - } - - if (('\0' == *filter_cur) && ('\0' == *testcase_cur)) { - return 0; - } - - /* if the testcase has been exhausted, we don't have a match! */ - if ('\0' == *testcase_cur) { - return 1; - } - } else { - if (*testcase_cur != *filter_cur) { - /* test case doesn't match filter */ - return 1; - } else { - /* move our filter and testcase forward */ - testcase_cur++; - filter_cur++; - } - } - } - - if (('\0' != *filter_cur) || - (('\0' != *testcase_cur) && - ((filter == filter_cur) || ('*' != filter_cur[-1])))) { - /* we have a mismatch! */ - return 1; - } - } - - return 0; -} - -static UTEST_INLINE FILE *utest_fopen(const char *filename, const char *mode) { -#ifdef _MSC_VER - FILE *file; - if (0 == fopen_s(&file, filename, mode)) { - return file; - } else { - return UTEST_NULL; - } -#else - return fopen(filename, mode); -#endif -} - -static UTEST_INLINE int utest_main(int argc, const char *const argv[]); -int utest_main(int argc, const char *const argv[]) { - utest_uint64_t failed = 0; - utest_uint64_t skipped = 0; - size_t index = 0; - size_t *failed_testcases = UTEST_NULL; - size_t failed_testcases_length = 0; - size_t *skipped_testcases = UTEST_NULL; - size_t skipped_testcases_length = 0; - const char *filter = UTEST_NULL; - utest_uint64_t ran_tests = 0; - int enable_mixed_units = 0; - int random_order = 0; - utest_uint32_t seed = 0; - - enum colours { RESET, GREEN, RED, YELLOW }; - - const int use_colours = UTEST_COLOUR_OUTPUT(); - const char *colours[] = {"\033[0m", "\033[32m", "\033[31m", "\033[33m"}; - - if (!use_colours) { - for (index = 0; index < sizeof colours / sizeof colours[0]; index++) { - colours[index] = ""; - } - } - /* loop through all arguments looking for our options */ - for (index = 1; index < UTEST_CAST(size_t, argc); index++) { - /* Informational switches */ - const char help_str[] = "--help"; - const char list_str[] = "--list-tests"; - /* Test config switches */ - const char filter_str[] = "--filter="; - const char output_str[] = "--output="; - const char enable_mixed_units_str[] = "--enable-mixed-units"; - const char random_order_str[] = "--random-order"; - const char random_order_with_seed_str[] = "--random-order="; - - if (0 == UTEST_STRNCMP(argv[index], help_str, strlen(help_str))) { - printf("utest.h - the single file unit testing solution for C/C++!\n" - "Command line Options:\n" - " --help Show this message and exit.\n" - " --filter= Filter the test cases to run (EG. " - "MyTest*.a would run MyTestCase.a but not MyTestCase.b).\n" - " --list-tests List testnames, one per line. Output " - "names can be passed to --filter.\n"); - printf(" --output= Output an xunit XML file to the file " - "specified in .\n" - " --enable-mixed-units Enable the per-test output to contain " - "mixed units (s/ms/us/ns).\n" - " --random-order[=] Randomize the order that the tests are " - "ran in. If the optional argument is not provided, then a " - "random starting seed is used.\n"); - goto cleanup; - } else if (0 == - UTEST_STRNCMP(argv[index], filter_str, strlen(filter_str))) { - /* user wants to filter what test cases run! */ - filter = argv[index] + strlen(filter_str); - } else if (0 == - UTEST_STRNCMP(argv[index], output_str, strlen(output_str))) { - utest_state.output = utest_fopen(argv[index] + strlen(output_str), "w+"); - } else if (0 == UTEST_STRNCMP(argv[index], list_str, strlen(list_str))) { - for (index = 0; index < utest_state.tests_length; index++) { - UTEST_PRINTF("%s\n", utest_state.tests[index].name); - } - /* when printing the test list, don't actually run the tests */ - return 0; - } else if (0 == UTEST_STRNCMP(argv[index], enable_mixed_units_str, - strlen(enable_mixed_units_str))) { - enable_mixed_units = 1; - } else if (0 == UTEST_STRNCMP(argv[index], random_order_with_seed_str, - strlen(random_order_with_seed_str))) { - seed = - UTEST_CAST(utest_uint32_t, - strtoul(argv[index] + strlen(random_order_with_seed_str), - UTEST_NULL, 10)); - random_order = 1; - } else if (0 == UTEST_STRNCMP(argv[index], random_order_str, - strlen(random_order_str))) { - const utest_int64_t ns = utest_ns(); - - // Some really poor pseudo-random using the current time. I do this - // because I really want to avoid using C's rand() because that'd mean our - // random would be affected by any srand() usage by the user (which I - // don't want). - seed = UTEST_CAST(utest_uint32_t, ns >> 32) * 31 + - UTEST_CAST(utest_uint32_t, ns & 0xffffffff); - random_order = 1; - } - } - - if (random_order) { - // Use Fisher-Yates with the Durstenfield's version to randomly re-order the - // tests. - for (index = utest_state.tests_length; index > 1; index--) { - // For the random order we'll use PCG. - const utest_uint32_t state = seed; - const utest_uint32_t word = - ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; - const utest_uint32_t next = - ((word >> 22u) ^ word) % UTEST_CAST(utest_uint32_t, index); - - // Swap the randomly chosen element into the last location. - const struct utest_test_state_s copy = utest_state.tests[index - 1]; - utest_state.tests[index - 1] = utest_state.tests[next]; - utest_state.tests[next] = copy; - - // Move the seed onwards. - seed = seed * 747796405u + 2891336453u; - } - } - - for (index = 0; index < utest_state.tests_length; index++) { - if (utest_should_filter_test(filter, utest_state.tests[index].name)) { - continue; - } - - ran_tests++; - } - - printf("%s[==========]%s Running %" UTEST_PRIu64 " test cases.\n", - colours[GREEN], colours[RESET], UTEST_CAST(utest_uint64_t, ran_tests)); - - if (utest_state.output) { - fprintf(utest_state.output, "\n"); - fprintf(utest_state.output, - "\n", - UTEST_CAST(utest_uint64_t, ran_tests)); - fprintf(utest_state.output, - "\n", - UTEST_CAST(utest_uint64_t, ran_tests)); - } - - for (index = 0; index < utest_state.tests_length; index++) { - int result = UTEST_TEST_PASSED; - utest_int64_t ns = 0; - - if (utest_should_filter_test(filter, utest_state.tests[index].name)) { - continue; - } - - printf("%s[ RUN ]%s %s\n", colours[GREEN], colours[RESET], - utest_state.tests[index].name); - - if (utest_state.output) { - fprintf(utest_state.output, "", - utest_state.tests[index].name); - } - - ns = utest_ns(); - errno = 0; -#if defined(UTEST_HAS_EXCEPTIONS) - UTEST_SURPRESS_WARNING_BEGIN - try { - utest_state.tests[index].func(&result, utest_state.tests[index].index); - } catch (const std::exception &err) { - printf(" Exception : %s\n", err.what()); - result = UTEST_TEST_FAILURE; - } catch (...) { - printf(" Exception : Unknown\n"); - result = UTEST_TEST_FAILURE; - } - UTEST_SURPRESS_WARNING_END -#else - utest_state.tests[index].func(&result, utest_state.tests[index].index); -#endif - ns = utest_ns() - ns; - - if (utest_state.output) { - fprintf(utest_state.output, "\n"); - } - - // Record the failing test. - if (UTEST_TEST_FAILURE == result) { - const size_t failed_testcase_index = failed_testcases_length++; - failed_testcases = UTEST_PTR_CAST( - size_t *, utest_realloc(UTEST_PTR_CAST(void *, failed_testcases), - sizeof(size_t) * failed_testcases_length)); - if (UTEST_NULL != failed_testcases) { - failed_testcases[failed_testcase_index] = index; - } - failed++; - } else if (UTEST_TEST_SKIPPED == result) { - const size_t skipped_testcase_index = skipped_testcases_length++; - skipped_testcases = UTEST_PTR_CAST( - size_t *, utest_realloc(UTEST_PTR_CAST(void *, skipped_testcases), - sizeof(size_t) * skipped_testcases_length)); - if (UTEST_NULL != skipped_testcases) { - skipped_testcases[skipped_testcase_index] = index; - } - skipped++; - } - - { - const char *const units[] = {"ns", "us", "ms", "s", UTEST_NULL}; - unsigned int unit_index = 0; - utest_int64_t time = ns; - - if (enable_mixed_units) { - for (unit_index = 0; UTEST_NULL != units[unit_index]; unit_index++) { - if (10000 > time) { - break; - } - - time /= 1000; - } - } - - if (UTEST_TEST_FAILURE == result) { - printf("%s[ FAILED ]%s %s (%" UTEST_PRId64 "%s)\n", colours[RED], - colours[RESET], utest_state.tests[index].name, time, - units[unit_index]); - } else if (UTEST_TEST_SKIPPED == result) { - printf("%s[ SKIPPED ]%s %s (%" UTEST_PRId64 "%s)\n", colours[YELLOW], - colours[RESET], utest_state.tests[index].name, time, - units[unit_index]); - } else { - printf("%s[ OK ]%s %s (%" UTEST_PRId64 "%s)\n", colours[GREEN], - colours[RESET], utest_state.tests[index].name, time, - units[unit_index]); - } - } - } - - printf("%s[==========]%s %" UTEST_PRIu64 " test cases ran.\n", colours[GREEN], - colours[RESET], ran_tests); - printf("%s[ PASSED ]%s %" UTEST_PRIu64 " tests.\n", colours[GREEN], - colours[RESET], ran_tests - failed - skipped); - - if (0 != skipped) { - printf("%s[ SKIPPED ]%s %" UTEST_PRIu64 " tests, listed below:\n", - colours[YELLOW], colours[RESET], skipped); - for (index = 0; index < skipped_testcases_length; index++) { - printf("%s[ SKIPPED ]%s %s\n", colours[YELLOW], colours[RESET], - utest_state.tests[skipped_testcases[index]].name); - } - } - - if (0 != failed) { - printf("%s[ FAILED ]%s %" UTEST_PRIu64 " tests, listed below:\n", - colours[RED], colours[RESET], failed); - for (index = 0; index < failed_testcases_length; index++) { - printf("%s[ FAILED ]%s %s\n", colours[RED], colours[RESET], - utest_state.tests[failed_testcases[index]].name); - } - } - - if (utest_state.output) { - fprintf(utest_state.output, "\n\n"); - } - -cleanup: - for (index = 0; index < utest_state.tests_length; index++) { - free(UTEST_PTR_CAST(void *, utest_state.tests[index].name)); - } - - free(UTEST_PTR_CAST(void *, skipped_testcases)); - free(UTEST_PTR_CAST(void *, failed_testcases)); - free(UTEST_PTR_CAST(void *, utest_state.tests)); - - if (utest_state.output) { - fclose(utest_state.output); - } - - return UTEST_CAST(int, failed); -} - -#if defined(__clang__) -#if __has_warning("-Wunsafe-buffer-usage") -#pragma clang diagnostic pop -#endif -#endif - -/* - we need, in exactly one source file, define the global struct that will hold - the data we need to run utest. This macro allows the user to declare the - data without having to use the UTEST_MAIN macro, thus allowing them to write - their own main() function. -*/ -#define UTEST_STATE() struct utest_state_s utest_state = {0, 0, 0} - -/* - define a main() function to call into utest.h and start executing tests! A - user can optionally not use this macro, and instead define their own main() - function and manually call utest_main. The user must, in exactly one source - file, use the UTEST_STATE macro to declare a global struct variable that - utest requires. -*/ -#define UTEST_MAIN() \ - UTEST_STATE(); \ - int main(int argc, const char *const argv[]) { \ - return utest_main(argc, argv); \ - } - -#endif /* SHEREDOM_UTEST_H_INCLUDED */ diff --git a/lab-4/Makefile b/lab-4/Makefile deleted file mode 100644 index 9e6ede1..0000000 --- a/lab-4/Makefile +++ /dev/null @@ -1,29 +0,0 @@ - -# The top level rule indicates how to link everything together into main - -main: main.o scanner.o parser.o - gcc main.o scanner.o parser.o -o parser.out -lm - -test: main_test.o scanner.o parser.o - gcc main_test.o scanner.o parser.o -o parser_test.out -lm - -# Only the files generated by flex and bison need explicit rules. - -scanner.c: scanner.flex parser.h - flex -oscanner.c scanner.flex - -parser.c parser.h: parser.bison - bison --defines=token.h --output=parser.c -v parser.bison - -# This pattern indicates that any .o file depends -# upon the .c file of the same name, and all of the .h files. -# So, if a .o file is needed, it is built automatically. - -%.o: %.c *.h - gcc -Wall -c $< -o $@ - -# clean causes all intermediate files to be deleted. - -clean: - rm -f parser.c parser.output token.h scanner.c *.o parser.out parser_test.out - diff --git a/lab-4/README.md b/lab-4/README.md deleted file mode 100644 index b2d23a0..0000000 --- a/lab-4/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# Bison Parser With Tests - -Create a scanner for your sample programs with tests. -The tests should include basic statements and the sample files for your language. -See the [example lab for Python](https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab-python). - -## Build Process - -To build the `scanner.c` run the following **flex** command. - -```sh -flex -o scanner.c scanner.flex -``` - -The parser is built using **bison**. -Note this command also builds the `token.h`. - -```sh -bison --defines=token.h --output=parser.c -v parser.bison -``` - -THe `-v` flag will create a `parser.output` which represents the grammar in text form. - -### Running the Parser - -Then build the `main.c`, `parcer.c` and `scanner.c` using **gcc**. -Note that you may get a few warnings that can be ignored. - -```sh -gcc main.c scanner.c parser.c -o parser.out -``` - -Then execute the test suite using `./parser.out` and pass in the input from your sample program. -For example here is a command for `samples/program.c` - -```sh -./parser.out < samples/program.c -``` - -### Testing the Parser - -Then build the `main_test.c`, `parcer.c` and `scanner.c` using **gcc**. -Note that you may get a few warnings that can be ignored. - -```sh -gcc main_test.c scanner.c parser.c -o parser_test.out -``` - -Then execute the test suite using `./parser_test.out`. - -```sh -./parser_test.out -``` - -### Using Make - -Alternatively you can use the supplied make file. - -- Build main program - `make` -- Build test program - `make test` -- Clean up build files - `make clean` - -## Tests - -- Write test for various statements in your language - - assignment - Riley - - print - Josh (write test) - - mathmatical expressions - Jenessy - - boolean expressions - Jenessy - - branching - Josh - - looping - Riley -- Write a test for each sample test file. - - Hello World! - Josh (already done) - - Quadratic - Jenessy - - Sorting - Riley - -## Grading Rubric - -The grading will be over the following categories. - -Points Description - ---- - -60 points Ability to parse — Six different language statements -10 points Ability to parse — Hello world -10 points Ability to parse — Quadratic equation -10 points Ability to parse — Integer sorting -10 points Report formatting and readability - -## Turn In - -Please submit the URL of your gitlab project to D2L's Brightspace with your report. -On gitlab update the `lab-4` folder to have your report and code snippets before the due date. diff --git a/lab-4/main.c b/lab-4/main.c deleted file mode 100644 index d0ab871..0000000 --- a/lab-4/main.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -extern int yyparse(); - -int main() { - if (yyparse() == 0) { - printf("Parse successful!\n"); - } else { - printf("Parse failed.\n"); - } -} diff --git a/lab-4/main_test.c b/lab-4/main_test.c deleted file mode 100644 index 2a8af21..0000000 --- a/lab-4/main_test.c +++ /dev/null @@ -1,122 +0,0 @@ -// https://github.com/sheredom/utest.h/blob/master/utest.h -#include "utest.h" -#include - -extern int yyparse(); - -typedef struct yy_buffer_state *YY_BUFFER_STATE; -extern int yyrestart(); -extern YY_BUFFER_STATE yy_scan_buffer(char *str, int i); -extern YY_BUFFER_STATE yy_scan_string(char *str); -extern void yy_delete_buffer(YY_BUFFER_STATE buffer); -extern FILE *yyin; -extern int yylineno; - -UTEST_MAIN(); - -UTEST(parser, math) { - // Must include the null character to terminate input - char string[] = "COMPUTE A = (b ** 2) - (4 * a * c)\0"; - YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); - - yylineno = 1; - int result = yyparse(); - - yy_delete_buffer(buffer); - - // Assert the result to test correctness - ASSERT_EQ(result, 0); -} - -UTEST(parser, hello) { - // Read sample file as input - yyin = fopen("samples/hello-world.cbl", "r"); - yyrestart(yyin); - ASSERT_TRUE(yyin); - - yylineno = 1; - int result = yyparse(); - - // Assert the result to test correctness - ASSERT_EQ(result, 0); -} - -UTEST(parser, print) { - // Must include the null character to terminate input - char string[] = "DISPLAY 'Hello World!'\0"; - YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); - - yylineno = 1; - int result = yyparse(); - - yy_delete_buffer(buffer); - - // Assert the result to test correctness - ASSERT_EQ(result, 0); -} - -UTEST(parser, branching) { - // Must include the null character to terminate input - char string[] = "IF A > B DISPLAY 'A is greater than B' ELSE DISPLAY 'B is greater than A'\0"; - YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); - - yylineno = 1; - int result = yyparse(); - - yy_delete_buffer(buffer); - - // Assert the result to test correctness - ASSERT_EQ(result, 0); -} - -UTEST(parser, looping) { - char string[] = "PERFORM VARYING I FROM 1 BY 1 UNTIL I > 10\0"; - YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); - - yylineno = 1; - int result = yyparse(); - - yy_delete_buffer(buffer); - - // Assert the result to test correctness - ASSERT_EQ(result, 0); -} - -UTEST(parser, assignment) { - char string[] = "MOVE I TO A(I) MOVE 1 TO I COMPUTE discriminant = (b ** 2) - (4 * a * c)\0"; - YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string)); - - yylineno = 1; - int result = yyparse(); - - yy_delete_buffer(buffer); - - // Assert the result to test correctness - ASSERT_EQ(result, 0); -} - -UTEST(parser, sorting) { - // Read sample file as input - yyin = fopen("samples/sorting-snippet.cbl", "r"); - yyrestart(yyin); - ASSERT_TRUE(yyin); - - yylineno = 1; - int result = yyparse(); - - // Assert the result to test correctness - ASSERT_EQ(result, 0); -} - -UTEST(parser, quadratic) { - // Read sample file as input - yyin = fopen("samples/quadratic-snippet.cbl", "r"); - yyrestart(yyin); - ASSERT_TRUE(yyin); - - yylineno = 1; - int result = yyparse(); - - // Assert the result to test correctness - ASSERT_EQ(result, 0); -} diff --git a/lab-4/parser.bison b/lab-4/parser.bison deleted file mode 100644 index 2585a15..0000000 --- a/lab-4/parser.bison +++ /dev/null @@ -1,190 +0,0 @@ -%{ -#define YYDEBUG 1 -#include -extern int yylineno; -void yyerror(const char*); -int yylex(); -%} - -%debug -%define parse.error detailed - -%token TOKEN_ADD -%token TOKEN_ALPHANUMERIC -%token TOKEN_COMPUTATION_LEVEL_0 -%token TOKEN_COMPUTATION_LEVEL_1 -%token TOKEN_COMPUTATION_LEVEL_2 -%token TOKEN_COMPUTATION_LEVEL_3 -%token TOKEN_DISPLAY -%token TOKEN_DIVIDE -%token TOKEN_DOT -%token TOKEN_ELSE -%token TOKEN_ELSE_IF -%token TOKEN_END_IF -%token TOKEN_END_PERFORM -%token TOKEN_EQUAL -%token TOKEN_EXPONENTIAL -%token TOKEN_GREATER_THAN -%token TOKEN_IDENT -%token TOKEN_IF -%token TOKEN_IMPLIED_DECIMAL -%token TOKEN_INTEGER -%token TOKEN_KEYWORD_BY -%token TOKEN_KEYWORD_COMPUTE -%token TOKEN_KEYWORD_DATA -%token TOKEN_KEYWORD_DIVISION -%token TOKEN_KEYWORD_FROM -%token TOKEN_KEYWORD_FUNCTION -%token TOKEN_KEYWORD_IDENTIFICATION -%token TOKEN_KEYWORD_OCCURS -%token TOKEN_KEYWORD_SECTION -%token TOKEN_KEYWORD_TO -%token TOKEN_KEYWORD_VALUE -%token TOKEN_LEFT_PARENTHESIS -%token TOKEN_LESS_THAN -%token TOKEN_MOVE -%token TOKEN_MULTIPLY -%token TOKEN_NUMERIC -%token TOKEN_PERFORM -%token TOKEN_PICTURE -%token TOKEN_PROGRAM_ID -%token TOKEN_PROCEDURE -%token TOKEN_RIGHT_PARENTHESIS -%token TOKEN_RUN -%token TOKEN_SIGNED_NUMERIC -%token TOKEN_SPACE -%token TOKEN_STOP -%token TOKEN_STRING -%token TOKEN_SUB -%token TOKEN_UNTIL -%token TOKEN_VARYING -%token TOKEN_WORKING_STORAGE -%token TOKEN_EOF - - - -%% -file : statements -statements : statement_list - ; -statement_list : statement_list statement - | statement - ; -statement : section - | sect_data - | simple_stmt - | data_space - | data_declaration - ; - -section : type TOKEN_KEYWORD_DIVISION TOKEN_DOT - | type TOKEN_RUN TOKEN_DOT - ; -sect_data : TOKEN_PROGRAM_ID TOKEN_DOT TOKEN_IDENT TOKEN_DOT - ; -type : TOKEN_KEYWORD_IDENTIFICATION - | TOKEN_PROCEDURE - | TOKEN_STOP - | TOKEN_KEYWORD_DATA - ; -simple_stmt : cbl_func_stmt - | if_branch - | else_parts - | perform_stmt - ; -cbl_func_stmt : cbl_function - | cbl_function op_parms - | cbl_function assignment_stmt - | cbl_function op_parm assignment_stmt - ; -assignment_stmt : TOKEN_EQUAL op_parms - | TOKEN_KEYWORD_TO op_parms - ; -op_parms : op_parm - | op_parms op_parm - ; -op_parm : mathmaticalexpr - | booleanexpr - ; -term : mathmaticalexpr - ; -math_op : TOKEN_ADD - | TOKEN_SUB - | TOKEN_MULTIPLY - | TOKEN_DIVIDE - | TOKEN_EXPONENTIAL - ; -mathmaticalexpr : type_expr - | mathmaticalexpr math_op term - | container_expr - | type_expr container_expr - ; -container_expr : TOKEN_LEFT_PARENTHESIS mathmaticalexpr TOKEN_RIGHT_PARENTHESIS - ; -booleanexpr : mathmaticalexpr TOKEN_LESS_THAN term - | mathmaticalexpr TOKEN_GREATER_THAN term - | mathmaticalexpr TOKEN_EQUAL term - ; -type_expr : TOKEN_IDENT - | TOKEN_INTEGER - | TOKEN_STRING - | TOKEN_SPACE - | TOKEN_SUB TOKEN_IDENT - | ext_function - ; -ext_function : TOKEN_KEYWORD_FUNCTION TOKEN_IDENT TOKEN_LEFT_PARENTHESIS TOKEN_IDENT TOKEN_RIGHT_PARENTHESIS - ; -cbl_function : TOKEN_DISPLAY - | TOKEN_MOVE - | TOKEN_KEYWORD_COMPUTE - ; -if_branch : TOKEN_IF booleanexpr - ; -else_parts : TOKEN_ELSE_IF booleanexpr simple_stmt - | TOKEN_ELSE simple_stmt - | TOKEN_END_IF - ; -perform_stmt : TOKEN_PERFORM TOKEN_VARYING TOKEN_IDENT TOKEN_KEYWORD_FROM TOKEN_INTEGER TOKEN_KEYWORD_BY TOKEN_INTEGER TOKEN_UNTIL op_parms - | TOKEN_END_PERFORM - ; -data_space : TOKEN_WORKING_STORAGE TOKEN_KEYWORD_SECTION TOKEN_DOT - ; -data_category : TOKEN_ALPHANUMERIC - | TOKEN_NUMERIC - | TOKEN_SIGNED_NUMERIC - | TOKEN_IMPLIED_DECIMAL - ; -categry_contain : TOKEN_LEFT_PARENTHESIS TOKEN_INTEGER TOKEN_RIGHT_PARENTHESIS - | TOKEN_LEFT_PARENTHESIS TOKEN_IDENT TOKEN_RIGHT_PARENTHESIS - ; -complete_category: data_category categry_contain - | data_category categry_contain complete_category - ; -data_clause : TOKEN_COMPUTATION_LEVEL_0 - | TOKEN_COMPUTATION_LEVEL_1 - | TOKEN_COMPUTATION_LEVEL_2 - | TOKEN_COMPUTATION_LEVEL_3 - | TOKEN_KEYWORD_VALUE - | TOKEN_KEYWORD_OCCURS - ; -full_data_clause: data_clause data_clause - | data_clause - ; -simple_decl : TOKEN_INTEGER TOKEN_IDENT TOKEN_DOT - ; -complex_decl : TOKEN_INTEGER TOKEN_IDENT TOKEN_PICTURE category_spec TOKEN_DOT - ; -category_spec : complete_category - | complete_category data_clauses - ; -data_clauses : full_data_clause - | full_data_clause TOKEN_INTEGER - ; -data_declaration: simple_decl - | complex_decl - ; - -%% -void yyerror(const char* msg) { - fprintf(stderr, "Error | Line: %d\n%s\n",yylineno,msg); -} diff --git a/lab-4/samples/hello-world.cbl b/lab-4/samples/hello-world.cbl deleted file mode 100644 index 737f19e..0000000 --- a/lab-4/samples/hello-world.cbl +++ /dev/null @@ -1,5 +0,0 @@ -IDENTIFICATION DIVISION. -PROGRAM-ID. HELLO-WORLD. -PROCEDURE DIVISION. - DISPLAY 'Hello World!' -STOP RUN. diff --git a/lab-4/samples/quadratic-snippet.cbl b/lab-4/samples/quadratic-snippet.cbl deleted file mode 100644 index 7f27b4d..0000000 --- a/lab-4/samples/quadratic-snippet.cbl +++ /dev/null @@ -1,33 +0,0 @@ - *> Code altered from https://www.quora.com/What-is-a-COBOL-program-that-will-solve-a-quadratic-equation - *> Program finds the roots to a simple quadratic equation - - IDENTIFICATION DIVISION. - PROGRAM-ID. QuadraticSolver. - DATA DIVISION. - WORKING-STORAGE SECTION. - 77 a PIC S9(5)V9(5) COMP-3 VALUE 1. - 77 b PIC S9(5)V9(5) COMP-3 VALUE 5. - 77 c PIC S9(5)V9(5) COMP-3 VALUE 6. - 77 discriminant PIC S9(5)V9(5) COMP-3. - 77 root1 PIC S9(5)V9(5) COMP-3. - 77 root2 PIC S9(5)V9(5) COMP-3. - 77 square-root-discriminant PIC S9(5)V9(5) COMP-3. - - PROCEDURE DIVISION. *> program begins here - DISPLAY "EQUATION: (1x^2) + 5x + 6 = 0" - COMPUTE discriminant = (b ** 2) - (4 * a * c) - - IF discriminant > 0 - COMPUTE square-root-discriminant = FUNCTION SQRT(discriminant) - COMPUTE root1 = (-b + square-root-discriminant) / (2 * a) - COMPUTE root2 = (-b - square-root-discriminant) / (2 * a) - DISPLAY "The equation has two distinct real roots: " - DISPLAY "Root 1: " root1 - DISPLAY "Root 2: " root2 - ELSE IF discriminant = 0 - COMPUTE root1 = -b / (2 * a) - DISPLAY "The equation has one real root: " - DISPLAY "Root: " root1 - ELSE - DISPLAY "The equation has no real roots." - STOP RUN. diff --git a/lab-4/samples/sorting-snippet.cbl b/lab-4/samples/sorting-snippet.cbl deleted file mode 100644 index 7019d00..0000000 --- a/lab-4/samples/sorting-snippet.cbl +++ /dev/null @@ -1,54 +0,0 @@ -IDENTIFICATION DIVISION. -PROGRAM-ID. sorting. -DATA DIVISION. -WORKING-STORAGE SECTION. - 01 WS-SORT-AREA. - 05 WS-SORT-TABLE. - 10 WS-SORT-ROW PIC X(10) OCCURS 100. - 05 WS-TEMP-ROW PIC X(10). - 05 WS-ROW-MAX PIC S9(4) COMP VALUE 100. - 05 WS-SORT-MAX PIC S9(4) COMP. - 05 WS-I PIC S9(4) COMP. - 05 WS-J PIC S9(4) COMP. - 05 WS-INDEX PIC S9(4) COMP. - -PROCEDURE DIVISION. -*> Initialize test data - MOVE "30" TO WS-SORT-ROW(1) - MOVE "10" TO WS-SORT-ROW(2) - MOVE "50" TO WS-SORT-ROW(3) - MOVE "20" TO WS-SORT-ROW(4) - MOVE "40" TO WS-SORT-ROW(5) - MOVE 5 TO WS-SORT-MAX - -*> * Display original array - DISPLAY "Original Array Contents:" - DISPLAY "---------------------" - PERFORM VARYING WS-INDEX FROM 1 BY 1 - UNTIL WS-INDEX > WS-SORT-MAX - DISPLAY "Element " WS-INDEX ": " WS-SORT-ROW(WS-INDEX) - END-PERFORM - DISPLAY SPACE - -*> * Simplified bubble sort - PERFORM VARYING WS-I FROM 1 BY 1 - UNTIL WS-I > WS-SORT-MAX - 1 - PERFORM VARYING WS-J FROM 1 BY 1 - UNTIL WS-J > WS-SORT-MAX - WS-I - IF WS-SORT-ROW(WS-J) > WS-SORT-ROW(WS-J + 1) - MOVE WS-SORT-ROW(WS-J) TO WS-TEMP-ROW - MOVE WS-SORT-ROW(WS-J + 1) TO WS-SORT-ROW(WS-J) - MOVE WS-TEMP-ROW TO WS-SORT-ROW(WS-J + 1) - END-PERFORM - END-PERFORM - -*> * Display sorted array - DISPLAY "Sorted Array Contents:" - DISPLAY "--------------------" - PERFORM VARYING WS-INDEX FROM 1 BY 1 - UNTIL WS-INDEX > WS-SORT-MAX - DISPLAY "Element " WS-INDEX ": " WS-SORT-ROW(WS-INDEX) - END-PERFORM - - STOP RUN. - \ No newline at end of file diff --git a/lab-4/scanner.flex b/lab-4/scanner.flex deleted file mode 100644 index 4b7a148..0000000 --- a/lab-4/scanner.flex +++ /dev/null @@ -1,64 +0,0 @@ -%{ -#include "token.h" -%} -NAME [a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])? -DIGIT [0-9]+ -%% - -(" "|\t|\n) /* skip whitespace */ -\*>\ ?.* -IDENTIFICATION { return TOKEN_KEYWORD_IDENTIFICATION; } -DIVISION { return TOKEN_KEYWORD_DIVISION; } -PROGRAM-ID { return TOKEN_PROGRAM_ID; } -PROCEDURE { return TOKEN_PROCEDURE; } -DATA { return TOKEN_KEYWORD_DATA; } -SECTION { return TOKEN_KEYWORD_SECTION; } -WORKING-STORAGE { return TOKEN_WORKING_STORAGE; } -DISPLAY { return TOKEN_DISPLAY; } -STOP { return TOKEN_STOP; } -RUN { return TOKEN_RUN; } -MOVE { return TOKEN_MOVE; } -TO { return TOKEN_KEYWORD_TO; } -VARYING { return TOKEN_VARYING; } -FROM { return TOKEN_KEYWORD_FROM; } -BY { return TOKEN_KEYWORD_BY; } -UNTIL { return TOKEN_UNTIL; } -PERFORM { return TOKEN_PERFORM; } -END-PERFORM { return TOKEN_END_PERFORM; } -IF { return TOKEN_IF; } -END-IF { return TOKEN_END_IF; } -SPACE { return TOKEN_SPACE; } -PIC { return TOKEN_PICTURE; } -OCCURS { return TOKEN_KEYWORD_OCCURS; } -VALUE { return TOKEN_KEYWORD_VALUE; } -COMPUTE { return TOKEN_KEYWORD_COMPUTE; } -FUNCTION { return TOKEN_KEYWORD_FUNCTION; } -X { return TOKEN_ALPHANUMERIC; } -S9 { return TOKEN_SIGNED_NUMERIC; } -9 { return TOKEN_NUMERIC; } -V9 { return TOKEN_IMPLIED_DECIMAL; } -COMP { return TOKEN_COMPUTATION_LEVEL_0; } -COMP-1 { return TOKEN_COMPUTATION_LEVEL_1; } -COMP-2 { return TOKEN_COMPUTATION_LEVEL_2; } -COMP-3 { return TOKEN_COMPUTATION_LEVEL_3; } - -{DIGIT} { return TOKEN_INTEGER; } -{NAME} { return TOKEN_IDENT; } -\+ { return TOKEN_ADD; } -\- { return TOKEN_SUB; } -\*\* { return TOKEN_EXPONENTIAL; } -\* { return TOKEN_MULTIPLY; } -\/ { return TOKEN_DIVIDE; } -\> { return TOKEN_GREATER_THAN; } -\< { return TOKEN_LESS_THAN; } -\= { return TOKEN_EQUAL;} - -"\""[^"]*"\"" { return TOKEN_STRING; } -"\'"[^']*"\'" { return TOKEN_STRING; } -"(" { return TOKEN_LEFT_PARENTHESIS; } -")" { return TOKEN_RIGHT_PARENTHESIS; } - -\. { return TOKEN_DOT; } - -%% -int yywrap() { return 1; } diff --git a/lab-4/utest.h b/lab-4/utest.h deleted file mode 100644 index 8767600..0000000 --- a/lab-4/utest.h +++ /dev/null @@ -1,1668 +0,0 @@ -/* - The latest version of this library is available on GitHub; - https://github.com/sheredom/utest.h -*/ - -/* - This is free and unencumbered software released into the public domain. - - Anyone is free to copy, modify, publish, use, compile, sell, or - distribute this software, either in source code form or as a compiled - binary, for any purpose, commercial or non-commercial, and by any - means. - - In jurisdictions that recognize copyright laws, the author or authors - of this software dedicate any and all copyright interest in the - software to the public domain. We make this dedication for the benefit - of the public at large and to the detriment of our heirs and - successors. We intend this dedication to be an overt act of - relinquishment in perpetuity of all present and future rights to this - software under copyright law. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - For more information, please refer to -*/ - -#ifndef SHEREDOM_UTEST_H_INCLUDED -#define SHEREDOM_UTEST_H_INCLUDED - -#ifdef _MSC_VER -/* - Disable warning about not inlining 'inline' functions. -*/ -#pragma warning(disable : 4710) - -/* - Disable warning about inlining functions that are not marked 'inline'. -*/ -#pragma warning(disable : 4711) - -/* - Disable warning for alignment padding added -*/ -#pragma warning(disable : 4820) - -#if _MSC_VER > 1900 -/* - Disable warning about preprocessor macros not being defined in MSVC headers. -*/ -#pragma warning(disable : 4668) - -/* - Disable warning about no function prototype given in MSVC headers. -*/ -#pragma warning(disable : 4255) - -/* - Disable warning about pointer or reference to potentially throwing function. -*/ -#pragma warning(disable : 5039) - -/* - Disable warning about macro expansion producing 'defined' has undefined - behavior. -*/ -#pragma warning(disable : 5105) -#endif - -#if _MSC_VER > 1930 -/* - Disable warning about 'const' variable is not used. -*/ -#pragma warning(disable : 5264) -#endif - -#pragma warning(push, 1) -#endif - -#if defined(_MSC_VER) && (_MSC_VER < 1920) -typedef __int64 utest_int64_t; -typedef unsigned __int64 utest_uint64_t; -typedef unsigned __int32 utest_uint32_t; -#else -#include -typedef int64_t utest_int64_t; -typedef uint64_t utest_uint64_t; -typedef uint32_t utest_uint32_t; -#endif - -#include -#include -#include -#include -#include - -#if defined(__cplusplus) -#if defined(_MSC_VER) && !defined(_CPPUNWIND) -/* We're on MSVC and the compiler is compiling without exception support! */ -#elif !defined(_MSC_VER) && !defined(__EXCEPTIONS) -/* We're on a GCC/Clang compiler that doesn't have exception support! */ -#else -#define UTEST_HAS_EXCEPTIONS 1 -#endif -#endif - -#if defined(UTEST_HAS_EXCEPTIONS) -#include -#endif - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -#if defined(__cplusplus) -#define UTEST_C_FUNC extern "C" -#else -#define UTEST_C_FUNC -#endif - -#define UTEST_TEST_PASSED (0) -#define UTEST_TEST_FAILURE (1) -#define UTEST_TEST_SKIPPED (2) - -#if defined(__TINYC__) -#define UTEST_ATTRIBUTE(a) __attribute((a)) -#else -#define UTEST_ATTRIBUTE(a) __attribute__((a)) -#endif - -#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) - -#if defined(__MINGW64__) || defined(__MINGW32__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpragmas" -#pragma GCC diagnostic ignored "-Wunknown-pragmas" -#endif - -#if defined(_WINDOWS_) || defined(_WINDOWS_H) -typedef LARGE_INTEGER utest_large_integer; -#else -// use old QueryPerformanceCounter definitions (not sure is this needed in some -// edge cases or not) on Win7 with VS2015 these extern declaration cause "second -// C linkage of overloaded function not allowed" error -typedef union { - struct { - unsigned long LowPart; - long HighPart; - } DUMMYSTRUCTNAME; - struct { - unsigned long LowPart; - long HighPart; - } u; - utest_int64_t QuadPart; -} utest_large_integer; - -UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceCounter( - utest_large_integer *); -UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceFrequency( - utest_large_integer *); - -#if defined(__MINGW64__) || defined(__MINGW32__) -#pragma GCC diagnostic pop -#endif -#endif - -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \ - defined(__HAIKU__) -/* - slightly obscure include here - we need to include glibc's features.h, but - we don't want to just include a header that might not be defined for other - c libraries like musl. Instead we include limits.h, which we know on all - glibc distributions includes features.h -*/ -#include - -#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) -#include - -#if ((2 < __GLIBC__) || ((2 == __GLIBC__) && (17 <= __GLIBC_MINOR__))) -/* glibc is version 2.17 or above, so we can just use clock_gettime */ -#define UTEST_USE_CLOCKGETTIME -#else -#include -#include -#endif -#else // Other libc implementations -#include -#define UTEST_USE_CLOCKGETTIME -#endif - -#elif defined(__APPLE__) -#include -#endif - -#if defined(_MSC_VER) && (_MSC_VER < 1920) -#define UTEST_PRId64 "I64d" -#define UTEST_PRIu64 "I64u" -#else -#include - -#define UTEST_PRId64 PRId64 -#define UTEST_PRIu64 PRIu64 -#endif - -#if defined(__cplusplus) -#define UTEST_INLINE inline - -#if defined(__clang__) -#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") - -#define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") -#else -#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS -#define UTEST_INITIALIZER_END_DISABLE_WARNINGS -#endif - -#define UTEST_INITIALIZER(f) \ - struct f##_cpp_struct { \ - f##_cpp_struct(); \ - }; \ - UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS static f##_cpp_struct \ - f##_cpp_global UTEST_INITIALIZER_END_DISABLE_WARNINGS; \ - f##_cpp_struct::f##_cpp_struct() -#elif defined(_MSC_VER) -#define UTEST_INLINE __forceinline - -#if defined(_WIN64) -#define UTEST_SYMBOL_PREFIX -#else -#define UTEST_SYMBOL_PREFIX "_" -#endif - -#if defined(__clang__) -#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wmissing-variable-declarations\"") - -#define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") -#else -#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS -#define UTEST_INITIALIZER_END_DISABLE_WARNINGS -#endif - -#pragma section(".CRT$XCU", read) -#define UTEST_INITIALIZER(f) \ - static void __cdecl f(void); \ - UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ - __pragma(comment(linker, "/include:" UTEST_SYMBOL_PREFIX #f "_")) \ - UTEST_C_FUNC __declspec(allocate(".CRT$XCU")) void(__cdecl * \ - f##_)(void) = f; \ - UTEST_INITIALIZER_END_DISABLE_WARNINGS \ - static void __cdecl f(void) -#else -#if defined(__linux__) -#if defined(__clang__) -#if __has_warning("-Wreserved-id-macro") -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreserved-id-macro" -#endif -#endif - -#define __STDC_FORMAT_MACROS 1 - -#if defined(__clang__) -#if __has_warning("-Wreserved-id-macro") -#pragma clang diagnostic pop -#endif -#endif -#endif - -#define UTEST_INLINE inline - -#define UTEST_INITIALIZER(f) \ - static void f(void) UTEST_ATTRIBUTE(constructor); \ - static void f(void) -#endif - -#if defined(__cplusplus) -#define UTEST_CAST(type, x) static_cast(x) -#define UTEST_PTR_CAST(type, x) reinterpret_cast(x) -#define UTEST_EXTERN extern "C" -#define UTEST_NULL NULL -#else -#define UTEST_CAST(type, x) ((type)(x)) -#define UTEST_PTR_CAST(type, x) ((type)(x)) -#define UTEST_EXTERN extern -#define UTEST_NULL 0 -#endif - -#ifdef _MSC_VER -/* - io.h contains definitions for some structures with natural padding. This is - uninteresting, but for some reason MSVC's behaviour is to warn about - including this system header. That *is* interesting -*/ -#pragma warning(disable : 4820) -#pragma warning(push, 1) -#include -#pragma warning(pop) -#define UTEST_COLOUR_OUTPUT() (_isatty(_fileno(stdout))) -#else -#if defined(__EMSCRIPTEN__) -#include -#define UTEST_COLOUR_OUTPUT() false -#else -#include -#define UTEST_COLOUR_OUTPUT() (isatty(STDOUT_FILENO)) -#endif -#endif - -static UTEST_INLINE void *utest_realloc(void *const pointer, size_t new_size) { - void *const new_pointer = realloc(pointer, new_size); - - if (UTEST_NULL == new_pointer) { - free(new_pointer); - } - - return new_pointer; -} - -static UTEST_INLINE utest_int64_t utest_ns(void) { -#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) - utest_large_integer counter; - utest_large_integer frequency; - QueryPerformanceCounter(&counter); - QueryPerformanceFrequency(&frequency); - return UTEST_CAST(utest_int64_t, - (counter.QuadPart * 1000000000) / frequency.QuadPart); -#elif defined(__linux__) && defined(__STRICT_ANSI__) - return UTEST_CAST(utest_int64_t, clock()) * 1000000000 / CLOCKS_PER_SEC; -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \ - defined(__HAIKU__) - struct timespec ts; -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(__HAIKU__) - timespec_get(&ts, TIME_UTC); -#else - const clockid_t cid = CLOCK_REALTIME; -#if defined(UTEST_USE_CLOCKGETTIME) - clock_gettime(cid, &ts); -#else - syscall(SYS_clock_gettime, cid, &ts); -#endif -#endif - return UTEST_CAST(utest_int64_t, ts.tv_sec) * 1000 * 1000 * 1000 + ts.tv_nsec; -#elif __APPLE__ - return UTEST_CAST(utest_int64_t, clock_gettime_nsec_np(CLOCK_UPTIME_RAW)); -#elif __EMSCRIPTEN__ - return emscripten_performance_now() * 1000000.0; -#else -#error Unsupported platform! -#endif -} - -typedef void (*utest_testcase_t)(int *, size_t); - -struct utest_test_state_s { - utest_testcase_t func; - size_t index; - char *name; -}; - -struct utest_state_s { - struct utest_test_state_s *tests; - size_t tests_length; - FILE *output; -}; - -/* extern to the global state utest needs to execute */ -UTEST_EXTERN struct utest_state_s utest_state; - -#if defined(_MSC_VER) -#define UTEST_WEAK __forceinline -#elif defined(__MINGW32__) || defined(__MINGW64__) -#define UTEST_WEAK static UTEST_ATTRIBUTE(used) -#elif defined(__clang__) || defined(__GNUC__) || defined(__TINYC__) -#define UTEST_WEAK UTEST_ATTRIBUTE(weak) -#else -#error Non clang, non gcc, non MSVC, non tcc compiler found! -#endif - -#if defined(_MSC_VER) -#define UTEST_UNUSED -#else -#define UTEST_UNUSED UTEST_ATTRIBUTE(unused) -#endif - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wvariadic-macros" -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#define UTEST_PRINTF(...) \ - if (utest_state.output) { \ - fprintf(utest_state.output, __VA_ARGS__); \ - } \ - printf(__VA_ARGS__) -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wvariadic-macros" -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -#ifdef _MSC_VER -#define UTEST_SNPRINTF(BUFFER, N, ...) _snprintf_s(BUFFER, N, N, __VA_ARGS__) -#else -#define UTEST_SNPRINTF(...) snprintf(__VA_ARGS__) -#endif - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#if defined(__cplusplus) -/* if we are using c++ we can use overloaded methods (its in the language) */ -#define UTEST_OVERLOADABLE -#elif defined(__clang__) -/* otherwise, if we are using clang with c - use the overloadable attribute */ -#define UTEST_OVERLOADABLE UTEST_ATTRIBUTE(overloadable) -#endif - -#if defined(__cplusplus) && (__cplusplus >= 201103L) - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -#include - -template ::value> -struct utest_type_deducer final { - static void _(const T t); -}; - -template <> struct utest_type_deducer { - static void _(const signed char c) { - UTEST_PRINTF("%d", static_cast(c)); - } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned char c) { - UTEST_PRINTF("%u", static_cast(c)); - } -}; - -template <> struct utest_type_deducer { - static void _(const short s) { UTEST_PRINTF("%d", static_cast(s)); } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned short s) { - UTEST_PRINTF("%u", static_cast(s)); - } -}; - -template <> struct utest_type_deducer { - static void _(const float f) { UTEST_PRINTF("%f", static_cast(f)); } -}; - -template <> struct utest_type_deducer { - static void _(const double d) { UTEST_PRINTF("%f", d); } -}; - -template <> struct utest_type_deducer { - static void _(const long double d) { -#if defined(__MINGW32__) || defined(__MINGW64__) - /* MINGW is weird - doesn't like LF at all?! */ - UTEST_PRINTF("%f", (double)d); -#else - UTEST_PRINTF("%Lf", d); -#endif - } -}; - -template <> struct utest_type_deducer { - static void _(const int i) { UTEST_PRINTF("%d", i); } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned int i) { UTEST_PRINTF("%u", i); } -}; - -template <> struct utest_type_deducer { - static void _(const long i) { UTEST_PRINTF("%ld", i); } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned long i) { UTEST_PRINTF("%lu", i); } -}; - -template <> struct utest_type_deducer { - static void _(const long long i) { UTEST_PRINTF("%lld", i); } -}; - -template <> struct utest_type_deducer { - static void _(const unsigned long long i) { UTEST_PRINTF("%llu", i); } -}; - -template struct utest_type_deducer { - static void _(const T *t) { - UTEST_PRINTF("%p", static_cast(const_cast(t))); - } -}; - -template struct utest_type_deducer { - static void _(T *t) { UTEST_PRINTF("%p", static_cast(t)); } -}; - -template struct utest_type_deducer { - static void _(const T t) { - UTEST_PRINTF("%llu", static_cast(t)); - } -}; - -template -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const T t) { - utest_type_deducer::_(t); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#elif defined(UTEST_OVERLOADABLE) - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(signed char c); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(signed char c) { - UTEST_PRINTF("%d", UTEST_CAST(int, c)); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned char c); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned char c) { - UTEST_PRINTF("%u", UTEST_CAST(unsigned int, c)); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f) { - UTEST_PRINTF("%f", UTEST_CAST(double, f)); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d) { - UTEST_PRINTF("%f", d); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d) { -#if defined(__MINGW32__) || defined(__MINGW64__) - /* MINGW is weird - doesn't like LF at all?! */ - UTEST_PRINTF("%f", (double)d); -#else - UTEST_PRINTF("%Lf", d); -#endif -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i) { - UTEST_PRINTF("%d", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i) { - UTEST_PRINTF("%u", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i) { - UTEST_PRINTF("%ld", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i) { - UTEST_PRINTF("%lu", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p) { - UTEST_PRINTF("%p", p); -} - -/* - long long is a c++11 extension -*/ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || \ - defined(__cplusplus) && (__cplusplus >= 201103L) || \ - (defined(__MINGW32__) || defined(__MINGW64__)) - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i); -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i) { - UTEST_PRINTF("%lld", i); -} - -UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long unsigned int i); -UTEST_WEAK UTEST_OVERLOADABLE void -utest_type_printer(long long unsigned int i) { - UTEST_PRINTF("%llu", i); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !(defined(__MINGW32__) || defined(__MINGW64__)) || \ - defined(__TINYC__) -#define utest_type_printer(val) \ - UTEST_PRINTF(_Generic((val), signed char \ - : "%d", unsigned char \ - : "%u", short \ - : "%d", unsigned short \ - : "%u", int \ - : "%d", long \ - : "%ld", long long \ - : "%lld", unsigned \ - : "%u", unsigned long \ - : "%lu", unsigned long long \ - : "%llu", float \ - : "%f", double \ - : "%f", long double \ - : "%Lf", default \ - : _Generic((val - val), ptrdiff_t \ - : "%p", default \ - : "undef")), \ - (val)) -#else -/* - we don't have the ability to print the values we got, so we create a macro - to tell our users we can't do anything fancy -*/ -#define utest_type_printer(...) UTEST_PRINTF("undef") -#endif - -#if defined(_MSC_VER) -#define UTEST_SURPRESS_WARNING_BEGIN \ - __pragma(warning(push)) __pragma(warning(disable : 4127)) \ - __pragma(warning(disable : 4571)) __pragma(warning(disable : 4130)) -#define UTEST_SURPRESS_WARNING_END __pragma(warning(pop)) -#else -#define UTEST_SURPRESS_WARNING_BEGIN -#define UTEST_SURPRESS_WARNING_END -#endif - -#if defined(__cplusplus) && (__cplusplus >= 201103L) -#define UTEST_AUTO(x) auto -#elif !defined(__cplusplus) - -#if defined(__clang__) -/* clang-format off */ -/* had to disable clang-format here because it malforms the pragmas */ -#define UTEST_AUTO(x) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wgnu-auto-type\"") __auto_type \ - _Pragma("clang diagnostic pop") -/* clang-format on */ -#else -#define UTEST_AUTO(x) __typeof__(x + 0) -#endif - -#else -#define UTEST_AUTO(x) typeof(x + 0) -#endif - -#if defined(__clang__) -#define UTEST_STRNCMP(x, y, size) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") \ - strncmp(x, y, size) _Pragma("clang diagnostic pop") -#else -#define UTEST_STRNCMP(x, y, size) strncmp(x, y, size) -#endif - -#if defined(_MSC_VER) -#define UTEST_STRNCPY(x, y, size) strcpy_s(x, size, y) -#elif !defined(__clang__) && defined(__GNUC__) -static UTEST_INLINE char * -utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-overflow" - return strncpy(dst, src, size); -#pragma GCC diagnostic pop -} - -#define UTEST_STRNCPY(x, y, size) utest_strncpy_gcc(x, y, size) -#else -#define UTEST_STRNCPY(x, y, size) strncpy(x, y, size) -#endif - -#define UTEST_SKIP(msg) \ - do { \ - UTEST_PRINTF(" Skipped : '%s'\n", (msg)); \ - *utest_result = UTEST_TEST_SKIPPED; \ - return; \ - } while (0) - -#if defined(__clang__) -#define UTEST_COND(x, y, cond, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wlanguage-extension-token\"") \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \ - _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \ - UTEST_AUTO(x) xEval = (x); \ - UTEST_AUTO(y) yEval = (y); \ - if (!((xEval)cond(yEval))) { \ - _Pragma("clang diagnostic pop") \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : ("); \ - UTEST_PRINTF(#x ") " #cond " (" #y); \ - UTEST_PRINTF(")\n"); \ - UTEST_PRINTF(" Actual : "); \ - utest_type_printer(xEval); \ - UTEST_PRINTF(" vs "); \ - utest_type_printer(yEval); \ - UTEST_PRINTF("\n"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END -#elif defined(__GNUC__) || defined(__TINYC__) -#define UTEST_COND(x, y, cond, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - UTEST_AUTO(x) xEval = (x); \ - UTEST_AUTO(y) yEval = (y); \ - if (!((xEval)cond(yEval))) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : ("); \ - UTEST_PRINTF(#x ") " #cond " (" #y); \ - UTEST_PRINTF(")\n"); \ - UTEST_PRINTF(" Actual : "); \ - utest_type_printer(xEval); \ - UTEST_PRINTF(" vs "); \ - utest_type_printer(yEval); \ - UTEST_PRINTF("\n"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END -#else -#define UTEST_COND(x, y, cond, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - if (!((x)cond(y))) { \ - UTEST_PRINTF("%s:%i: Failure (Expected " #cond " Actual)", __FILE__, \ - __LINE__); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s", msg); \ - } \ - UTEST_PRINTF("\n"); \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END -#endif - -#define EXPECT_EQ(x, y) UTEST_COND(x, y, ==, "", 0) -#define EXPECT_EQ_MSG(x, y, msg) UTEST_COND(x, y, ==, msg, 0) -#define ASSERT_EQ(x, y) UTEST_COND(x, y, ==, "", 1) -#define ASSERT_EQ_MSG(x, y, msg) UTEST_COND(x, y, ==, msg, 1) - -#define EXPECT_NE(x, y) UTEST_COND(x, y, !=, "", 0) -#define EXPECT_NE_MSG(x, y, msg) UTEST_COND(x, y, !=, msg, 0) -#define ASSERT_NE(x, y) UTEST_COND(x, y, !=, "", 1) -#define ASSERT_NE_MSG(x, y, msg) UTEST_COND(x, y, !=, msg, 1) - -#define EXPECT_LT(x, y) UTEST_COND(x, y, <, "", 0) -#define EXPECT_LT_MSG(x, y, msg) UTEST_COND(x, y, <, msg, 0) -#define ASSERT_LT(x, y) UTEST_COND(x, y, <, "", 1) -#define ASSERT_LT_MSG(x, y, msg) UTEST_COND(x, y, <, msg, 1) - -#define EXPECT_LE(x, y) UTEST_COND(x, y, <=, "", 0) -#define EXPECT_LE_MSG(x, y, msg) UTEST_COND(x, y, <=, msg, 0) -#define ASSERT_LE(x, y) UTEST_COND(x, y, <=, "", 1) -#define ASSERT_LE_MSG(x, y, msg) UTEST_COND(x, y, <=, msg, 1) - -#define EXPECT_GT(x, y) UTEST_COND(x, y, >, "", 0) -#define EXPECT_GT_MSG(x, y, msg) UTEST_COND(x, y, >, msg, 0) -#define ASSERT_GT(x, y) UTEST_COND(x, y, >, "", 1) -#define ASSERT_GT_MSG(x, y, msg) UTEST_COND(x, y, >, msg, 1) - -#define EXPECT_GE(x, y) UTEST_COND(x, y, >=, "", 0) -#define EXPECT_GE_MSG(x, y, msg) UTEST_COND(x, y, >=, msg, 0) -#define ASSERT_GE(x, y) UTEST_COND(x, y, >=, "", 1) -#define ASSERT_GE_MSG(x, y, msg) UTEST_COND(x, y, >=, msg, 1) - -#define UTEST_TRUE(x, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const int xEval = !!(x); \ - if (!(xEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : true\n"); \ - UTEST_PRINTF(" Actual : %s\n", (xEval) ? "true" : "false"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_TRUE(x) UTEST_TRUE(x, "", 0) -#define EXPECT_TRUE_MSG(x, msg) UTEST_TRUE(x, msg, 0) -#define ASSERT_TRUE(x) UTEST_TRUE(x, "", 1) -#define ASSERT_TRUE_MSG(x, msg) UTEST_TRUE(x, msg, 1) - -#define UTEST_FALSE(x, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const int xEval = !!(x); \ - if (xEval) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : false\n"); \ - UTEST_PRINTF(" Actual : %s\n", (xEval) ? "true" : "false"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_FALSE(x) UTEST_FALSE(x, "", 0) -#define EXPECT_FALSE_MSG(x, msg) UTEST_FALSE(x, msg, 0) -#define ASSERT_FALSE(x) UTEST_FALSE(x, "", 1) -#define ASSERT_FALSE_MSG(x, msg) UTEST_FALSE(x, msg, 1) - -#define UTEST_STREQ(x, y, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const char *xEval = (x); \ - const char *yEval = (y); \ - if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ - 0 != strcmp(xEval, yEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : \"%s\"\n", xEval); \ - UTEST_PRINTF(" Actual : \"%s\"\n", yEval); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_STREQ(x, y) UTEST_STREQ(x, y, "", 0) -#define EXPECT_STREQ_MSG(x, y, msg) UTEST_STREQ(x, y, msg, 0) -#define ASSERT_STREQ(x, y) UTEST_STREQ(x, y, "", 1) -#define ASSERT_STREQ_MSG(x, y, msg) UTEST_STREQ(x, y, msg, 1) - -#define UTEST_STRNE(x, y, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const char *xEval = (x); \ - const char *yEval = (y); \ - if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ - 0 == strcmp(xEval, yEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : \"%s\"\n", xEval); \ - UTEST_PRINTF(" Actual : \"%s\"\n", yEval); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_STRNE(x, y) UTEST_STRNE(x, y, "", 0) -#define EXPECT_STRNE_MSG(x, y, msg) UTEST_STRNE(x, y, msg, 0) -#define ASSERT_STRNE(x, y) UTEST_STRNE(x, y, "", 1) -#define ASSERT_STRNE_MSG(x, y, msg) UTEST_STRNE(x, y, msg, 1) - -#define UTEST_STRNEQ(x, y, n, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const char *xEval = (x); \ - const char *yEval = (y); \ - const size_t nEval = UTEST_CAST(size_t, n); \ - if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ - 0 != UTEST_STRNCMP(xEval, yEval, nEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, nEval), xEval); \ - UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, nEval), yEval); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_STRNEQ(x, y, n) UTEST_STRNEQ(x, y, n, "", 0) -#define EXPECT_STRNEQ_MSG(x, y, n, msg) UTEST_STRNEQ(x, y, n, msg, 0) -#define ASSERT_STRNEQ(x, y, n) UTEST_STRNEQ(x, y, n, "", 1) -#define ASSERT_STRNEQ_MSG(x, y, n, msg) UTEST_STRNEQ(x, y, n, msg, 1) - -#define UTEST_STRNNE(x, y, n, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const char *xEval = (x); \ - const char *yEval = (y); \ - const size_t nEval = UTEST_CAST(size_t, n); \ - if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ - 0 == UTEST_STRNCMP(xEval, yEval, nEval)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, nEval), xEval); \ - UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, nEval), yEval); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_STRNNE(x, y, n) UTEST_STRNNE(x, y, n, "", 0) -#define EXPECT_STRNNE_MSG(x, y, n, msg) UTEST_STRNNE(x, y, n, msg, 0) -#define ASSERT_STRNNE(x, y, n) UTEST_STRNNE(x, y, n, "", 1) -#define ASSERT_STRNNE_MSG(x, y, n, msg) UTEST_STRNNE(x, y, n, msg, 1) - -#define UTEST_NEAR(x, y, epsilon, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - const double diff = \ - utest_fabs(UTEST_CAST(double, x) - UTEST_CAST(double, y)); \ - if (diff > UTEST_CAST(double, epsilon) || utest_isnan(diff)) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : %f\n", UTEST_CAST(double, x)); \ - UTEST_PRINTF(" Actual : %f\n", UTEST_CAST(double, y)); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_NEAR(x, y, epsilon) UTEST_NEAR(x, y, epsilon, "", 0) -#define EXPECT_NEAR_MSG(x, y, epsilon, msg) UTEST_NEAR(x, y, epsilon, msg, 0) -#define ASSERT_NEAR(x, y, epsilon) UTEST_NEAR(x, y, epsilon, "", 1) -#define ASSERT_NEAR_MSG(x, y, epsilon, msg) UTEST_NEAR(x, y, epsilon, msg, 1) - -#if defined(UTEST_HAS_EXCEPTIONS) -#define UTEST_EXCEPTION(x, exception_type, msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - int exception_caught = 0; \ - try { \ - x; \ - } catch (const exception_type &) { \ - exception_caught = 1; \ - } catch (...) { \ - exception_caught = 2; \ - } \ - if (1 != exception_caught) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : %s exception\n", #exception_type); \ - UTEST_PRINTF(" Actual : %s\n", (2 == exception_caught) \ - ? "Unexpected exception" \ - : "No exception"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_EXCEPTION(x, exception_type) \ - UTEST_EXCEPTION(x, exception_type, "", 0) -#define EXPECT_EXCEPTION_MSG(x, exception_type, msg) \ - UTEST_EXCEPTION(x, exception_type, msg, 0) -#define ASSERT_EXCEPTION(x, exception_type) \ - UTEST_EXCEPTION(x, exception_type, "", 1) -#define ASSERT_EXCEPTION_MSG(x, exception_type, msg) \ - UTEST_EXCEPTION(x, exception_type, msg, 1) - -#define UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, \ - msg, is_assert) \ - UTEST_SURPRESS_WARNING_BEGIN do { \ - int exception_caught = 0; \ - char *message_caught = UTEST_NULL; \ - try { \ - x; \ - } catch (const exception_type &e) { \ - const char *const what = e.what(); \ - exception_caught = 1; \ - if (0 != \ - UTEST_STRNCMP(what, exception_message, strlen(exception_message))) { \ - const size_t message_size = strlen(what) + 1; \ - message_caught = UTEST_PTR_CAST(char *, malloc(message_size)); \ - UTEST_STRNCPY(message_caught, what, message_size); \ - } \ - } catch (...) { \ - exception_caught = 2; \ - } \ - if (1 != exception_caught) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : %s exception\n", #exception_type); \ - UTEST_PRINTF(" Actual : %s\n", (2 == exception_caught) \ - ? "Unexpected exception" \ - : "No exception"); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - if (is_assert) { \ - return; \ - } \ - } else if (UTEST_NULL != message_caught) { \ - UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ - UTEST_PRINTF(" Expected : %s exception with message %s\n", \ - #exception_type, exception_message); \ - UTEST_PRINTF(" Actual message : %s\n", message_caught); \ - if (strlen(msg) > 0) { \ - UTEST_PRINTF(" Message : %s\n", msg); \ - } \ - *utest_result = UTEST_TEST_FAILURE; \ - free(message_caught); \ - if (is_assert) { \ - return; \ - } \ - } \ - } \ - while (0) \ - UTEST_SURPRESS_WARNING_END - -#define EXPECT_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message) \ - UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, "", 0) -#define EXPECT_EXCEPTION_WITH_MESSAGE_MSG(x, exception_type, \ - exception_message, msg) \ - UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, msg, 0) -#define ASSERT_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message) \ - UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, "", 1) -#define ASSERT_EXCEPTION_WITH_MESSAGE_MSG(x, exception_type, \ - exception_message, msg) \ - UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, msg, 1) -#endif - -#if defined(__clang__) -#if __has_warning("-Wunsafe-buffer-usage") -#define UTEST_SURPRESS_WARNINGS_BEGIN \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wunsafe-buffer-usage\"") -#define UTEST_SURPRESS_WARNINGS_END _Pragma("clang diagnostic pop") -#else -#define UTEST_SURPRESS_WARNINGS_BEGIN -#define UTEST_SURPRESS_WARNINGS_END -#endif -#elif defined(__GNUC__) && __GNUC__ >= 8 && defined(__cplusplus) -#define UTEST_SURPRESS_WARNINGS_BEGIN \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") -#define UTEST_SURPRESS_WARNINGS_END _Pragma("GCC diagnostic pop") -#else -#define UTEST_SURPRESS_WARNINGS_BEGIN -#define UTEST_SURPRESS_WARNINGS_END -#endif - -#define UTEST(SET, NAME) \ - UTEST_SURPRESS_WARNINGS_BEGIN \ - UTEST_EXTERN struct utest_state_s utest_state; \ - static void utest_run_##SET##_##NAME(int *utest_result); \ - static void utest_##SET##_##NAME(int *utest_result, size_t utest_index) { \ - (void)utest_index; \ - utest_run_##SET##_##NAME(utest_result); \ - } \ - UTEST_INITIALIZER(utest_register_##SET##_##NAME) { \ - const size_t index = utest_state.tests_length++; \ - const char *name_part = #SET "." #NAME; \ - const size_t name_size = strlen(name_part) + 1; \ - char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ - utest_state.tests = UTEST_PTR_CAST( \ - struct utest_test_state_s *, \ - utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ - sizeof(struct utest_test_state_s) * \ - utest_state.tests_length)); \ - if (utest_state.tests) { \ - utest_state.tests[index].func = &utest_##SET##_##NAME; \ - utest_state.tests[index].name = name; \ - utest_state.tests[index].index = 0; \ - UTEST_SNPRINTF(name, name_size, "%s", name_part); \ - } else if (name) { \ - free(name); \ - } \ - } \ - UTEST_SURPRESS_WARNINGS_END \ - void utest_run_##SET##_##NAME(int *utest_result) - -#define UTEST_F_SETUP(FIXTURE) \ - static void utest_f_setup_##FIXTURE(int *utest_result, \ - struct FIXTURE *utest_fixture) - -#define UTEST_F_TEARDOWN(FIXTURE) \ - static void utest_f_teardown_##FIXTURE(int *utest_result, \ - struct FIXTURE *utest_fixture) - -#define UTEST_F(FIXTURE, NAME) \ - UTEST_SURPRESS_WARNINGS_BEGIN \ - UTEST_EXTERN struct utest_state_s utest_state; \ - static void utest_f_setup_##FIXTURE(int *, struct FIXTURE *); \ - static void utest_f_teardown_##FIXTURE(int *, struct FIXTURE *); \ - static void utest_run_##FIXTURE##_##NAME(int *, struct FIXTURE *); \ - static void utest_f_##FIXTURE##_##NAME(int *utest_result, \ - size_t utest_index) { \ - struct FIXTURE fixture; \ - (void)utest_index; \ - memset(&fixture, 0, sizeof(fixture)); \ - utest_f_setup_##FIXTURE(utest_result, &fixture); \ - if (UTEST_TEST_PASSED != *utest_result) { \ - return; \ - } \ - utest_run_##FIXTURE##_##NAME(utest_result, &fixture); \ - utest_f_teardown_##FIXTURE(utest_result, &fixture); \ - } \ - UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME) { \ - const size_t index = utest_state.tests_length++; \ - const char *name_part = #FIXTURE "." #NAME; \ - const size_t name_size = strlen(name_part) + 1; \ - char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ - utest_state.tests = UTEST_PTR_CAST( \ - struct utest_test_state_s *, \ - utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ - sizeof(struct utest_test_state_s) * \ - utest_state.tests_length)); \ - if (utest_state.tests) { \ - utest_state.tests[index].func = &utest_f_##FIXTURE##_##NAME; \ - utest_state.tests[index].name = name; \ - UTEST_SNPRINTF(name, name_size, "%s", name_part); \ - } else if (name) { \ - free(name); \ - } \ - } \ - UTEST_SURPRESS_WARNINGS_END \ - void utest_run_##FIXTURE##_##NAME(int *utest_result, \ - struct FIXTURE *utest_fixture) - -#define UTEST_I_SETUP(FIXTURE) \ - static void utest_i_setup_##FIXTURE( \ - int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) - -#define UTEST_I_TEARDOWN(FIXTURE) \ - static void utest_i_teardown_##FIXTURE( \ - int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) - -#define UTEST_I(FIXTURE, NAME, INDEX) \ - UTEST_SURPRESS_WARNINGS_BEGIN \ - UTEST_EXTERN struct utest_state_s utest_state; \ - static void utest_run_##FIXTURE##_##NAME##_##INDEX(int *, struct FIXTURE *); \ - static void utest_i_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ - size_t index) { \ - struct FIXTURE fixture; \ - memset(&fixture, 0, sizeof(fixture)); \ - utest_i_setup_##FIXTURE(utest_result, &fixture, index); \ - if (UTEST_TEST_PASSED != *utest_result) { \ - return; \ - } \ - utest_run_##FIXTURE##_##NAME##_##INDEX(utest_result, &fixture); \ - utest_i_teardown_##FIXTURE(utest_result, &fixture, index); \ - } \ - UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME##_##INDEX) { \ - size_t i; \ - utest_uint64_t iUp; \ - for (i = 0; i < (INDEX); i++) { \ - const size_t index = utest_state.tests_length++; \ - const char *name_part = #FIXTURE "." #NAME; \ - const size_t name_size = strlen(name_part) + 32; \ - char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ - utest_state.tests = UTEST_PTR_CAST( \ - struct utest_test_state_s *, \ - utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ - sizeof(struct utest_test_state_s) * \ - utest_state.tests_length)); \ - if (utest_state.tests) { \ - utest_state.tests[index].func = &utest_i_##FIXTURE##_##NAME##_##INDEX; \ - utest_state.tests[index].index = i; \ - utest_state.tests[index].name = name; \ - iUp = UTEST_CAST(utest_uint64_t, i); \ - UTEST_SNPRINTF(name, name_size, "%s/%" UTEST_PRIu64, name_part, iUp); \ - } else if (name) { \ - free(name); \ - } \ - } \ - } \ - UTEST_SURPRESS_WARNINGS_END \ - void utest_run_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ - struct FIXTURE *utest_fixture) - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - -UTEST_WEAK -double utest_fabs(double d); -UTEST_WEAK -double utest_fabs(double d) { - union { - double d; - utest_uint64_t u; - } both; - both.d = d; - both.u &= 0x7fffffffffffffffu; - return both.d; -} - -UTEST_WEAK -int utest_isnan(double d); -UTEST_WEAK -int utest_isnan(double d) { - union { - double d; - utest_uint64_t u; - } both; - both.d = d; - both.u &= 0x7fffffffffffffffu; - return both.u > 0x7ff0000000000000u; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#if defined(__clang__) -#if __has_warning("-Wunsafe-buffer-usage") -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" -#endif -#endif - -UTEST_WEAK -int utest_should_filter_test(const char *filter, const char *testcase); -UTEST_WEAK int utest_should_filter_test(const char *filter, - const char *testcase) { - if (filter) { - const char *filter_cur = filter; - const char *testcase_cur = testcase; - const char *filter_wildcard = UTEST_NULL; - - while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { - if ('*' == *filter_cur) { - /* store the position of the wildcard */ - filter_wildcard = filter_cur; - - /* skip the wildcard character */ - filter_cur++; - - while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { - if ('*' == *filter_cur) { - /* - we found another wildcard (filter is something like *foo*) so we - exit the current loop, and return to the parent loop to handle - the wildcard case - */ - break; - } else if (*filter_cur != *testcase_cur) { - /* otherwise our filter didn't match, so reset it */ - filter_cur = filter_wildcard; - } - - /* move testcase along */ - testcase_cur++; - - /* move filter along */ - filter_cur++; - } - - if (('\0' == *filter_cur) && ('\0' == *testcase_cur)) { - return 0; - } - - /* if the testcase has been exhausted, we don't have a match! */ - if ('\0' == *testcase_cur) { - return 1; - } - } else { - if (*testcase_cur != *filter_cur) { - /* test case doesn't match filter */ - return 1; - } else { - /* move our filter and testcase forward */ - testcase_cur++; - filter_cur++; - } - } - } - - if (('\0' != *filter_cur) || - (('\0' != *testcase_cur) && - ((filter == filter_cur) || ('*' != filter_cur[-1])))) { - /* we have a mismatch! */ - return 1; - } - } - - return 0; -} - -static UTEST_INLINE FILE *utest_fopen(const char *filename, const char *mode) { -#ifdef _MSC_VER - FILE *file; - if (0 == fopen_s(&file, filename, mode)) { - return file; - } else { - return UTEST_NULL; - } -#else - return fopen(filename, mode); -#endif -} - -static UTEST_INLINE int utest_main(int argc, const char *const argv[]); -int utest_main(int argc, const char *const argv[]) { - utest_uint64_t failed = 0; - utest_uint64_t skipped = 0; - size_t index = 0; - size_t *failed_testcases = UTEST_NULL; - size_t failed_testcases_length = 0; - size_t *skipped_testcases = UTEST_NULL; - size_t skipped_testcases_length = 0; - const char *filter = UTEST_NULL; - utest_uint64_t ran_tests = 0; - int enable_mixed_units = 0; - int random_order = 0; - utest_uint32_t seed = 0; - - enum colours { RESET, GREEN, RED, YELLOW }; - - const int use_colours = UTEST_COLOUR_OUTPUT(); - const char *colours[] = {"\033[0m", "\033[32m", "\033[31m", "\033[33m"}; - - if (!use_colours) { - for (index = 0; index < sizeof colours / sizeof colours[0]; index++) { - colours[index] = ""; - } - } - /* loop through all arguments looking for our options */ - for (index = 1; index < UTEST_CAST(size_t, argc); index++) { - /* Informational switches */ - const char help_str[] = "--help"; - const char list_str[] = "--list-tests"; - /* Test config switches */ - const char filter_str[] = "--filter="; - const char output_str[] = "--output="; - const char enable_mixed_units_str[] = "--enable-mixed-units"; - const char random_order_str[] = "--random-order"; - const char random_order_with_seed_str[] = "--random-order="; - - if (0 == UTEST_STRNCMP(argv[index], help_str, strlen(help_str))) { - printf("utest.h - the single file unit testing solution for C/C++!\n" - "Command line Options:\n" - " --help Show this message and exit.\n" - " --filter= Filter the test cases to run (EG. " - "MyTest*.a would run MyTestCase.a but not MyTestCase.b).\n" - " --list-tests List testnames, one per line. Output " - "names can be passed to --filter.\n"); - printf(" --output= Output an xunit XML file to the file " - "specified in .\n" - " --enable-mixed-units Enable the per-test output to contain " - "mixed units (s/ms/us/ns).\n" - " --random-order[=] Randomize the order that the tests are " - "ran in. If the optional argument is not provided, then a " - "random starting seed is used.\n"); - goto cleanup; - } else if (0 == - UTEST_STRNCMP(argv[index], filter_str, strlen(filter_str))) { - /* user wants to filter what test cases run! */ - filter = argv[index] + strlen(filter_str); - } else if (0 == - UTEST_STRNCMP(argv[index], output_str, strlen(output_str))) { - utest_state.output = utest_fopen(argv[index] + strlen(output_str), "w+"); - } else if (0 == UTEST_STRNCMP(argv[index], list_str, strlen(list_str))) { - for (index = 0; index < utest_state.tests_length; index++) { - UTEST_PRINTF("%s\n", utest_state.tests[index].name); - } - /* when printing the test list, don't actually run the tests */ - return 0; - } else if (0 == UTEST_STRNCMP(argv[index], enable_mixed_units_str, - strlen(enable_mixed_units_str))) { - enable_mixed_units = 1; - } else if (0 == UTEST_STRNCMP(argv[index], random_order_with_seed_str, - strlen(random_order_with_seed_str))) { - seed = - UTEST_CAST(utest_uint32_t, - strtoul(argv[index] + strlen(random_order_with_seed_str), - UTEST_NULL, 10)); - random_order = 1; - } else if (0 == UTEST_STRNCMP(argv[index], random_order_str, - strlen(random_order_str))) { - const utest_int64_t ns = utest_ns(); - - // Some really poor pseudo-random using the current time. I do this - // because I really want to avoid using C's rand() because that'd mean our - // random would be affected by any srand() usage by the user (which I - // don't want). - seed = UTEST_CAST(utest_uint32_t, ns >> 32) * 31 + - UTEST_CAST(utest_uint32_t, ns & 0xffffffff); - random_order = 1; - } - } - - if (random_order) { - // Use Fisher-Yates with the Durstenfield's version to randomly re-order the - // tests. - for (index = utest_state.tests_length; index > 1; index--) { - // For the random order we'll use PCG. - const utest_uint32_t state = seed; - const utest_uint32_t word = - ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; - const utest_uint32_t next = - ((word >> 22u) ^ word) % UTEST_CAST(utest_uint32_t, index); - - // Swap the randomly chosen element into the last location. - const struct utest_test_state_s copy = utest_state.tests[index - 1]; - utest_state.tests[index - 1] = utest_state.tests[next]; - utest_state.tests[next] = copy; - - // Move the seed onwards. - seed = seed * 747796405u + 2891336453u; - } - } - - for (index = 0; index < utest_state.tests_length; index++) { - if (utest_should_filter_test(filter, utest_state.tests[index].name)) { - continue; - } - - ran_tests++; - } - - printf("%s[==========]%s Running %" UTEST_PRIu64 " test cases.\n", - colours[GREEN], colours[RESET], UTEST_CAST(utest_uint64_t, ran_tests)); - - if (utest_state.output) { - fprintf(utest_state.output, "\n"); - fprintf(utest_state.output, - "\n", - UTEST_CAST(utest_uint64_t, ran_tests)); - fprintf(utest_state.output, - "\n", - UTEST_CAST(utest_uint64_t, ran_tests)); - } - - for (index = 0; index < utest_state.tests_length; index++) { - int result = UTEST_TEST_PASSED; - utest_int64_t ns = 0; - - if (utest_should_filter_test(filter, utest_state.tests[index].name)) { - continue; - } - - printf("%s[ RUN ]%s %s\n", colours[GREEN], colours[RESET], - utest_state.tests[index].name); - - if (utest_state.output) { - fprintf(utest_state.output, "", - utest_state.tests[index].name); - } - - ns = utest_ns(); - errno = 0; -#if defined(UTEST_HAS_EXCEPTIONS) - UTEST_SURPRESS_WARNING_BEGIN - try { - utest_state.tests[index].func(&result, utest_state.tests[index].index); - } catch (const std::exception &err) { - printf(" Exception : %s\n", err.what()); - result = UTEST_TEST_FAILURE; - } catch (...) { - printf(" Exception : Unknown\n"); - result = UTEST_TEST_FAILURE; - } - UTEST_SURPRESS_WARNING_END -#else - utest_state.tests[index].func(&result, utest_state.tests[index].index); -#endif - ns = utest_ns() - ns; - - if (utest_state.output) { - fprintf(utest_state.output, "\n"); - } - - // Record the failing test. - if (UTEST_TEST_FAILURE == result) { - const size_t failed_testcase_index = failed_testcases_length++; - failed_testcases = UTEST_PTR_CAST( - size_t *, utest_realloc(UTEST_PTR_CAST(void *, failed_testcases), - sizeof(size_t) * failed_testcases_length)); - if (UTEST_NULL != failed_testcases) { - failed_testcases[failed_testcase_index] = index; - } - failed++; - } else if (UTEST_TEST_SKIPPED == result) { - const size_t skipped_testcase_index = skipped_testcases_length++; - skipped_testcases = UTEST_PTR_CAST( - size_t *, utest_realloc(UTEST_PTR_CAST(void *, skipped_testcases), - sizeof(size_t) * skipped_testcases_length)); - if (UTEST_NULL != skipped_testcases) { - skipped_testcases[skipped_testcase_index] = index; - } - skipped++; - } - - { - const char *const units[] = {"ns", "us", "ms", "s", UTEST_NULL}; - unsigned int unit_index = 0; - utest_int64_t time = ns; - - if (enable_mixed_units) { - for (unit_index = 0; UTEST_NULL != units[unit_index]; unit_index++) { - if (10000 > time) { - break; - } - - time /= 1000; - } - } - - if (UTEST_TEST_FAILURE == result) { - printf("%s[ FAILED ]%s %s (%" UTEST_PRId64 "%s)\n", colours[RED], - colours[RESET], utest_state.tests[index].name, time, - units[unit_index]); - } else if (UTEST_TEST_SKIPPED == result) { - printf("%s[ SKIPPED ]%s %s (%" UTEST_PRId64 "%s)\n", colours[YELLOW], - colours[RESET], utest_state.tests[index].name, time, - units[unit_index]); - } else { - printf("%s[ OK ]%s %s (%" UTEST_PRId64 "%s)\n", colours[GREEN], - colours[RESET], utest_state.tests[index].name, time, - units[unit_index]); - } - } - } - - printf("%s[==========]%s %" UTEST_PRIu64 " test cases ran.\n", colours[GREEN], - colours[RESET], ran_tests); - printf("%s[ PASSED ]%s %" UTEST_PRIu64 " tests.\n", colours[GREEN], - colours[RESET], ran_tests - failed - skipped); - - if (0 != skipped) { - printf("%s[ SKIPPED ]%s %" UTEST_PRIu64 " tests, listed below:\n", - colours[YELLOW], colours[RESET], skipped); - for (index = 0; index < skipped_testcases_length; index++) { - printf("%s[ SKIPPED ]%s %s\n", colours[YELLOW], colours[RESET], - utest_state.tests[skipped_testcases[index]].name); - } - } - - if (0 != failed) { - printf("%s[ FAILED ]%s %" UTEST_PRIu64 " tests, listed below:\n", - colours[RED], colours[RESET], failed); - for (index = 0; index < failed_testcases_length; index++) { - printf("%s[ FAILED ]%s %s\n", colours[RED], colours[RESET], - utest_state.tests[failed_testcases[index]].name); - } - } - - if (utest_state.output) { - fprintf(utest_state.output, "\n\n"); - } - -cleanup: - for (index = 0; index < utest_state.tests_length; index++) { - free(UTEST_PTR_CAST(void *, utest_state.tests[index].name)); - } - - free(UTEST_PTR_CAST(void *, skipped_testcases)); - free(UTEST_PTR_CAST(void *, failed_testcases)); - free(UTEST_PTR_CAST(void *, utest_state.tests)); - - if (utest_state.output) { - fclose(utest_state.output); - } - - return UTEST_CAST(int, failed); -} - -#if defined(__clang__) -#if __has_warning("-Wunsafe-buffer-usage") -#pragma clang diagnostic pop -#endif -#endif - -/* - we need, in exactly one source file, define the global struct that will hold - the data we need to run utest. This macro allows the user to declare the - data without having to use the UTEST_MAIN macro, thus allowing them to write - their own main() function. -*/ -#define UTEST_STATE() struct utest_state_s utest_state = {0, 0, 0} - -/* - define a main() function to call into utest.h and start executing tests! A - user can optionally not use this macro, and instead define their own main() - function and manually call utest_main. The user must, in exactly one source - file, use the UTEST_STATE macro to declare a global struct variable that - utest requires. -*/ -#define UTEST_MAIN() \ - UTEST_STATE(); \ - int main(int argc, const char *const argv[]) { \ - return utest_main(argc, argv); \ - } - -#endif /* SHEREDOM_UTEST_H_INCLUDED */ diff --git a/lab-5/README.md b/lab-5/README.md deleted file mode 100644 index b9e30d0..0000000 --- a/lab-5/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# Bison Interpreter - -Create an interpreter for your sample programs. -See the [example lab for Python](https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab-python). - -In this lab, you will focus on basic operations that support your sample code. - -* Arithmetic operations - * add - * subtract - * multiple - * divide -* Functions (but implemented directly in the language) - * Printing - * Square root -* Variable for numbers -* Variable for lists (or arrays) -* Branching statements -* Looping statements - -Notice you will find a new file `expr.c`. -The file is used to implement the parser rule. -Inside these functions, you will create the runtime code that is the interpreter. - - -## Build Process - -The process is similar to prior labs. -To build the `scanner.c` run the following **flex** command. - -```sh -flex -o scanner.c scanner.flex -``` - -The parser is built using **bison**. -Note this command also builds the `token.h`. - -```sh -bison --defines=token.h --output=parser.c parser.bison -``` - -Then build the `main.c`, `expr.c`, `parcer.c` and `scanner.c` using **gcc**. -Note that you may get a few warnings that can be ignored. - -```sh -gcc *.c -o interpreter.out -``` - -Then execute the test suite using `./interpreter.out` and pass in the input from your sample program. -For example here is a command for `samples/program.c` - -```sh -./interpreter.out < samples/program.c -``` - -Single line command: - -```sh -flex -o scanner.c scanner.flex && \ -bison --defines=token.h --output=parser.c parser.bison && \ -gcc *.c -o interpreter.out && ./interpreter.out < samples/program.c -``` - -## Building with Make - -To simplify the process a Makefile has been supplied. - -```sh -make && ./interpreter.out < samples/program.c -``` - -To remove the build files, use make clean. - -```sh -make clean -``` - - -## Assignment Steps - -1. Start by confirming these commands work for the sample code provided. - -1. Next copy over your `scanner.flex`, `parser.bison` and sample programs from lab 5. - -1. Start working on your bison `parser.bison` and `expr.c` files to implement the interpreter part of your parser. - - -## Grading Rubric - -The grading will be over the following categories. - -Points Description ------------ ------------------------------------ -30 points Ability to interpret — Hello world -30 points Ability to interpret — Quadratic equation -30 points Ability to interpret — Arithmetic operations -30 points Ability to interpret — Integer Sort example -20 points Ability to interpret — Looping operations -20 points Ability to interpret — Branching operations -20 points Ability to interpret — Array variables -10 points Report formatting and readability - - -## Turn In - -Please submit the URL of your GitLab project to D2L's Brightspace with your report. -On GitLab update the `lab-5` folder to have your report and code snippets before the due date. diff --git a/lab-5/samples/hello-world.cbl b/lab-5/samples/hello-world.cbl deleted file mode 100644 index 737f19e..0000000 --- a/lab-5/samples/hello-world.cbl +++ /dev/null @@ -1,5 +0,0 @@ -IDENTIFICATION DIVISION. -PROGRAM-ID. HELLO-WORLD. -PROCEDURE DIVISION. - DISPLAY 'Hello World!' -STOP RUN. diff --git a/lab-5/samples/only-variables.cbl b/lab-5/samples/only-variables.cbl deleted file mode 100644 index 1a900a5..0000000 --- a/lab-5/samples/only-variables.cbl +++ /dev/null @@ -1,24 +0,0 @@ -IDENTIFICATION DIVISION. -PROGRAM-ID. variables. -DATA DIVISION. -WORKING-STORAGE SECTION. - 01 WS-SORT-AREA. - 05 WS-SORT-TABLE. - 10 WS-SORT-ROW PIC X(10) OCCURS 100. - 05 WS-TEMP-ROW PIC X(10). - 05 WS-ROW-MAX PIC S9(4) COMP VALUE 100. - 05 WS-SORT-MAX PIC S9(4) COMP. - 05 WS-I PIC S9(4) COMP. - 05 WS-J PIC S9(4) COMP. - 05 WS-INDEX PIC S9(4) COMP. - 77 a PIC S9(5)V9(5) COMP-3 VALUE 1. - 77 b PIC S9(5)V9(5) COMP-3 VALUE 5. - 77 c PIC S9(5)V9(5) COMP-3 VALUE 6. - 77 discriminant PIC S9(5)V9(5) COMP-3. - 77 root1 PIC S9(5)V9(5) COMP-3. - 77 root2 PIC S9(5)V9(5) COMP-3. - 77 square-root-discriminant PIC S9(5)V9(5) COMP-3. - -PROCEDURE DIVISION. - DISPLAY 'Hello World!' - STOP RUN. \ No newline at end of file diff --git a/lab-5/main.c b/main.c similarity index 100% rename from lab-5/main.c rename to main.c diff --git a/lab-5/main_test.c b/main_test.c similarity index 100% rename from lab-5/main_test.c rename to main_test.c diff --git a/lab-5/parser.bison b/parser.bison similarity index 100% rename from lab-5/parser.bison rename to parser.bison diff --git a/lab-5/parser.bison.new b/parser.bison.new similarity index 100% rename from lab-5/parser.bison.new rename to parser.bison.new diff --git a/lab-5/parser_test.c b/parser_test.c similarity index 100% rename from lab-5/parser_test.c rename to parser_test.c diff --git a/lab-5/samples/addition.cbl b/samples/addition.cbl similarity index 100% rename from lab-5/samples/addition.cbl rename to samples/addition.cbl diff --git a/lab-5/samples/assignment.cbl b/samples/assignment.cbl similarity index 100% rename from lab-5/samples/assignment.cbl rename to samples/assignment.cbl diff --git a/lab-5/samples/branching.cbl b/samples/branching.cbl similarity index 100% rename from lab-5/samples/branching.cbl rename to samples/branching.cbl diff --git a/lab-5/samples/hello-world-multiple-args.cbl b/samples/hello-world-multiple-args.cbl similarity index 100% rename from lab-5/samples/hello-world-multiple-args.cbl rename to samples/hello-world-multiple-args.cbl diff --git a/lab-3/samples/hello-world.cbl b/samples/hello-world.cbl similarity index 100% rename from lab-3/samples/hello-world.cbl rename to samples/hello-world.cbl diff --git a/lab-5/samples/looping.cbl b/samples/looping.cbl similarity index 100% rename from lab-5/samples/looping.cbl rename to samples/looping.cbl diff --git a/lab-4/samples/only-variables.cbl b/samples/only-variables.cbl similarity index 100% rename from lab-4/samples/only-variables.cbl rename to samples/only-variables.cbl diff --git a/lab-5/samples/outputs/addition_evaluate.txt b/samples/outputs/addition_evaluate.txt similarity index 100% rename from lab-5/samples/outputs/addition_evaluate.txt rename to samples/outputs/addition_evaluate.txt diff --git a/lab-5/samples/outputs/addition_print.txt b/samples/outputs/addition_print.txt similarity index 100% rename from lab-5/samples/outputs/addition_print.txt rename to samples/outputs/addition_print.txt diff --git a/lab-5/samples/outputs/assignment_evaluate.txt b/samples/outputs/assignment_evaluate.txt similarity index 100% rename from lab-5/samples/outputs/assignment_evaluate.txt rename to samples/outputs/assignment_evaluate.txt diff --git a/lab-5/samples/outputs/assignment_print.txt b/samples/outputs/assignment_print.txt similarity index 100% rename from lab-5/samples/outputs/assignment_print.txt rename to samples/outputs/assignment_print.txt diff --git a/lab-5/samples/outputs/branching_evaluate.txt b/samples/outputs/branching_evaluate.txt similarity index 100% rename from lab-5/samples/outputs/branching_evaluate.txt rename to samples/outputs/branching_evaluate.txt diff --git a/lab-5/samples/outputs/branching_print.txt b/samples/outputs/branching_print.txt similarity index 100% rename from lab-5/samples/outputs/branching_print.txt rename to samples/outputs/branching_print.txt diff --git a/lab-5/samples/outputs/hello-world_evaluate.txt b/samples/outputs/hello-world_evaluate.txt similarity index 100% rename from lab-5/samples/outputs/hello-world_evaluate.txt rename to samples/outputs/hello-world_evaluate.txt diff --git a/lab-5/samples/outputs/hello-world_print.txt b/samples/outputs/hello-world_print.txt similarity index 100% rename from lab-5/samples/outputs/hello-world_print.txt rename to samples/outputs/hello-world_print.txt diff --git a/lab-5/samples/outputs/looping_evaluate.txt b/samples/outputs/looping_evaluate.txt similarity index 100% rename from lab-5/samples/outputs/looping_evaluate.txt rename to samples/outputs/looping_evaluate.txt diff --git a/lab-5/samples/outputs/looping_print.txt b/samples/outputs/looping_print.txt similarity index 100% rename from lab-5/samples/outputs/looping_print.txt rename to samples/outputs/looping_print.txt diff --git a/lab-5/samples/outputs/quadratic_evaluate.txt b/samples/outputs/quadratic_evaluate.txt similarity index 100% rename from lab-5/samples/outputs/quadratic_evaluate.txt rename to samples/outputs/quadratic_evaluate.txt diff --git a/lab-5/samples/outputs/quadratic_print.txt b/samples/outputs/quadratic_print.txt similarity index 100% rename from lab-5/samples/outputs/quadratic_print.txt rename to samples/outputs/quadratic_print.txt diff --git a/lab-5/samples/outputs/sorting_evaluate.txt b/samples/outputs/sorting_evaluate.txt similarity index 100% rename from lab-5/samples/outputs/sorting_evaluate.txt rename to samples/outputs/sorting_evaluate.txt diff --git a/lab-5/samples/outputs/sorting_print.txt b/samples/outputs/sorting_print.txt similarity index 100% rename from lab-5/samples/outputs/sorting_print.txt rename to samples/outputs/sorting_print.txt diff --git a/lab-5/samples/quadratic-snippet.cbl b/samples/quadratic-snippet.cbl similarity index 100% rename from lab-5/samples/quadratic-snippet.cbl rename to samples/quadratic-snippet.cbl diff --git a/lab-5/samples/sorting-snippet.cbl b/samples/sorting-snippet.cbl similarity index 100% rename from lab-5/samples/sorting-snippet.cbl rename to samples/sorting-snippet.cbl diff --git a/lab-5/scanner.flex b/scanner.flex similarity index 100% rename from lab-5/scanner.flex rename to scanner.flex diff --git a/lab-5/scanner_test.c b/scanner_test.c similarity index 99% rename from lab-5/scanner_test.c rename to scanner_test.c index 4cec799..735e804 100644 --- a/lab-5/scanner_test.c +++ b/scanner_test.c @@ -31,7 +31,7 @@ UTEST(scanner, hello) { {TOKEN_KEYWORD_DIVISION, "DIVISION"}, {TOKEN_DOT, "."}, {TOKEN_DISPLAY, "DISPLAY"}, - {TOKEN_STRING, "'Hello World!'"}, + {TOKEN_STRING, "Hello World!"}, {TOKEN_STOP, "STOP"}, {TOKEN_RUN, "RUN"}, {TOKEN_DOT, "."}, diff --git a/lab-5/symbol_map.c b/symbol_map.c similarity index 100% rename from lab-5/symbol_map.c rename to symbol_map.c diff --git a/lab-5/symbol_map.h b/symbol_map.h similarity index 100% rename from lab-5/symbol_map.h rename to symbol_map.h diff --git a/lab-5/token.h b/token.h similarity index 100% rename from lab-5/token.h rename to token.h diff --git a/lab-5/utest.h b/utest.h similarity index 100% rename from lab-5/utest.h rename to utest.h