Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • iocla/tema-1-2025
  • albert_mark.stan/tema-1-2025
2 results
Show changes
Commits on Source (18)
Showing
with 8798 additions and 111 deletions
transpiler
*.o
*.out
*.valgrind
\ No newline at end of file
......@@ -26,6 +26,6 @@ build:
checker:
stage: test
image:
name: gitlab.cs.pub.ro:5050/vmchecker/vmchecker-next-assignment
name: gitlab.cs.pub.ro:5050/iocla/tema-1-2025
script:
- echo ""
- echo "Test"
FROM jokeswar/base-ctl
FROM gitlab.cs.pub.ro:5050/iocla/tema-1-2024
RUN echo "Hello from Docker"
RUN cargo install hw_checker
COPY ./checker ${CHECKER_DATA_DIRECTORY}
COPY ./data.json ${CHECKER_DATA_DIRECTORY}
all: build
build:
cd src && make
pack:
cd src && zip ../Tema_1_Mihai_Popescu_312CA.zip *.c *.h Makefile
clean:
cd src && make clean
rm -rf transpiler
# Perfect assignment
# Homework 1
Write a program that given a number as input argument prints the corespondig number of 1s on standard output.
## Assignment: Simple C-to-Assembly Compiler
E.g:
**Deadline soft**: 6 aprilie 2025, 11:55PM
**Deadline hard**: 11 aprilie 2025, 11:55PM
**Authors**
* Robert Grancsa
* Adelina Alexe
## Introduction
![](banner.webp)
In a neon-lit room filled with vintage circuit boards and digital memes, Alex—a modern TikTok brain rot specialist—devised a daring plan to escape Instagram’s endless scroll. Determined to reclaim his mind, he crafted a groundbreaking compiler that transformed addictive algorithms into streams of artful data. With every line of code, toxic noise became immersive stories, intricate music, and thought-provoking visuals, forging a digital sanctuary where creativity reigned. As the algorithmic chains broke, Alex emerged as a quiet revolutionary—a cyber alchemist turning the toxic into transcendent.
### Objective
Develop a small compiler or translator that converts simple C-like code snippets into basic assembly instructions. The primary goal is to familiarize yourself with assembly language mnemonics and to understand how high-level constructs map to low-level operations. This assignment is intentionally minimalistic to ease you into both assembly language and compiler design. If we actually want to be pedantic, this is actually a [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler) implementation.
### Theme
_Simple C Statements → Real Assembly_
The translation should be as simple as possible while covering basic arithmetic operations, register usage, data movement, and control flow constructs. On an lower level, this is what happens in the background when compiling a C program, but it is simplified for easier implementations. If you are really intersted about how a compiler works in reality, we recommend you the 4th year course of [Compilers](https://gitlab.cs.pub.ro/Compilatoare)
## Conventions and Guidelines
Because we want to prevent you from having to juggle with registers, we'll use some simple conventions.
- **Basic Register Mapping:**
- `A``eax`
- `B``ebx`
- `C``ecx`
- `D``edx`
- **Data types**
- We'll assume all of the data types are **4 bytes**
- When you see a number, we will treat it as a int (4 bytes)
- When handling pointers, those will also be stored as 4 bytes
## Instructions
### MOV
The mov instructions is the simplest of all, and as the name says, it moves the data from one place to another. More details here
#### Usage
`MOV destination, source`
#### C - ASM translation
| **C Code** | **ASM Code** |
|------------ |---------------- |
| `a = 1;` | `MOV eax, 1` |
| `b = a;` | `MOV ebx, eax` |
**Note**: There will be no `MOV 2, eax` as that is an invalid operation
### Logical operations
#### Usage
`AND destination, source`
`OR destination, source`
`XOR destination, source`
#### C - ASM translation
| **C Code** | **ASM Code** |
|------------ |---------------- |
| `a = a & 0xFF;` | `AND eax, 0xFF` |
| `b = b \| a` | `OR ebx, eax` |
| `c = a ^ c;` | `XOR ecx, eax` |
### Arithmetic operations
There are 4 aritmetic operations, but we will take them 2 by two, as there are differences between them. The first two, add and sub, are for + and - operations. These work the same way as the MOV instructions.
#### Usage - add, sub
`SUB destination, source`
#### C - ASM translation
| **C Code** | **ASM Code** |
|------------ |---------------- |
| `a = a + 5;` | `ADD eax, 5` |
| `b = b - a;` | `SUB ebx, eax` |
#### Usage - mul, div
`MUL source2`
`DIV divisor`
You might be wondering, why only one operand? Here we have a special rule, and goes something like this:
When multiplying with MUL, the multiplication will actually take EAX and source2 as the multiplication values, and set them in 2 registers -> EDX and EAX. EDX will store the higher values, and EAX the lower one, acting as a big 8 byte register, because after multiplying two 32 bit number, we might have an overflow. Looking at the table will make it a bit clearer.
Similar to MUL, DIV works with EAX as the primary operand, but it also considers EDX as part of the dividend. This means the division is performed using a 64-bit value (EDX:EAX) divided by the given divisor. The result is stored in EAX, while the remainder is placed in EDX.
| **C Code** | **ASM Code** |
|------------ |---------------- |
| `a = a * 3;` | `MUL 3` |
| `b = b * c;` | `MOV eax, ebx` |
| | `MUL ecx` |
| | `MOV ebx, eax` |
| `a = a / 3;` | `MOV eax, a` |
| | `DIV 3` |
| | `MOV a, eax` |
| `b = b / c;` | `MOV eax, ebx` |
| | `DIV ecx` |
| | ` MOV ebx, eax` |
**Note**: For simplicity, we will never use eax as source2, and we will never never use the value from EDX.
If you use the *DIV* instruction with a **divisor of 0**, the processor will generate a **"Divide Error" exception**, and the program will stop if it is not handled.
Since division requires **EDX** to be set up properly, we should always **zero** it before performing DIV if we are working with unsigned values.
### Shift operations
SHL (Shift left) and SHR (Shift right) are bitwise shift instructions.
#### Usage - shl, shr
`SHL destination, no_bits_shifted`
`SHR destination, no_bits_shifted`
- SHL: Moves bits to the left, filling the rightmost bits with zeros. Each shift effectively **multiplies** the value by 2.
- Example: `00001100` (`12` in decimal) shifted left by 1 becomes `00011000` (`24` in decimal).
- SHR: Moves bits to the right, filling the leftmost bits with zeros. Each shift effectively **divides** the value by 2.
- Example: `00001100` (`12` in decimal) shifted left by 1 becomes `00000110` (`6` in decimal).
| **C Code** | **ASM Code** |
|------------- |---------------- |
| `a = a << 1` | `SHL eax, 1` |
| `b = b >> 2` | `SHR ebx, 2` |
### Conditional Statements
#### CMP Instrunction
`CMP` instruction compares two values by substracting the second operand from the first. It updates CPU flags, but does not store the result.
#### Usage - cmp
`CMP operand1, operand2`
- Example:
`MOV eax, 3`
`CMP eax, 3` ; Compares eax with 3
`JE equal_label` ; Jumps to label "equal_label" if eax == 3 (Zero flag is set)
### Jumps
Here's a short description of each conditional jump:
- **JMP** (Jump): Jumps to the given label.
- **JE** (Jump if Equal): Jumps to the given label if the two compared values are equal (e.g.: `CMP` sets the Zero Flag).
- **JNE** (Jump if Not Equal): Jumps if the two values are not equal (Zero Flag is not set).
- **JG** (Jump if Greater): Jumps if the first value is greater than the second (Signed comparison).
- **JGE** (Jump if Greater or Equal): Jumps if the first value is greater than or equal to the second.
- **JL** (Jump if Less): Jumps if the first value is less than the second.
- **JLE** (Jump if Less or Equal): Jumps if the first value is less than or equal to the second.
#### Usage
`JMP label`
`JE label`
`JNE label`
`JG label`
`JL label`
#### C - ASM translation
| **C Code** | **ASM Code** |
|------------- |---------------- |
| `if (a == b) {` | `CMP eax, ebx` |
| | `JNE else_label` |
| `// some code here` | `; some code here` |
| | `JMP end_if` |
| `} else {` | `else_label:` |
| `some other code here` | `; some other code here`|
| `}` | `end_if:` |
### Loops - for, while
#### `for` loop
| **C Code** | **ASM Code** |
|------------- |---------------- |
| `for (a = 0; a < 10; a++) {` | `MOV eax, 0` |
| | `start_loop:` |
| | `CMP eax, 10` |
| | `JGE end_loop` |
| `// some code here` | `; some code here` |
| | `ADD eax, 1` |
| | `JMP start_loop` |
| `}` | `end_loop:` |
#### `while` loop
| **C Code** | **ASM Code** |
|------------- |---------------- |
| `while (b < 5) {` | `start_loop:` |
| | `CMP ebx, 5` |
| | `JGE end_loop` |
| `// some code here` | `; some code that makes b greater than or equal to 5` |
| | `JMP start_loop` |
| `}` | `end_loop:` |
### Coding style
Coding style can be run directly in the checker, by pressing `C`, or by using the
`cs.sh` executable from `checker/cs`. The points are the folowing:
- \>= 10 of `CHECK` => -5 points
- \>= 5 of `WARNING` => -5 points
- \>= 1 of `ERROR` => -10 points
## Notes
- The implementation can be done in any file, and the executable must be named
`transpiler`, situated in the root of the folder, same as the initial makefile does
- For sending the homework, you can use the `make pack` rule, which automatically creates
a zip file with the necesarry content already in it. Don't forget to change your name first
## Checker
> ! Atention, the checker doesn't run valgrind by default, but you must pass all the test
with valgrind in order to get the score. To activate valgrind on your checker, press
`v`, making sure there is a red border which will show that it is on.
### Instalation steps
You can use the `./install.sh` to install all the dependencies and the checker.
If you find any errors along this process, try to follow the steps below:
1. Download rustup using
`curl https://sh.rustup.rs -sSf | sh -s -- -y`. If you get any errors
after this step, add cargo to the PATH variable using `source "$HOME/.cargo/env"`.
2. Run the following command to install the checker
```bash
$> ./binary 3
1 1 1
$ cargo install hw_checker
```
After install, you can use the `hw_checker` command to run the checker.
### Instructiuni checker
For a list of commands and guides for the checker, please read the README from the
`src/` directory. If you have any problems running the GUI, you can use the
`hw_checker --legacy` command to run them in text only mode.
banner.webp

531 KiB

#!/bin/bash
EXECUTABLE="../src/perfect"
TIMEOUT_DURATION=10
SCORE=0
TOTAL_SCORE=0
test_err()
{
local temp_output=''
temp_output="$(mktemp)"
timeout "$TIMEOUT_DURATION" bash -c "$EXECUTABLE > $temp_output 2>&1"
diff -Zq "$temp_output" "./references/ref1" > /dev/null 2>&1
return $?
}
test_single()
{
local temp_output=''
temp_output="$(mktemp)"
timeout "$TIMEOUT_DURATION" xargs -a ./input/input2 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1"
diff -Zq "$temp_output" "./references/ref2" > /dev/null 2>&1
return $?
}
test_multiple()
{
local temp_output=''
temp_output="$(mktemp)"
timeout "$TIMEOUT_DURATION" xargs -a ./input/input3 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1"
diff -Zq "$temp_output" "./references/ref3" > /dev/null 2>&1
return $?
}
test_edge()
{
local temp_output=''
temp_output="$(mktemp)"
timeout "$TIMEOUT_DURATION" xargs -a ./input/input4 -0 -I{} bash -c "$EXECUTABLE {} > $temp_output 2>&1"
diff -Zq "$temp_output" "./references/ref4" > /dev/null 2>&1
return $?
}
setup()
{
pushd ../src > /dev/null || exit 1
make -s build
popd > /dev/null || exit 1
}
cleanup()
{
pushd ../src > /dev/null || exit 1
make -s clean
popd > /dev/null || exit 1
}
test_fun_array=( \
test_err "Name 1" 25 \
test_single "Name 2" 25 \
test_multiple "Name 3" 25 \
test_edge "Name 4" 25 \
)
run_test()
{
test_index="$1"
test_func_index=$((test_index * 3))
description=${test_fun_array[$((test_func_index + 1))]}
points=${test_fun_array[$((test_func_index + 2))]}
TOTAL_SCORE=$((TOTAL_SCORE + points))
echo -ne "Testing\t\t$description\t"
if ${test_fun_array["$test_func_index"]} ; then
SCORE=$((SCORE + points))
echo "$points/$points"
return 0
else
echo "0/$points"
return 1
fi
}
test_all()
{
for i in $(seq 0 "$((${#test_fun_array[@]} / 3 - 1))") ; do
run_test "$i"
done
echo -e "\nTotal: $SCORE/$TOTAL_SCORE"
cd ../src
make clean
ulimit -n 1024
cd ..
hw_checker --legacy
}
setup
if [ -z "$1" ] ; then
test_all
else
run_test "$1"
exit $?
fi
cleanup
test_all
File moved
File added
build:
pack:
zip -r cs.zip README.md cs/cs.sh cs/checkpatch.pl cs/spelling.txt cs/const_structs.checkpatch cs/tests/
clean:
.PHONY: build pack clean
# cs
## Usage
```
$ cs/cs.sh
Usage: cs/cs.sh file
cs/cs.sh directory
$ cs/cs.sh -h
Usage: cs/cs.sh file
cs/cs.sh directory
$ cs/cs.sh cs/tests/10-FUNCTION_TOO_LONG.c
cs/tests/10-FUNCTION_TOO_LONG.c:83: WARNING:LONG_FUNCTION: 'func_not_ok' function definition is 81 lines, perhaps refactor
```
## Tests
```
cs/cs.sh cs/tests/
cs/tests/05-TABS.c:3: WARNING:LEADING_SPACE: please, no spaces at the start of a line
cs/tests/05-TABS.c:8: ERROR:CODE_INDENT: code indent should use tabs where possible
cs/tests/05-TABS.c:8: WARNING:LEADING_SPACE: please, no spaces at the start of a line
cs/tests/09-LINE_TOO_LONG.c:3: CHECK:LONG_LINE_STRING: line length of 91 exceeds 80 columns
cs/tests/03-FUNCTION_WITHOUT_ARGS.c:1: ERROR:FUNCTION_WITHOUT_ARGS: Bad function definition - int main() should probably be int main(void)
cs/tests/04-BLANK_LINES.c:5: CHECK:LINE_SPACING: Please use a blank line after function/struct/union/enum declarations
cs/tests/04-BLANK_LINES.c:9: CHECK:LINE_SPACING: Please use a blank line after function/struct/union/enum declarations
cs/tests/04-BLANK_LINES.c:11: CHECK:BRACES: Blank lines aren't necessary after an open brace '{'
cs/tests/04-BLANK_LINES.c:12: CHECK:LINE_SPACING: Please don't use multiple blank lines
cs/tests/04-BLANK_LINES.c:15: CHECK:LINE_SPACING: Please don't use multiple blank lines
cs/tests/08-EXTRA_WHITESPACE.c:3: WARNING:SPACING: space prohibited before semicolon
cs/tests/08-EXTRA_WHITESPACE.c:4: WARNING:SPACING: space prohibited between function name and open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:4: ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
cs/tests/08-EXTRA_WHITESPACE.c:4: ERROR:SPACING: space prohibited before that close parenthesis ')'
cs/tests/08-EXTRA_WHITESPACE.c:8: ERROR:SPACING: space required one side of that '++' (ctx:WxW)
cs/tests/08-EXTRA_WHITESPACE.c:9: WARNING:SPACING: space prohibited before semicolon
cs/tests/08-EXTRA_WHITESPACE.c:10: WARNING:SPACING: space prohibited between function name and open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:10: ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
cs/tests/08-EXTRA_WHITESPACE.c:10: ERROR:SPACING: space prohibited after that open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:10: ERROR:SPACING: space prohibited before that close parenthesis ')'
cs/tests/08-EXTRA_WHITESPACE.c:11: WARNING:SPACING: space prohibited between function name and open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:11: ERROR:SPACING: space prohibited after that open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:11: ERROR:SPACING: space prohibited before that close parenthesis ')'
cs/tests/08-EXTRA_WHITESPACE.c:19: ERROR:SPACING: space prohibited after that open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:19: ERROR:SPACING: space prohibited before that close parenthesis ')'
cs/tests/08-EXTRA_WHITESPACE.c:20: WARNING:SPACING: space prohibited between function name and open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:20: WARNING:SPACING: space prohibited before semicolon
cs/tests/08-EXTRA_WHITESPACE.c:20: ERROR:SPACING: space prohibited before that close parenthesis ')'
cs/tests/08-EXTRA_WHITESPACE.c:21: WARNING:SPACING: space prohibited between function name and open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:21: WARNING:SPACING: space prohibited before semicolon
cs/tests/08-EXTRA_WHITESPACE.c:21: ERROR:SPACING: space prohibited before that close parenthesis ')'
cs/tests/08-EXTRA_WHITESPACE.c:25: WARNING:SPACING: space prohibited before semicolon
cs/tests/08-EXTRA_WHITESPACE.c:25: ERROR:SPACING: space prohibited after that open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:26: WARNING:SPACING: space prohibited before semicolon
cs/tests/08-EXTRA_WHITESPACE.c:26: ERROR:SPACING: space prohibited after that open parenthesis '('
cs/tests/08-EXTRA_WHITESPACE.c:27: ERROR:SPACING: space prohibited before that close parenthesis ')'
cs/tests/08-EXTRA_WHITESPACE.c:29: WARNING:SPACING: space prohibited before semicolon
cs/tests/10-FUNCTION_TOO_LONG.c:83: WARNING:LONG_FUNCTION: 'func_not_ok' function definition is 81 lines, perhaps refactor
cs/tests/06-TRAILING_WHITESPACE.c:3: ERROR:TRAILING_WHITESPACE: trailing whitespace
cs/tests/06-TRAILING_WHITESPACE.c:7: ERROR:TRAILING_WHITESPACE: trailing whitespace
cs/tests/06-TRAILING_WHITESPACE.c:8: ERROR:TRAILING_WHITESPACE: trailing whitespace
cs/tests/06-TRAILING_WHITESPACE.c:9: ERROR:TRAILING_WHITESPACE: trailing whitespace
cs/tests/06-TRAILING_WHITESPACE.c:12: ERROR:TRAILING_WHITESPACE: trailing whitespace
cs/tests/01-BRACES.c:5: ERROR:OPEN_BRACE: open brace '{' following function definitions go on the next line
cs/tests/01-BRACES.c:7: ERROR:OPEN_BRACE: that open brace { should be on the previous line
cs/tests/01-BRACES.c:12: WARNING:BRACES: braces {} are not necessary for single statement blocks
cs/tests/07-MISSING_WHITESPACE.c:4: ERROR:SPACING: space required after that ',' (ctx:VxO)
cs/tests/07-MISSING_WHITESPACE.c:4: ERROR:SPACING: space required before that '&' (ctx:OxV)
cs/tests/07-MISSING_WHITESPACE.c:6: ERROR:SPACING: spaces required around that '=' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:7: ERROR:SPACING: spaces required around that '=' (ctx:WxV)
cs/tests/07-MISSING_WHITESPACE.c:8: ERROR:SPACING: spaces required around that '=' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:8: ERROR:SPACING: space required after that ';' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:8: ERROR:SPACING: spaces required around that '<' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:8: ERROR:SPACING: space required after that ';' (ctx:VxO)
cs/tests/07-MISSING_WHITESPACE.c:8: ERROR:SPACING: space required before the open brace '{'
cs/tests/07-MISSING_WHITESPACE.c:8: ERROR:SPACING: space required before the open parenthesis '('
cs/tests/07-MISSING_WHITESPACE.c:12: ERROR:SPACING: spaces required around that '+=' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:13: ERROR:SPACING: spaces required around that '=' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:13: CHECK:SPACING: spaces preferred around that '*' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:16: ERROR:SPACING: spaces required around that '>' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:16: ERROR:SPACING: spaces required around that '&&' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:16: ERROR:SPACING: spaces required around that '>' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:17: ERROR:SPACING: spaces required around that '=' (ctx:VxV)
cs/tests/07-MISSING_WHITESPACE.c:19: ERROR:SPACING: space required before the open brace '{'
cs/tests/07-MISSING_WHITESPACE.c:19: ERROR:SPACING: space required before the open parenthesis '('
cs/tests/07-MISSING_WHITESPACE.c:24: ERROR:SPACING: space required before the open brace '{'
cs/tests/07-MISSING_WHITESPACE.c:27: ERROR:SPACING: space required after that close brace '}'
cs/tests/07-MISSING_WHITESPACE.c:27: ERROR:SPACING: space required before the open parenthesis '('
cs/tests/02-SUSPECT_CODE_INDENT.c:4: WARNING:SUSPECT_CODE_INDENT: suspect code indent for conditional statements (4, 4)
```
This diff is collapsed.
#!/bin/bash
CHECKPATCH="$(dirname "$0")/checkpatch.pl"
DOS2UNIX="$(dirname "$0")/.dos2unix"
usage()
{
echo "Usage: $0 file"
echo " $0 directory"
}
check_coding_style()
{
declare -a IGNORED_FLAGS=(
SPLIT_STRING # kernel specific convention
SSCANF_TO_KSTRTO # kernel specific convention
NEW_TYPEDEFS # kernel specific convention
VOLATILE # kernel specific convention
AVOID_EXTERNS # kernel specific convention
CONST_STRUCT # kernel specific convention
NOT_UNIFIED_DIFF # kernel specific convention
SPDX_LICENSE_TAG # kernel specific convention
BLOCK_COMMENT_STYLE # kernel specific convention
EMBEDDED_FUNCTION_NAME # DN -> not required for PC: Prefer using '"%s...", __func__' to using 'main', this function's name, in a string
MALFORMED_INCLUDE # DN -> not required for PC: ERROR:MALFORMED_INCLUDE: malformed #include filename
CONSTANT_COMPARISON # DN -> not required for PC: WARNING:CONSTANT_COMPARISON: Comparisons should place the constant on the right side of the test
TYPO_SPELLING # DN -> not required for PC: CHECK:TYPO_SPELLING: 'alocate' may be misspelled - perhaps 'allocate'?
OPEN_BRACE
BIT_MACRO
)
local ignored_flags_combined=$(printf ",%s" "${IGNORED_FLAGS[@]}")
ignored_flags_combined=${ignored_flags_combined:1}
"${DOS2UNIX}" "${1}" 1> /dev/null 2>&1
"${CHECKPATCH}" \
--no-tree \
--terse \
--show-types \
--no-summary \
--max-line-length=80 \
--tab-size=4 \
--strict \
--ignore "${ignored_flags_combined}" \
-f "${1}"
}
export CHECKPATCH="${CHECKPATCH}"
export DOS2UNIX="${DOS2UNIX}"
export -f check_coding_style
if [ $# -eq 0 ] || [ "$1" = "-h" ]; then
usage 0
elif [ $# -eq 1 ] && [ -f "$1" ]; then
check_coding_style "$1"
else
TARGET_DIR="."
if [ $# -eq 1 ] && [ -d "$1" ]; then
TARGET_DIR="$1"
fi
find "${TARGET_DIR}" -type f -regextype posix-egrep -regex '.*\.(c|h)' -exec bash -c 'check_coding_style "{}"' \;
fi
diff --git a/cs/checkpatch.pl b/cs/checkpatch.pl
index 504d2e4..c351dec 100755
--- a/cs/checkpatch.pl
+++ b/cs/checkpatch.pl
@@ -51,7 +51,7 @@ my %ignore_type = ();
my @ignore = ();
my $help = 0;
my $configuration_file = ".checkpatch.conf";
-my $max_line_length = 100;
+my $max_line_length = 80;
my $ignore_perl_version = 0;
my $minimum_perl_version = 5.10.0;
my $min_conf_desc_length = 4;
@@ -64,7 +64,7 @@ my $color = "auto";
my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
# git output parsing needs US English output, so first set backtick child process LANGUAGE
my $git_command ='export LANGUAGE=en_US.UTF-8; git';
-my $tabsize = 8;
+my $tabsize = 4;
sub help {
my ($exitcode) = @_;
diff --git a/cs/checkpatch.pl b/cs/checkpatch.pl
index 504d2e4..67f22a9 100755
--- a/cs/checkpatch.pl
+++ b/cs/checkpatch.pl
@@ -3551,11 +3551,11 @@ sub process {
$sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) &&
# indentation of previous and current line are the same
(($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) {
- if (WARN("LINE_SPACING",
- "Missing a blank line after declarations\n" . $hereprev) &&
- $fix) {
- fix_insert_line($fixlinenr, "\+");
- }
+ # if (WARN("LINE_SPACING",
+ # "Missing a blank line after declarations\n" . $hereprev) &&
+ # $fix) {
+ # fix_insert_line($fixlinenr, "\+");
+ # }
}
# check for spaces at the beginning of a line.
diff --git a/cs/checkpatch.pl b/cs/checkpatch.pl
index ffce972..d3a163a 100755
--- a/cs/checkpatch.pl
+++ b/cs/checkpatch.pl
@@ -65,6 +65,7 @@ my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANC
# git output parsing needs US English output, so first set backtick child process LANGUAGE
my $git_command ='export LANGUAGE=en_US.UTF-8; git';
my $tabsize = 4;
+my $max_function_length = 80;
sub help {
my ($exitcode) = @_;
@@ -2375,6 +2376,7 @@ sub process {
my $realcnt = 0;
my $here = '';
my $context_function; #undef'd unless there's a known function
+ my $context_function_linenum;
my $in_comment = 0;
my $comment_edge = 0;
my $first_line = 0;
@@ -2522,9 +2524,11 @@ sub process {
$suppress_statement = 0;
if ($context =~ /\b(\w+)\s*\(/) {
$context_function = $1;
+ $context_function_linenum = $realline;
} else {
undef $context_function;
}
+ undef $context_function_linenum;
next;
# track the line number as we move through the hunk, note that
@@ -3585,11 +3589,19 @@ sub process {
if ($sline =~ /^\+\{\s*$/ &&
$prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) {
$context_function = $1;
+ $context_function_linenum = $realline;
}
# check if this appears to be the end of function declaration
if ($sline =~ /^\+\}\s*$/) {
+ if (defined($context_function_linenum) &&
+ ($realline - $context_function_linenum) > $max_function_length) {
+ WARN("LONG_FUNCTION",
+ "'$context_function' function definition is " . ($realline - $context_function_linenum) . " lines, perhaps refactor\n" . $herecurr);
+ }
+
undef $context_function;
+ undef $context_function_linenum;
}
# check indentation of any line with a bare else
@@ -6417,6 +6429,7 @@ sub process {
defined $stat &&
$stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
$context_function = $1;
+ $context_function_linenum = $realline;
# check for multiline function definition with misplaced open brace
my $ok = 0;
This diff is collapsed.
## Update checkpatch.pl
```
wget https://raw.githubusercontent.com/torvalds/linux/master/scripts/checkpatch.pl
mv checkpatch.pl > cs/checkpatch.pl
git add cs/checpatch.pl
git commit -m "checkpatch.pl: update to latest master version"
for patch in $(ls -v cs/patches); do git apply < cs/patches/${patch}; done
```