diff --git a/.gitignore b/.gitignore index 4c94a4c..fe633f6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,12 @@ *.exe *.out *.log -**_** *.tclPreview +*.DS_Store **~** ~* *.o -*.orig \ No newline at end of file +*.orig +**/debug/ +**/release/ +*.stackdump \ No newline at end of file diff --git a/Generate-Wiki/definitions.m4 b/Generate-Wiki/definitions.m4 deleted file mode 100644 index c60aa1e..0000000 --- a/Generate-Wiki/definitions.m4 +++ /dev/null @@ -1,19 +0,0 @@ -changequote({{,}}) -dnl# root definitions import first -dnl#syscmd(echo "Author: " | tr -d '\n')dnl -dnl#pushdef({{__author__}}, esyscmd(read AUTHOR && echo $AUTHOR | tr -d '\n'))dnl -pushdef({{__author__}}, {{Betsalel (Saul) Williamson}}))dnl -dnl -dnl -dnl#syscmd(echo "Author Email: " | tr -d '\n')dnl -dnl#pushdef({{__author_email__}}, esyscmd(read AUTHOR_EMAIL && echo $AUTHOR_EMAIL | tr -d '\n'))dnl -pushdef({{__author_email__}}, {{saul.williamson@ieee.org}}))dnl -dnl -dnl -pushdef({{__wiki_licence__}}, {{CC BY 4.0 license}})dnl -pushdef({{__wiki_licence_full__}}, {{Creative Commons 4.0 Attribution License}})dnl -pushdef({{__wiki_licence_web_address__}}, {{https://creativecommons.org/licenses/by/4.0/}})dnl -dnl -dnl -pushdef({{__project_repo__}}, {{https://github.com/betsalel-williamson/Programming-Tutorial.git}})dnl -pushdef({{__project_repo_name__}}, {{Programming-Tutorial}})dnl diff --git a/Notes.md b/Notes.md new file mode 100644 index 0000000..8bf10d7 --- /dev/null +++ b/Notes.md @@ -0,0 +1,134 @@ +THE FOLLOWING INFORMATION IS IN DRAFT AND NOT YET RATIFIED BY THE PROJECT TEAM THE INFORMATION WILL BE RATIFIED IN THE MONTH OF JULY 2021 + +# Project Goals + +Whereby coding tutorials and resources on the Internet may be helpful to an experienced programmer, there can be information that is considered "understood" or "implicit". This is a barrier to learning. + +Whereby many programming languages and frameworks offer features that are "nice to have" or "cool", these features can be a stumbling block for those learning to code. In addition, certain programming languages and frameworks have features that prevent projects from scaling up. + +Whereby early-career professionals are familiar with the early stages of learning to code and are looking for outlets to volunteer, there is a need for a project to provide opportunities and a low-pressure environment to network and further professional growth. + +Whereby the college students in the IEEE Pittsburgh Section area have expressed interest in attending coding workshops and access to coding resources and the IEEE Pittsburgh Student Activities Committee is committed to: +1. Create virtual activities that interest students +2. Develop and deploy a strategy and plan for first-year undergraduate and graduate student members + +Therefore, the following goals have been established: + +1. Provide a free, public learning resource including virtual or in-person workshops for learners 2 times a year. These events will be hosted by multiple facilitators and encourage learning and professional growth for all involved. +1. Identify and fill in gaps in coding tutorials. Help create order out of the chaos in coding tutorials and other coding resources on the Internet. +1. For the selected programming languages and frameworks, identify best practices and highlight what features to use and what features to avoid. +1. Meet as a group at least once a month to review progress, outline action items, and assist each other with finding professional fulfillment through participation in this project. + 1. Meetings will be hosted on vtools.ieee.org and will be posted online 4 weeks before the date of the event. + 1. An agenda will be posted at least 5 days in advance of the meeting. + 1. Agenda items will be pulled from the GitHub issues for the project or other items submitted to the Project Lead ahead of the meeting and must be received by the Project Lead at least 8 days before the meeting to be added to the agenda. + +## Minimum requirements to join as a contributor + +Currently, the project is hosting a virtual "open house" to gauge interest and find volunteers. + +You may request to join the project, but must be approved by the project lead (see below for the current project lead information). This process will help ensure that the project expectations are understood and that they align with your expectations for what you hope to get out of the project. At a minimum, you must set up a time to talk over video chat with the leadership team and provide us access to a volunteering or other professional resume/CV. + +This project is posted on the Internet and includes open license terms for others to fork the project. While this is possible, we request that you first ask to join the project before splintering off. + +## Project Leadership + +Project Lead: +- Saul Williamson + +Founding Members: +- Alexis B. +- Andre G. +- Ava C. +- Avram A. +- Jenna D. +- Keting Z. +- Miriam W. +- Rachel M. +- Sam D. + +# Meetings + +## Upcoming: + +- March 9 2021 https://events.vtools.ieee.org/m/261965 + +## February 8, 2021 + +Meeting link: https://events.vtools.ieee.org/m/257072 + +### Attendance: +- Miriam W. +- Sam D. +- Avram A. +- Alexis B. +- Saul W. + +## Agenda: + +See below agenda for January 25, 2021. + +### Minutes: + +The group provided introductions including experiences with coding. The conversation centered around the soft-skills that would benefit engineers. There was also the strong feeling that "stick-to-it-ness" is required in this industry and there is often hit-or-miss for events offered to students. The root cause for students not engaging in events or taking way important skills was not identified. Nonetheless, an event that holds net benefit for single attendee should be considered a measure of success for the event. + +The outline for how to acheive teaching soft-skills still needs to be outlined. + +Alexis shared about the TechGirlz organization. Saul signed up and will investigate if there is a possible collaboration or way to benefit from the existing efforts by this organization. + +## January 25, 2021 + +Meeting link: https://events.vtools.ieee.org/m/257070 + +### Attendance: +- Andre G. +- Ava C. +- Keting Z. +- Rachel M. +- Saul W. + +### Agenda: + +Betsalel (Saul) Williamson, a member of the IEEE Pittsburgh Student Activities Committee, is looking for you, a passionate engineer (at any stage of your career), to volunteer and assist with development of a coding tutorial designed for first-year college students and early-career engineers. + +This is a collaborative effort built to help others propel their understanding of coding and help pass on industry know-how including practical skills in version control, automated testing, and documentation. + +If you are interested or want to hear more, sign up for the virtual QA on January 25th and February 8th to learn how you can get involved. We are looking for a wide range, and depends on the interest. For a minimal commitment, just showing up to support discussions, review content, or if you want to take lead on authoring content that could be more involved. + +This is a great opportunity to meet other engineers and to bolster your resume. + +Link to event on January 25th 7-8 p.m Eastern +https://events.vtools.ieee.org/m/257070 + +Link to event on February 8th 7-8 p.m Eastern +https://events.vtools.ieee.org/m/257072 + +The current iteration of the tutorial is at https://github.com/betsalel-williamson/Programming-Tutorial/wiki . + +The unique edge for this tutorial is that it has a high attention to detail and includes broader instructions so that those new to programming not only have the information to get their machine setup, but can learn industry best practices that usually aren't spelled out in classes and during internships. + +The tutorial was initially developed in 2018 by Saul in collaboration with the University of Pittsburgh's Student Electronics Resource Center https://sercpitt.weebly.com/ to help students fill in the gaps. The tutorial helped a dozen IEEE students increase their understanding of C and how to build automated tests with TCL. + +### Minutes: + +Group discussed initial goals and outline for the collaborative project. There are items to sort out and explore regarding the future direction of the project including minimum system requirements and expectations for the end user. + +#### Additional ideas discussed included: +- Jupyter notebooks +- We don't need to reinvent the wheel. We can use examples available on the Internet, but creating an outline to prioritize materials so that it is easier to learn. +- The tutorials should leverage what we know and help those who are learning +- We need to outline when to use specific coding tools and when not to +- The ability to meet in person and provide food in the future is exciting +- We can use GitHub issues to project manage and keep track of progress and work items +- Providing workshops are helpful and allow those who are looking to learn the ability to reach out to a person for help. A lot of Internet forums are perceived to be insular and unwelcoming. + + + +# Notes for Programming Tutorial + +- [ ] make templates to make it easier to manage in the long run +- [ ] create contribution guidelines +- [x] invite others to contribute (1/1/2021, on linkedin) +- [ ] replace `sed` commands with a search for first line and `n` lines afterwards to avoid needing to worry about rewriting examples +- [ ] need list of pre-reqs for building the source `M4`, `astyle` ... +- [ ] https://www.tcl.tk/doc/styleGuide.pdf is helpful, add it to the tutorial appendix +- [ ] implement fix for makefiles, need to have broken and fixed versions so that the wiki instructions make sense diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..0327a2b --- /dev/null +++ b/build.sh @@ -0,0 +1,87 @@ +#! env sh +# filename: generate_docs.sh + +# TODO: validate assumptions here... + +# ensure that we start executing in +# the script's location +pushd $(dirname $0) > /dev/null 2>&1 + +# TODO: check that there are no arguments... + +# TODO: check for Programming-Tutorial.wiki +# find ../ -name .git +# get the different names ... +# config should download the wiki +# Possibly: basename -s .git `git config --get remote.origin.url` +# https://stackoverflow.com/questions/15715825/how-do-you-get-the-git-repositorys-name-in-some-git-repository +# +# $ find ../ -name .git -exec sh -c 'basename $(cat $0/config | perl -lane "print /= (.*)[.]git/")' {} \; +# Programming-Tutorial.wiki +# Programming-Tutorial +# + +# TODO: have the wiki repository cloned at ../../Programming-Tutorial.wiki +# we don't need to worry about the name, just that it should +# be there... + +pushd ./templates-code > /dev/null 2>&1 + +# format code +astyle "./*.c.m4" "./*.h.m4" \ +--indent=spaces=2 \ +--indent-switches \ +--indent-after-parens \ +--break-blocks \ +--pad-oper \ +--pad-comma \ +--pad-paren-in \ +--break-one-line-headers \ +--add-braces \ +--add-one-line-braces \ +--max-code-length=80 \ +--mode=c \ +--recursive \ +--verbose + +# find the md.m4 files +# for each file, +# run the m4 command +# to do this we need to rename the files from *.md.m4 to *.md +# and place these files in the result directory + +find . -name "*.m4" -exec sh -c 'rename=$(echo "$0" | perl -lane "print /(.*)[.]m4/"); mkdir -p $(dirname "../src/$rename"); m4 ../definitions.m4 "$(realpath "$0")" > "../src/$rename"' {} \; +mv ../src/README.md ../ +popd > /dev/null 2>&1 + +pushd ./src > /dev/null 2>&1 + +# ensure that tcl scripts can be executed +find . -name "*.tcl" -exec chmod +x {} \; + +# run test files +find . -name "test*.tcl" -exec sh -c 'echo "Running test: ($(basename "$0")) in ($(dirname "$0"))"; pushd "$(dirname "$0")" > /dev/null 2>&1; ./$(basename "$0"); popd > /dev/null 2>&1' {} \; + +# TODO: clean up output format of test files + +popd > /dev/null 2>&1 + +# we call the realpath command for the wiki so that it fails fast +# if the wiki directory does not exist +pushd ./templates-wiki > /dev/null 2>&1 + +# TODO: replace '../../Programming-Tutorial.wiki' with location of wiki +# it may not be 'Programming-Tutorial.wiki' because the user can +# clone a repo into any folder... + +find . -name "*.m4" -exec sh -c 'rename=$(echo "$0" | perl -lane "print /(.*)[.]m4/"); m4 ../definitions.m4 "$(realpath "$0")" > "$(realpath "../../Programming-Tutorial.wiki/$rename")"' {} \; +popd > /dev/null 2>&1 + +# TODO: check all links to see that they are valid... +# print a list of links and basic context (from file, line) +# output to MD file and save to a temp file + +# TODO: comb through and add all "todo's" to the Notes file. +# TODO: remove todo's from output + +popd > /dev/null 2>&1 # go back to where ever... \ No newline at end of file diff --git a/definitions.m4 b/definitions.m4 new file mode 100644 index 0000000..b4dd92a --- /dev/null +++ b/definitions.m4 @@ -0,0 +1,45 @@ +changequote({{,}})dnl +dnl# root definitions import first +dnl#syscmd(echo "Author: " | tr -d '\n')dnl +dnl#pushdef({{__author__}}, esyscmd(read AUTHOR && echo $AUTHOR | tr -d '\n'))dnl +pushdef({{__author__}}, {{Betsalel (Saul) Williamson}})dnl +dnl +dnl +dnl#syscmd(echo "Author Email: " | tr -d '\n')dnl +dnl#pushdef({{__author_email__}}, esyscmd(read AUTHOR_EMAIL && echo $AUTHOR_EMAIL | tr -d '\n'))dnl +pushdef({{__author_email__}}, {{saul.williamson@ieee.org}})dnl +dnl +dnl +pushdef({{__wiki_licence__}}, {{CC BY 4.0 license}})dnl +pushdef({{__wiki_licence_full__}}, {{Creative Commons 4.0 Attribution License}})dnl +pushdef({{__wiki_licence_web_address__}}, {{https://creativecommons.org/licenses/by/4.0/}})dnl +dnl +dnl +pushdef({{__project_repo_root__}}, {{https://github.com/betsalel-williamson/Programming-Tutorial}})dnl +pushdef({{__project_repo__}}, {{__project_repo_root__{{}}.git}})dnl +pushdef({{__project_repo_source_root__}}, {{__project_repo_root__{{}}/tree/main/src}})dnl +pushdef({{__project_repo_name__}}, {{Programming-Tutorial}})dnl +pushdef({{__code_license_header__}}, {{The author disclaims copyright to this source code. In place of +a legal notice, here is a blessing: + May you do good and not evil. + May you find forgiveness for yourself and forgive others. + May you share freely, never taking more than you give.}})dnl +pushdef({{__code_license_header_hash_style__}}, {{# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give.}})dnl +pushdef({{__code_license_header_c__}}, {{/* +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +*/}})dnl +pushdef({{__code_license_header_markdown__}}, {{In place of a legal notice, here is a blessing: +- May you do good and not evil. +- May you find forgiveness for yourself and forgive others. +- May you share freely, never taking more than you give.}})dnl +pushdef({{__project_under_construction_flag__}}, {{# Warning !!! This tutorial is currently under construction... Proceed at your own risk +}})dnl diff --git a/T1/step-1-setup/windows-setup.cmd b/src/T1/step-1-setup/windows-setup.cmd similarity index 83% rename from T1/step-1-setup/windows-setup.cmd rename to src/T1/step-1-setup/windows-setup.cmd index ada2c73..d5b8377 100644 --- a/T1/step-1-setup/windows-setup.cmd +++ b/src/T1/step-1-setup/windows-setup.cmd @@ -39,6 +39,20 @@ if not exist %cygwinPath% ( :: double-check that Cygwin was installed to the correct path if not exist %cygwinPath%\bin echo %cygwinPath%\bin not found. Check Cygwin installation path. && exit /B +:: TODO: Check the Path length to see if +:: adding would exceed the max length. +:: MAX_PATH, which is defined as 260 +:: If so, then alert the user to edit +:: the path first then run again. +:: +:: Possible solution from: +:: https://stackoverflow.com/questions/5837418/how-do-you-get-the-string-length-in-a-batch-file/8566001#8566001 +:: set tempPath="%USERPROFILE%\AppData\Local\Temp\win-setup-path.txt" +:: (ECHO %PATH%)> %tempPath% +:: FOR %%? IN (%tempPath%) DO ( SET /A strlength=%%~z? - 2 ) +:: del %tempPath% +:: if strlength + :: check to see that the environmental variables have the cygwin path echo %PATH% | find /i "%cygwinPath%\bin" > nul && set CYGWIN_PATH_BIN_SET=TRUE || set CYGWIN_PATH_BIN_SET= if defined CYGWIN_PATH_BIN_SET ( @@ -48,9 +62,6 @@ if defined CYGWIN_PATH_BIN_SET ( :: BUG, Does not check the Path length first to ensure that :: the Cygwin bin path can be added. -:: TODO: Check the Path length to see if -:: adding would exceed the max length. If so then -:: alert the user to edit the path first then run again. :: then install Git, TCL, Expect, GCC and other developer programs echo Updating Cygwin to latest and installing development programs... diff --git a/src/T1/step-2-command-line-101/hello-world-fixed.tcl b/src/T1/step-2-command-line-101/hello-world-fixed.tcl new file mode 100755 index 0000000..58c1d10 --- /dev/null +++ b/src/T1/step-2-command-line-101/hello-world-fixed.tcl @@ -0,0 +1,33 @@ +#!/usr/bin/env expect +# This first line is called a shebang (pronounced Sha-Bang) and +# will tell the shell what program to use for the following text. + +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. + +spawn echo "Hello World from TCL/Expect!" + +# What can we do to make this command exit with success? +# There are multiple ways to go about this. +# Method one, is to simply change the text in the expect +# command from "Hello world." to "Hello World from TCL/Expect!" +# Method two is to change the text to be more flexible +# and replace "Hello world." with the text +# "Hello World from TCL/Expect!" or with `-nocase "hello world"`. +# The '-nocase' argument allows the check to ignore the +# case of the text so it could be upper or lower case. + +# Method two: +expect { + -nocase "hello world" { + puts "Success!" + exit 0 + } + default { + puts "Error!" + exit 1 + } +} diff --git a/src/T1/step-2-command-line-101/hello-world.tcl b/src/T1/step-2-command-line-101/hello-world.tcl new file mode 100755 index 0000000..62f83b9 --- /dev/null +++ b/src/T1/step-2-command-line-101/hello-world.tcl @@ -0,0 +1,33 @@ +#!/usr/bin/env expect +# This first line is called a shebang (pronounced Sha-Bang) and +# will tell the shell what program to use for the following text. + +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. + +# Our first line of code we tell the expect program to run a program! +# The program to run is `echo`. +# The echo program will display text to the shell, in this case +# that is "Hello World from TCL/Expect!" +spawn echo "Hello World from TCL/Expect!" + +# This next command `expect` (which is the same name as the program) +# will look at the shell and follow a command that you tell it to. +# We are looking to see the words "Hello world." and if we do +# then we output "Success!" to the shell and exit with the +# value 0. +# If we don't see the words "Hello world." then we will output +# "Error!" and exit with the value 1. +expect { + "Hello world from." { + puts "Success!" + exit 0 + } + default { + puts "Error!" + exit 1 + } +} diff --git a/T1/step-3-version-control-101/download-repository.tcl b/src/T1/step-3-version-control-101/download-repository.tcl old mode 100644 new mode 100755 similarity index 100% rename from T1/step-3-version-control-101/download-repository.tcl rename to src/T1/step-3-version-control-101/download-repository.tcl diff --git a/T1/step-3-version-control-101/hello-world.tcl b/src/T1/step-3-version-control-101/hello-world.tcl similarity index 100% rename from T1/step-3-version-control-101/hello-world.tcl rename to src/T1/step-3-version-control-101/hello-world.tcl diff --git a/T1/step-4-hello-world/1-Hello-World/main.c b/src/T1/step-4-hello-world/1-Hello-World/main.c similarity index 99% rename from T1/step-4-hello-world/1-Hello-World/main.c rename to src/T1/step-4-hello-world/1-Hello-World/main.c index 4395f01..16e0451 100644 --- a/T1/step-4-hello-world/1-Hello-World/main.c +++ b/src/T1/step-4-hello-world/1-Hello-World/main.c @@ -1,12 +1,3 @@ -/* -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -*/ - /* * Welcome to your first program in C. This program will output "Hello World" to * the shell when run. @@ -18,6 +9,16 @@ * * Single line comments are written after double forward slashes `//` */ + +/* +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +*/ + int main ( ) { // Programming language of C requires a function named `main` that returns diff --git a/src/T1/step-4-hello-world/2-Test-Hello-World/.gitignore b/src/T1/step-4-hello-world/2-Test-Hello-World/.gitignore new file mode 100644 index 0000000..9d780a1 --- /dev/null +++ b/src/T1/step-4-hello-world/2-Test-Hello-World/.gitignore @@ -0,0 +1,7 @@ +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. + +main \ No newline at end of file diff --git a/src/T1/step-4-hello-world/2-Test-Hello-World/main-fixed.c b/src/T1/step-4-hello-world/2-Test-Hello-World/main-fixed.c new file mode 100644 index 0000000..cb966b7 --- /dev/null +++ b/src/T1/step-4-hello-world/2-Test-Hello-World/main-fixed.c @@ -0,0 +1,68 @@ +/* + * Welcome to your second program in C. + * + * In this program you will modify the code from your first program + * to accept a parameter or argument as input from the Shell. + * + */ + +/* +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +*/ + +int main ( int argc, const char* argv[] ) { + + // argc is the number of arguments passed into the program + // argv is the array (think a list) of arguments + // We access the items in the array by putting a number between + // the square brackets. In C, we call this number an index. + // This is very important because indexes will always start + // with 0. You can think of this in terms of number types. + // In math, the natural numbers start with 1 and increase. + // Indexes start at 0 and will increase until the number of + // items in the array minus 1. + + int exit_value = -1; + // we set this exit value to be -1 so we can know if the + // program exits unexpectedly before being able to set + // the value 0, or 1 as will be shown later on. + + // ensure the correct number of parameters are used. + if ( argc == 2 ) { + int i = 0; // declare a variable to count the length + // of the text passed in as an argument + + // In C, all properly formmated strings end with + // the character '\0'. To get the length of the text, + // or string, we start at the first index value 0. + while( argv[1][i] != '\0' ) { + i = i + 1; + } + + write( 1, argv[1], i ); + + // What do you think the zeroth item or element + // in argv is? + + // i = 0; // reset i to be 0 + + // while(argv[0][i] != '\0') { + // i = i+1; + // } + + // write(1, argv[0], i); + + exit_value = 0; + } else { + // if the incorrect number of parameters are used + // then report that there was an error + exit_value = 1; + } + + return exit_value; +} diff --git a/src/T1/step-4-hello-world/2-Test-Hello-World/main.c b/src/T1/step-4-hello-world/2-Test-Hello-World/main.c new file mode 100644 index 0000000..a1997b0 --- /dev/null +++ b/src/T1/step-4-hello-world/2-Test-Hello-World/main.c @@ -0,0 +1,25 @@ +/* +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +*/ + +int main ( int argc, const char* argv[] ) { + int exit_value = -1; + + if ( argc == 2 ) { + + while( argv[1][i] != '\0' ) { + i = i + 1; + } + + exit_value = 0 + } else { + exit_value = 1; + } + + return exit_value; +} \ No newline at end of file diff --git a/src/T1/step-4-hello-world/2-Test-Hello-World/test.tcl b/src/T1/step-4-hello-world/2-Test-Hello-World/test.tcl new file mode 100755 index 0000000..36a5979 --- /dev/null +++ b/src/T1/step-4-hello-world/2-Test-Hello-World/test.tcl @@ -0,0 +1,66 @@ +#!/usr/bin/env expect + +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. + +# delete the executable file +if { [file exists main] == 1 } { + exec rm main +} + +# compile the file +exec gcc -w main-fixed.c -o main + +### Test 1 ### +# +# Given that we provide a single text input to our program, +# When we run it, +# Then the program will print the text to the Shell +# and exits with the value 0 +# + +spawn ./main "Hello World" +expect { + -nocase "hello world" { + puts "\nFound output of: Hello World\n" + } + default { + puts "\nTest failed. Expected Hello world\n" + } +} + +expect eof +catch wait result +if {[lindex $result 3] == 0} { + puts "Exited successfully.\n" +} else { + puts "Test failed with code [lindex $result 3].\n" +} + +### Test 2 ### +# +# Given that we don't provide a single text input to our +# program, +# When we run it, +# Then the program exits without printing the input and +# has the value 1 +# + +spawn ./main +expect eof +catch wait result + +if {[lindex $result 3] == 1} { + puts "Exited successfully.\n" +} else { + puts "Test failed with code [lindex $result 3].\n" +} + +# What happens when we try calling main +# with more than 1 parameter? +# $ ./main Hello World +# Hello world must be in quotes in order for this +# to be considered a single parameter diff --git a/src/T1/step-4-hello-world/3-Makefile-Hello-World/.gitignore b/src/T1/step-4-hello-world/3-Makefile-Hello-World/.gitignore new file mode 100644 index 0000000..9d780a1 --- /dev/null +++ b/src/T1/step-4-hello-world/3-Makefile-Hello-World/.gitignore @@ -0,0 +1,7 @@ +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. + +main \ No newline at end of file diff --git a/T1/step-4-hello-world/3-Makefile-Hello-World/main.c b/src/T1/step-4-hello-world/3-Makefile-Hello-World/main-fixed.c similarity index 100% rename from T1/step-4-hello-world/3-Makefile-Hello-World/main.c rename to src/T1/step-4-hello-world/3-Makefile-Hello-World/main-fixed.c index f157f83..dc524ab 100644 --- a/T1/step-4-hello-world/3-Makefile-Hello-World/main.c +++ b/src/T1/step-4-hello-world/3-Makefile-Hello-World/main-fixed.c @@ -1,3 +1,11 @@ +/* + * Welcome to your second program in C. + * + * In this program you will modify the code from your first program + * to accept a parameter or argument as input from the Shell. + * + */ + /* ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -7,14 +15,6 @@ ** May you share freely, never taking more than you give. */ -/* - * Welcome to your second program in C. - * - * In this program you will modify the code from your first program - * to accept a parameter or argument as input from the Shell. - * - */ - #include int main ( int argc, const char* argv[] ) { diff --git a/src/T1/step-4-hello-world/3-Makefile-Hello-World/main.c b/src/T1/step-4-hello-world/3-Makefile-Hello-World/main.c new file mode 100644 index 0000000..50a32f9 --- /dev/null +++ b/src/T1/step-4-hello-world/3-Makefile-Hello-World/main.c @@ -0,0 +1,65 @@ +/* + * Welcome to your second program in C. + * + * In this program you will modify the code from your first program + * to accept a parameter or argument as input from the Shell. + * + */ + +/* +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +*/ + +int main ( int argc, const char* argv[] ) { + + // argc is the number of arguments passed into the program + // argv is the array (think a list) of arguments + // We access the items in the array by putting a number between + // the square brackets. In C, we call this number an index. + // This is very important because indexes will always start + // with 0. You can think of this in terms of number types. + // In math, the natural numbers start with 1 and increase. + // Indexes start at 0 and will increase until the number of + // items in the array minus 1. + int exit_value; + + // ensure the correct number of parameters are used. + if ( argc == 2 ) + { + int i = 0; // declare a variable to count the length + // of the text passed in as an argument + + // In C, all text ends with the character '\0'. + // To get the length of the text, or string, we + // start at the first index + while( argv[1][i] != '\0' ) { + i = i + 1; + } + + write( 1, argv[1], i ); + + // What do you think the zeroth item or element + // in argv is? + + // i = 0; // reset i to be 0 + + // while(argv[0][i] != '\0') { + // i = i+1; + // } + + // write(1, argv[0], i); + + exit_value = 0; + } else { + // if the incorrect number of parameters are used + // then report that there was an error + exit_value = 1; + } + + return exit_value; +} diff --git a/T2/step-2-brute-force/makefile b/src/T1/step-4-hello-world/3-Makefile-Hello-World/makefile similarity index 93% rename from T2/step-2-brute-force/makefile rename to src/T1/step-4-hello-world/3-Makefile-Hello-World/makefile index 48da4ac..b325058 100644 --- a/T2/step-2-brute-force/makefile +++ b/src/T1/step-4-hello-world/3-Makefile-Hello-World/makefile @@ -5,7 +5,7 @@ # May you share freely, never taking more than you give. CC = gcc -SRCS = main.c +SRCS = main-fixed.c OBJS = $(subst .c,.o,$(SRCS)) CFLAGS = -Wall -Werror -Wextra RM = rm -f @@ -17,7 +17,7 @@ debug: main main: $(OBJS) $(CC) -o main $(OBJS) $(CFLAGS) -main.o: main.c +main.o: main-fixed.c # We don't glob because this doesn't scale for # large projects diff --git a/T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl b/src/T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl old mode 100644 new mode 100755 similarity index 98% rename from T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl rename to src/T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl index 632def8..93e0c77 --- a/T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl +++ b/src/T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl @@ -1,4 +1,4 @@ -#!/bin/env expect +#!/usr/bin/env expect # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: diff --git a/T2/step-1-code-gen/.gitignore b/src/T2/step-1-code-gen/.gitignore similarity index 100% rename from T2/step-1-code-gen/.gitignore rename to src/T2/step-1-code-gen/.gitignore diff --git a/T2/step-1-code-gen/lib.c b/src/T2/step-1-code-gen/lib.c similarity index 100% rename from T2/step-1-code-gen/lib.c rename to src/T2/step-1-code-gen/lib.c diff --git a/T2/step-1-code-gen/lib.h b/src/T2/step-1-code-gen/lib.h similarity index 100% rename from T2/step-1-code-gen/lib.h rename to src/T2/step-1-code-gen/lib.h diff --git a/T2/step-1-code-gen/macrologger.h b/src/T2/step-1-code-gen/macrologger.h similarity index 99% rename from T2/step-1-code-gen/macrologger.h rename to src/T2/step-1-code-gen/macrologger.h index 7c36361..f53fa49 100644 --- a/T2/step-1-code-gen/macrologger.h +++ b/src/T2/step-1-code-gen/macrologger.h @@ -120,4 +120,4 @@ static inline void objc_print( NSString *format, ... ) { #endif -#endif \ No newline at end of file +#endif diff --git a/T2/step-1-code-gen/main.c b/src/T2/step-1-code-gen/main.c similarity index 97% rename from T2/step-1-code-gen/main.c rename to src/T2/step-1-code-gen/main.c index 2d98984..e603581 100644 --- a/T2/step-1-code-gen/main.c +++ b/src/T2/step-1-code-gen/main.c @@ -1,3 +1,5 @@ +/* Simple program to demonstrate c */ + /* ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: diff --git a/T2/step-1-code-gen/makefile b/src/T2/step-1-code-gen/makefile similarity index 100% rename from T2/step-1-code-gen/makefile rename to src/T2/step-1-code-gen/makefile diff --git a/T2/step-1-code-gen/test.tcl b/src/T2/step-1-code-gen/test.tcl old mode 100644 new mode 100755 similarity index 99% rename from T2/step-1-code-gen/test.tcl rename to src/T2/step-1-code-gen/test.tcl index 509d8a5..93da2ad --- a/T2/step-1-code-gen/test.tcl +++ b/src/T2/step-1-code-gen/test.tcl @@ -1,4 +1,5 @@ #!/usr/bin/env expect + # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # May you do good and not evil. @@ -75,6 +76,8 @@ proc testInvalidInput args { } } +exec make prep + if {[catch {exec make debug} result] == 0} { testMustProvideCode testProvidedCode diff --git a/T2/step-1-pointers/.gitignore b/src/T2/step-1-pointers/.gitignore similarity index 100% rename from T2/step-1-pointers/.gitignore rename to src/T2/step-1-pointers/.gitignore diff --git a/T2/step-1-pointers/main.c b/src/T2/step-1-pointers/main.c similarity index 100% rename from T2/step-1-pointers/main.c rename to src/T2/step-1-pointers/main.c diff --git a/T1/step-4-hello-world/3-Makefile-Hello-World/makefile b/src/T2/step-1-pointers/makefile similarity index 100% rename from T1/step-4-hello-world/3-Makefile-Hello-World/makefile rename to src/T2/step-1-pointers/makefile diff --git a/T2/step-2-brute-force/.gitignore b/src/T2/step-2-brute-force/.gitignore similarity index 100% rename from T2/step-2-brute-force/.gitignore rename to src/T2/step-2-brute-force/.gitignore diff --git a/T2/step-2-brute-force/main.c b/src/T2/step-2-brute-force/main.c similarity index 100% rename from T2/step-2-brute-force/main.c rename to src/T2/step-2-brute-force/main.c diff --git a/T2/step-1-pointers/makefile b/src/T2/step-2-brute-force/makefile similarity index 100% rename from T2/step-1-pointers/makefile rename to src/T2/step-2-brute-force/makefile diff --git a/test.tcl b/src/test.tcl similarity index 85% rename from test.tcl rename to src/test.tcl index 127491a..4f0f719 100755 --- a/test.tcl +++ b/src/test.tcl @@ -1,24 +1,12 @@ #!/usr/bin/env expect # Test the tutorial +# run from the 'src' directory -# run from the base directory - -# format code -astyle "./*.c" "./*.h" \ ---indent=spaces=2 \ ---indent-switches \ ---indent-after-parens \ ---break-blocks \ ---pad-oper \ ---pad-comma \ ---pad-paren-in \ ---break-one-line-headers \ ---add-braces \ ---add-one-line-braces \ ---max-code-length=80 \ ---mode=c \ ---recursive \ ---verbose +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. # test files set t1step1file "./T1/step-1-setup/windows-setup.cmd" diff --git a/templates-code/README.md.m4 b/templates-code/README.md.m4 new file mode 100644 index 0000000..b40d861 --- /dev/null +++ b/templates-code/README.md.m4 @@ -0,0 +1,22 @@ +# Programming Tutorial +This project is a basic programming. The target audience is for those who may be beginning to learn programming or have already taken an introductory programming course. + +This tutorial walks through the creation of a program that generates a passcode and then a second program that is brute-force passcode cracking program! The tutorials don't assume much. Unlike other tutorials, it teaches important best practices like configuraiton control, developing build procedures, and testing your code. Lastly, you can follow this tutorial on any operating system (Windows, Linux, or Mac). + +The tutorial is located at <{{}}__project_repo_root__{{}}/wiki>. + +The author disclaims copyright to this source code and the tutorial may be freely shared with the [{{}}__wiki_licence__{{}}]({{}}__wiki_licence_web_address__{{}}). To share, please include the following in any slides or documents: + +``` +The tutorial is reproduced or modified from work created and shared by __author__ <{{}}__author_email__{{}}> and used according to terms described in the __wiki_licence_full__{{}}. +``` + +From the SQLite source code header: + +``` +__code_license_header_markdown__ +``` + +For questions, comments, or suggestions about this tutorial contact [{{}}__author__{{}}](mailto:{{}}__author_email__{{}}). + +This was developed with guidance from the founders of the University of Pittsburgh's Student Electronics Resource Center (SERC) and tested in a classroom setting with students. For other cool engineering tutorials and resources, check out SERC's website at [sercpitt.weebly.com](https://sercpitt.weebly.com/) . diff --git a/templates-code/T1/step-1-setup/windows-setup.cmd.m4 b/templates-code/T1/step-1-setup/windows-setup.cmd.m4 new file mode 100644 index 0000000..d5b8377 --- /dev/null +++ b/templates-code/T1/step-1-setup/windows-setup.cmd.m4 @@ -0,0 +1,72 @@ +@echo off +:: The `@echo off` command ensures that the commands that are run during this script are not displayed on the command console +setlocal +:: The `setLocal` command ensures that any variables that are set do not exist after the script exits. + +:: The author disclaims copyright to this source code. In place of +:: a legal notice, here is a blessing: +:: May you do good and not evil. +:: May you find forgiveness for yourself and forgive others. +:: May you share freely, never taking more than you give. + + +echo Checking system 32 or 64 bit... +reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=32BIT || set OS=64BIT +if %OS%==32BIT (set cygwinUrl=https://cygwin.com/setup-x86.exe + echo 32 Bit system found + set cygwinPath=C:\cygwin) +if %OS%==64BIT (set cygwinUrl=https://cygwin.com/setup-x86_64.exe + echo 64 Bit system found + set cygwinPath=C:\cygwin64) + +echo Downloading cygwin setup... +if not exist %USERPROFILE%\Downloads mkdir %USERPROFILE%\Downloads +:: download Cygwin setup application +bitsadmin /transfer mydownloadjob /download /priority normal "%cygwinUrl%" "%USERPROFILE%\Downloads\cygwin-setup.exe" > NUL +echo Download completed. + +echo Checking if cygwin is installed... +:: if cygwin isn't installed then install it +if not exist %cygwinPath% ( + echo Will run cygwin installer after any key. Install with defaults. + pause + %USERPROFILE%\Downloads\cygwin-setup.exe + echo Wait to click any key until after setup is complete. + pause + ) + + +:: double-check that Cygwin was installed to the correct path +if not exist %cygwinPath%\bin echo %cygwinPath%\bin not found. Check Cygwin installation path. && exit /B + +:: TODO: Check the Path length to see if +:: adding would exceed the max length. +:: MAX_PATH, which is defined as 260 +:: If so, then alert the user to edit +:: the path first then run again. +:: +:: Possible solution from: +:: https://stackoverflow.com/questions/5837418/how-do-you-get-the-string-length-in-a-batch-file/8566001#8566001 +:: set tempPath="%USERPROFILE%\AppData\Local\Temp\win-setup-path.txt" +:: (ECHO %PATH%)> %tempPath% +:: FOR %%? IN (%tempPath%) DO ( SET /A strlength=%%~z? - 2 ) +:: del %tempPath% +:: if strlength + +:: check to see that the environmental variables have the cygwin path +echo %PATH% | find /i "%cygwinPath%\bin" > nul && set CYGWIN_PATH_BIN_SET=TRUE || set CYGWIN_PATH_BIN_SET= +if defined CYGWIN_PATH_BIN_SET ( + echo Cygwin\bin found in system PATH. + ) else (echo Adding '%cygwinPath%\bin' to PATH. + setx /M PATH "%PATH%;%cygwinPath%\bin") + +:: BUG, Does not check the Path length first to ensure that +:: the Cygwin bin path can be added. + +:: then install Git, TCL, Expect, GCC and other developer programs +echo Updating Cygwin to latest and installing development programs... +%USERPROFILE%\Downloads\cygwin-setup.exe -qvg -P python36 -P python36-devel -P python36-numpy -P python36-pip -P tcl -P expect -P git -P gcc-g++ -P make -P astyle -P diffutils -P libmpfr-devel -P libgmp-devel -P libmpc-devel -P cmake -P gdb + +pause + +goto :eof diff --git a/templates-code/T1/step-2-command-line-101/hello-world-fixed.tcl.m4 b/templates-code/T1/step-2-command-line-101/hello-world-fixed.tcl.m4 new file mode 100755 index 0000000..b4ec857 --- /dev/null +++ b/templates-code/T1/step-2-command-line-101/hello-world-fixed.tcl.m4 @@ -0,0 +1,29 @@ +#!/usr/bin/env expect +# This first line is called a shebang (pronounced Sha-Bang) and +# will tell the shell what program to use for the following text. + +__code_license_header_hash_style__ + +spawn echo "Hello World from TCL/Expect!" + +# What can we do to make this command exit with success? +# There are multiple ways to go about this. +# Method one, is to simply change the text in the expect +# command from "Hello world." to "Hello World from TCL/Expect!" +# Method two is to change the text to be more flexible +# and replace "Hello world." with the text +# "Hello World from TCL/Expect!" or with `-nocase "hello world"`. +# The '-nocase' argument allows the check to ignore the +# case of the text so it could be upper or lower case. + +# Method two: +expect { + -nocase "hello world" { + puts "Success!" + exit 0 + } + default { + puts "Error!" + exit 1 + } +} diff --git a/templates-code/T1/step-2-command-line-101/hello-world.tcl.m4 b/templates-code/T1/step-2-command-line-101/hello-world.tcl.m4 new file mode 100755 index 0000000..95c99ff --- /dev/null +++ b/templates-code/T1/step-2-command-line-101/hello-world.tcl.m4 @@ -0,0 +1,29 @@ +#!/usr/bin/env expect +# This first line is called a shebang (pronounced Sha-Bang) and +# will tell the shell what program to use for the following text. + +__code_license_header_hash_style__ + +# Our first line of code we tell the expect program to run a program! +# The program to run is `echo`. +# The echo program will display text to the shell, in this case +# that is "Hello World from TCL/Expect!" +spawn echo "Hello World from TCL/Expect!" + +# This next command `expect` (which is the same name as the program) +# will look at the shell and follow a command that you tell it to. +# We are looking to see the words "Hello world." and if we do +# then we output "Success!" to the shell and exit with the +# value 0. +# If we don't see the words "Hello world." then we will output +# "Error!" and exit with the value 1. +expect { + "Hello world from." { + puts "Success!" + exit 0 + } + default { + puts "Error!" + exit 1 + } +} diff --git a/templates-code/T1/step-3-version-control-101/download-repository.tcl.m4 b/templates-code/T1/step-3-version-control-101/download-repository.tcl.m4 new file mode 100644 index 0000000..6638dc8 --- /dev/null +++ b/templates-code/T1/step-3-version-control-101/download-repository.tcl.m4 @@ -0,0 +1,64 @@ +#!/usr/bin/env expect + +__code_license_header_hash_style__ + +# package require platform + +# create a repository folder in your documents directory +# If using Cygwin +switch $::tcl_platform(os) { + CYGWIN_NT-10.0 { + set homeDirectory $env(HOMEDRIVE)$env(HOMEPATH) + } + default { + set homeDirectory ~/ + } +} + +# make directory Documents/Code/ +# change to +set dir [file join $homeDirectory Documents\\Code\\] + +if {[file exists $dir]} { + puts "Directory exists!" +} else { + file mkdir $dir +} + +cd $dir +puts [pwd] + +# dangerous command to clear out the directory before download +if {[file exists SERC-Pitt-C-Programming-Tutorial]} { + puts "Do you want to clear out the directory first? (Y/N)" + gets stdin someVar + + if {[string match Y $someVar]} { + exec rm -rf SERC-Pitt-C-Programming-Tutorial + } +} + +if { [catch { spawn git clone https://github.com/betsalel-williamson/C-Programming-Tutorial.git } msg] } { + puts "Something seems to have gone wrong:" + puts "Information about it: $::errorInfo" +} + +expect { + eof { + puts "Finished downloading." + } +} + +puts [spawn ls -la SERC-Pitt-C-Programming-Tutorial] + +expect { + eof { + puts "Finished listing directory." + } +} +# git clone + +## make change to file +## git add change +## git commit with comment +## git revert commit diff --git a/T1/step-2-command-line-101/hello-world.tcl b/templates-code/T1/step-3-version-control-101/hello-world.tcl.m4 similarity index 80% rename from T1/step-2-command-line-101/hello-world.tcl rename to templates-code/T1/step-3-version-control-101/hello-world.tcl.m4 index 2f070db..24befcb 100755 --- a/T1/step-2-command-line-101/hello-world.tcl +++ b/templates-code/T1/step-3-version-control-101/hello-world.tcl.m4 @@ -2,11 +2,7 @@ # This first line is called a shebang (pronounced Sha-Bang) and # will tell the shell what program to use for the following text. -# The author disclaims copyright to this source code. In place of -# a legal notice, here is a blessing: -# May you do good and not evil. -# May you find forgiveness for yourself and forgive others. -# May you share freely, never taking more than you give. +__code_license_header_hash_style__ # Our first line of code we tell the expect program to run a program! # The program to run is `echo`. @@ -35,7 +31,7 @@ expect { # What can we do to make this command exit with success? # There are multiple ways to go about this. # Method one, is to simply change the text in the expect -# command from "Hello world." to "Hello World from TCL/Expect!" +# command from "Hello world." to "Hello World!" # Method two is to change the text to be more flexible # and replace "Hello world." with the text between the # `` characters `-nocase "hello world"`. diff --git a/templates-code/T1/step-4-hello-world/1-Hello-World/main.c.m4 b/templates-code/T1/step-4-hello-world/1-Hello-World/main.c.m4 new file mode 100644 index 0000000..bfc0330 --- /dev/null +++ b/templates-code/T1/step-4-hello-world/1-Hello-World/main.c.m4 @@ -0,0 +1,60 @@ +/* + * Welcome to your first program in C. This program will output "Hello World" to + * the shell when run. + * + * In this program you will see code, and comments about the code. + * + * Multi-line comments are text written between a leading `/*` and ending with + * the reverse. + * + * Single line comments are written after double forward slashes `//` + */ + +__code_license_header_c__ + +int main ( ) { + + // Programming language of C requires a function named `main` that returns + // an integer value. The reason for needing `main` is because the compiler + // that converts this program needs to know where to start. + // + // The reason for returning an integer or `int` is for you to report back to + // the person running the program how things went. It is the adopted + // practice to use the value 0 when all has gone well and to use other + // values to indicate that something went wrong. + // + // We will leave the ( ) blank for now and will come back to this later. C + // does not care about the white space or number of spaces between different + // lines of code. + // + // We could have written it like () or ( ). + // + // Finally, the code that we want this function to have is between the curly + // braces { } . The code between these two braces is also called a block of + // code. + + write( 1, "Hello World", 12 ); + + // The second function in this program will print the words Hello World to + // the shell. This function is called an implicitly declared function + // because we did not write where it comes from. + // There are a selection of implicit functions that C knows about. We will + // therefore ignore the warning with the `-w` option when we compile. + // + // This function takes 3 arguments: + // `1` - indicates that we would like to write to Standard Out or the main + // shell (in contrast with standard error, used when we output errors + // to the shell) + // `"Hello World"` - is the information that we want to print to the shell + // `12` - is the size of the information in bytes we want to print, or in + // other words the number of letters between the quotes + + // In C, all lines of code must end with the `;` character. One of the + // biggest issues that people run into during their first program is not + // paying attention to this detail and turning away in frustration. + + // Finally, the `return` keyword will tell the function that are finished + // and would like to indicate our program ran successfully by returning the + // value of 0. + return 0; +} diff --git a/templates-code/T1/step-4-hello-world/2-Test-Hello-World/.gitignore.m4 b/templates-code/T1/step-4-hello-world/2-Test-Hello-World/.gitignore.m4 new file mode 100644 index 0000000..b9034f7 --- /dev/null +++ b/templates-code/T1/step-4-hello-world/2-Test-Hello-World/.gitignore.m4 @@ -0,0 +1,3 @@ +__code_license_header_hash_style__ + +main \ No newline at end of file diff --git a/T1/step-4-hello-world/2-Test-Hello-World/main.c b/templates-code/T1/step-4-hello-world/2-Test-Hello-World/main-fixed.c.m4 similarity index 98% rename from T1/step-4-hello-world/2-Test-Hello-World/main.c rename to templates-code/T1/step-4-hello-world/2-Test-Hello-World/main-fixed.c.m4 index c3ef0da..d06ef2c 100644 --- a/T1/step-4-hello-world/2-Test-Hello-World/main.c +++ b/templates-code/T1/step-4-hello-world/2-Test-Hello-World/main-fixed.c.m4 @@ -6,6 +6,8 @@ * */ +__code_license_header_c__ + int main ( int argc, const char* argv[] ) { // argc is the number of arguments passed into the program diff --git a/templates-code/T1/step-4-hello-world/2-Test-Hello-World/main.c.m4 b/templates-code/T1/step-4-hello-world/2-Test-Hello-World/main.c.m4 new file mode 100644 index 0000000..5cd6702 --- /dev/null +++ b/templates-code/T1/step-4-hello-world/2-Test-Hello-World/main.c.m4 @@ -0,0 +1,18 @@ +__code_license_header_c__ + +int main ( int argc, const char* argv[] ) { + int exit_value = -1; + + if ( argc == 2 ) { + + while( argv[1][i] != '\0' ) { + i = i + 1; + } + + exit_value = 0 + } else { + exit_value = 1; + } + + return exit_value; +} \ No newline at end of file diff --git a/templates-code/T1/step-4-hello-world/2-Test-Hello-World/test.tcl.m4 b/templates-code/T1/step-4-hello-world/2-Test-Hello-World/test.tcl.m4 new file mode 100644 index 0000000..1f46529 --- /dev/null +++ b/templates-code/T1/step-4-hello-world/2-Test-Hello-World/test.tcl.m4 @@ -0,0 +1,62 @@ +#!/usr/bin/env expect + +__code_license_header_hash_style__ + +# delete the executable file +if { [file exists main] == 1 } { + exec rm main +} + +# compile the file +exec gcc -w main-fixed.c -o main + +### Test 1 ### +# +# Given that we provide a single text input to our program, +# When we run it, +# Then the program will print the text to the Shell +# and exits with the value 0 +# + +spawn ./main "Hello World" +expect { + -nocase "hello world" { + puts "\nFound output of: Hello World\n" + } + default { + puts "\nTest failed. Expected Hello world\n" + } +} + +expect eof +catch wait result +if {[lindex $result 3] == 0} { + puts "Exited successfully.\n" +} else { + puts "Test failed with code [lindex $result 3].\n" +} + +### Test 2 ### +# +# Given that we don't provide a single text input to our +# program, +# When we run it, +# Then the program exits without printing the input and +# has the value 1 +# + +spawn ./main +expect eof +catch wait result + +if {[lindex $result 3] == 1} { + puts "Exited successfully.\n" +} else { + puts "Test failed with code [lindex $result 3].\n" +} + +# What happens when we try calling main +# with more than 1 parameter? +# $ ./main Hello World +# Hello world must be in quotes in order for this +# to be considered a single parameter diff --git a/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/.gitignore.m4 b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/.gitignore.m4 new file mode 100644 index 0000000..b9034f7 --- /dev/null +++ b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/.gitignore.m4 @@ -0,0 +1,3 @@ +__code_license_header_hash_style__ + +main \ No newline at end of file diff --git a/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/main-fixed.c.m4 b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/main-fixed.c.m4 new file mode 100644 index 0000000..82deef6 --- /dev/null +++ b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/main-fixed.c.m4 @@ -0,0 +1,60 @@ +/* + * Welcome to your second program in C. + * + * In this program you will modify the code from your first program + * to accept a parameter or argument as input from the Shell. + * + */ + +__code_license_header_c__ + +#include + +int main ( int argc, const char* argv[] ) { + + // argc is the number of arguments passed into the program + // argv is the array (think a list) of arguments + // We access the items in the array by putting a number between + // the square brackets. In C, we call this number an index. + // This is very important because indexes will always start + // with 0. You can think of this in terms of number types. + // In math, the natural numbers start with 1 and increase. + // Indexes start at 0 and will increase until the number of + // items in the array minus 1. + int exit_value; + + // ensure the correct number of parameters are used. + if ( argc == 2 ) + { + int i = 0; // declare a variable to count the length + // of the text passed in as an argument + + // In C, all text ends with the character '\0'. + // To get the length of the text, or string, we + // start at the first index + while( argv[1][i] != '\0' ) { + i = i + 1; + } + + write( 1, argv[1], i ); + + // What do you think the zeroth item or element + // in argv is? + + // i = 0; // reset i to be 0 + + // while(argv[0][i] != '\0') { + // i = i+1; + // } + + // write(1, argv[0], i); + + exit_value = 0; + } else { + // if the incorrect number of parameters are used + // then report that there was an error + exit_value = 1; + } + + return exit_value; +} diff --git a/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/main.c.m4 b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/main.c.m4 new file mode 100644 index 0000000..f9134c0 --- /dev/null +++ b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/main.c.m4 @@ -0,0 +1,58 @@ +/* + * Welcome to your second program in C. + * + * In this program you will modify the code from your first program + * to accept a parameter or argument as input from the Shell. + * + */ + +__code_license_header_c__ + +int main ( int argc, const char* argv[] ) { + + // argc is the number of arguments passed into the program + // argv is the array (think a list) of arguments + // We access the items in the array by putting a number between + // the square brackets. In C, we call this number an index. + // This is very important because indexes will always start + // with 0. You can think of this in terms of number types. + // In math, the natural numbers start with 1 and increase. + // Indexes start at 0 and will increase until the number of + // items in the array minus 1. + int exit_value; + + // ensure the correct number of parameters are used. + if ( argc == 2 ) + { + int i = 0; // declare a variable to count the length + // of the text passed in as an argument + + // In C, all text ends with the character '\0'. + // To get the length of the text, or string, we + // start at the first index + while( argv[1][i] != '\0' ) { + i = i + 1; + } + + write( 1, argv[1], i ); + + // What do you think the zeroth item or element + // in argv is? + + // i = 0; // reset i to be 0 + + // while(argv[0][i] != '\0') { + // i = i+1; + // } + + // write(1, argv[0], i); + + exit_value = 0; + } else { + // if the incorrect number of parameters are used + // then report that there was an error + exit_value = 1; + } + + return exit_value; +} diff --git a/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/makefile.m4 b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/makefile.m4 new file mode 100644 index 0000000..341b4d8 --- /dev/null +++ b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/makefile.m4 @@ -0,0 +1,24 @@ +__code_license_header_hash_style__ + +CC = gcc +SRCS = main-fixed.c +OBJS = $(subst .c,.o,$(SRCS)) +CFLAGS = -Wall -Werror -Wextra +RM = rm -f + +all: main +debug: $(eval CFLAGS := -g -DDBUG) +debug: main + +main: $(OBJS) + $(CC) -o main $(OBJS) $(CFLAGS) + +main.o: main-fixed.c + +# We don't glob because this doesn't scale for +# large projects +# %.o: %.c $(DEPS) +# $(CC) -g -c -o $@ $< $(CFLAGS) + +clean: + $(RM) $(OBJS) main diff --git a/T1/step-4-hello-world/2-Test-Hello-World/test.tcl b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl.m4 similarity index 86% rename from T1/step-4-hello-world/2-Test-Hello-World/test.tcl rename to templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl.m4 index 817f9c3..e72fe7b 100644 --- a/T1/step-4-hello-world/2-Test-Hello-World/test.tcl +++ b/templates-code/T1/step-4-hello-world/3-Makefile-Hello-World/test.tcl.m4 @@ -1,9 +1,11 @@ -#!/bin/env expect +#!/usr/bin/env expect -# delete the executable file -exec rm main +__code_license_header_hash_style__ + +# delete the old executable and object files +exec make clean # compile the file -exec gcc -w main.c -o main +exec make ### Test 1 ### # @@ -54,4 +56,4 @@ if {[lindex $result 3] == 1} { # with more than 1 parameter? # $ ./main Hello World # Hello world must be in quotes in order for this -# to be considered a single parameter \ No newline at end of file +# to be considered a single parameter diff --git a/templates-code/T2/step-1-code-gen/.gitignore.m4 b/templates-code/T2/step-1-code-gen/.gitignore.m4 new file mode 100644 index 0000000..2d428a4 --- /dev/null +++ b/templates-code/T2/step-1-code-gen/.gitignore.m4 @@ -0,0 +1,7 @@ +__code_license_header_hash_style__ + +debug/ +release/ +*.o +*.orig +*.stackdump diff --git a/templates-code/T2/step-1-code-gen/lib.c.m4 b/templates-code/T2/step-1-code-gen/lib.c.m4 new file mode 100644 index 0000000..fa45d7e --- /dev/null +++ b/templates-code/T2/step-1-code-gen/lib.c.m4 @@ -0,0 +1,95 @@ +__code_license_header_c__ + +#include "lib.h" + +int generateSecretCode( char * secret_key ) { + LOG_DEBUG( "Secret Key %s", secret_key ); + int secret_code = 0; + // for more info on this time functionality look atUpdated + // https://www.tutorialspoint.com/c_standard_library/time_h.htm + time_t my_time; + time ( &my_time ); + struct tm * time_info = localtime ( &my_time ); + LOG_DEBUG( "year->%d", time_info->tm_year + 1900 ); + LOG_DEBUG( "month->%d", time_info->tm_mon + 1 ); + LOG_DEBUG( "date->%d", time_info->tm_mday ); + LOG_DEBUG( "hour->%d", time_info->tm_hour ); + LOG_DEBUG( "minutes->%d", time_info->tm_min ); + LOG_DEBUG( "seconds->%d", time_info->tm_sec ); + int second_info = ( time_info->tm_sec / 20 ); + LOG_DEBUG( "seconds divide: %d", second_info ); + // this will demonstrate bit-wise operations + secret_code ^= time_info->tm_min << ( 'b' & 0b11 ); + secret_code ^= 1214 << ( 'h' & 0b11 ) ; + secret_code >>= ( 'w' & 0b11 ); + secret_code ^= second_info << ( '7' & 0b11 ); + + unsigned long i; + + for ( i = 0; i < strlen( secret_key ); i++ ) + { + secret_code = secret_key[i] ^ secret_code; + } + + secret_code &= 0b11111111; + + LOG_DEBUG( "secret_code %d", secret_code ); + return secret_code; +} + +void processInputArguments( int argc, char* const argv[], + char **user_input_attempt_s, char ** user_input_override_s ) { + static struct option long_options[] = + { + /* These options set a flag. */ + // each one of these lines is an option struct + /* These options don’t set a flag. + We distinguish them by their indices. */ + // required_argument is a macro in the getopts.h + {"code", required_argument, 0, 'c'}, + {"force", required_argument, 0, 'f'} + }; + /* getopt_long stores the option index here. */ + int option_index = 0; + + /* value to hold the short argument returned by getopt_long */ + int c; + + /* Detect the end of the options. */ + while ( ( c = getopt_long ( argc, argv, "c:f:", long_options, + &option_index ) ) != -1 ) + { + switch ( c ) + { + case 'c': + LOG_DEBUG ( "option -c with value `%s'\n", optarg ); + *user_input_attempt_s = optarg; + break; + + case 'f': + LOG_DEBUG ( "option -f with value `%s'\n", optarg ); + *user_input_override_s = optarg; + break; + + case '?': + LOG_DEBUG ( "unknown with value `%s'\n", optarg ); + break; + + default: + LOG_DEBUG ( "In default with value `%c'\n", c ); + } + } + + /* Print any remaining command line arguments (not options). */ + if ( optind < argc ) + { + LOG_DEBUG ( "non-option ARGV-elements: " ); + + while ( optind < argc ) + { LOG_DEBUG ( "%s ", argv[optind++] ); } + + LOG_DEBUG ( "\n" ); + } + + return; +} diff --git a/templates-code/T2/step-1-code-gen/lib.h.m4 b/templates-code/T2/step-1-code-gen/lib.h.m4 new file mode 100644 index 0000000..1216679 --- /dev/null +++ b/templates-code/T2/step-1-code-gen/lib.h.m4 @@ -0,0 +1,32 @@ +__code_license_header_c__ + +// basic C functions including write, and printf +#include +// includes the exit function along with others +#include +// some basic operations working with ASCII text +#include +// for processInputArguments +#include +// for use with getting the time +#include +// use a logger instead of printf everywhere to +// save you from printing everything in release mode +#include "macrologger.h" + +// note the style of UPPER_CASE_SNAKE_CASE, or SCREAMING_SNAKE +// this is to indicate that this is a macro, +// note that sometimes lower_case_snake is also used +// this is a style convention +#define STRING_NOT_SET NULL +#define INT_NOT_SET -1 +#define CORRECT_CODE EXIT_SUCCESS +#define INCORRECT_CODE EXIT_FAILURE +#define INVALID_USER_INPUT 2 +#define EXIT_CODE_NOT_SET -1 +#define ATOI_NO_NUMBER_CODE 0 + +// in a header file we declare functions in the corresponding .c file +int generateSecretCode( char * secret_key ); +void processInputArguments( int argc, char* const argv[], + char **user_input_attempt_s, char ** user_input_override_s ); diff --git a/templates-code/T2/step-1-code-gen/macrologger.h.m4 b/templates-code/T2/step-1-code-gen/macrologger.h.m4 new file mode 100644 index 0000000..f53fa49 --- /dev/null +++ b/templates-code/T2/step-1-code-gen/macrologger.h.m4 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2012 David Rodrigues + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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 OR COPYRIGHT HOLDERS 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. + */ + +#ifndef __MACROLOGGER_H__ +#define __MACROLOGGER_H__ + +#ifdef __OBJC__ +#import +#else +#include +#include +#endif + +// === auxiliar functions +static inline char *timenow(); + +#define _FILE strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__ + +#define NO_LOG 0x00 +#define ERROR_LEVEL 0x01 +#define INFO_LEVEL 0x02 +#define DEBUG_LEVEL 0x03 + +#ifndef LOG_LEVEL +#define LOG_LEVEL DEBUG_LEVEL +#endif + +#ifdef __OBJC__ + +#if __has_feature(objc_arc) +#define AUTORELEASEPOOL_BEGIN @autoreleasepool { +#define AUTORELEASEPOOL_END } +#define RELEASE(OBJ) OBJ = nil +#else +#define AUTORELEASEPOOL_BEGIN NSAutoreleasePool *_pool = [[NSAutoreleasePool alloc] init]; +#define AUTORELEASEPOOL_END [_pool release]; +#define RELEASE(OBJ) [OBJ release]; +#endif + +#define PRINTFUNCTION(format, ...) objc_print(@format, __VA_ARGS__) +#else +#define PRINTFUNCTION(format, ...) fprintf(stderr, format, __VA_ARGS__) + +#endif + +#define LOG_FMT "%s | %-7s | %-15s | %s:%d | " +#define LOG_ARGS(LOG_TAG) timenow(), LOG_TAG, _FILE, __FUNCTION__, __LINE__ + +#define NEWLINE "\n" + +#define ERROR_TAG "ERROR" +#define INFO_TAG "INFO" +#define DEBUG_TAG "DEBUG" + +#if LOG_LEVEL >= DEBUG_LEVEL +#define LOG_DEBUG(message, args...) PRINTFUNCTION(LOG_FMT message NEWLINE, LOG_ARGS(DEBUG_TAG), ## args) +#else +#define LOG_DEBUG(message, args...) +#endif + +#if LOG_LEVEL >= INFO_LEVEL +#define LOG_INFO(message, args...) PRINTFUNCTION(LOG_FMT message NEWLINE, LOG_ARGS(INFO_TAG), ## args) +#else +#define LOG_INFO(message, args...) +#endif + +#if LOG_LEVEL >= ERROR_LEVEL +#define LOG_ERROR(message, args...) PRINTFUNCTION(LOG_FMT message NEWLINE, LOG_ARGS(ERROR_TAG), ## args) +#else +#define LOG_ERROR(message, args...) +#endif + +#if LOG_LEVEL >= NO_LOGS +#define LOG_IF_ERROR(condition, message, args...) if (condition) PRINTFUNCTION(LOG_FMT message NEWLINE, LOG_ARGS(ERROR_TAG), ## args) +#else +#define LOG_IF_ERROR(condition, message, args...) +#endif + +static inline char *timenow() { + static char buffer[64]; + time_t rawtime; + struct tm *timeinfo; + time( &rawtime ); + timeinfo = localtime( &rawtime ); + strftime( buffer, 64, "%Y-%m-%d %H:%M:%S", timeinfo ); + return buffer; +} + +#ifdef __OBJC__ + +static inline void objc_print( NSString *format, ... ) { + AUTORELEASEPOOL_BEGIN + va_list args; + va_start( args, format ); + NSString *logStr = [[NSString alloc] initWithFormat:format arguments:args]; + fprintf( stderr, "%s", [logStr UTF8String] ); + RELEASE( logStr ); + va_end( args ); + AUTORELEASEPOOL_END +} + +#endif + +#endif diff --git a/templates-code/T2/step-1-code-gen/main.c.m4 b/templates-code/T2/step-1-code-gen/main.c.m4 new file mode 100644 index 0000000..f4bbbc0 --- /dev/null +++ b/templates-code/T2/step-1-code-gen/main.c.m4 @@ -0,0 +1,48 @@ +/* Simple program to demonstrate c */ + +__code_license_header_c__ + +#include "lib.h" + +int main ( int argc, char* const argv[] ) { + int exit_code = EXIT_CODE_NOT_SET; + char *user_input_attempt_s = STRING_NOT_SET; + char *user_input_override_s = STRING_NOT_SET; + + processInputArguments( argc, argv, &user_input_attempt_s, + &user_input_override_s ); + + if( user_input_attempt_s == STRING_NOT_SET ) { + LOG_ERROR( "%s", "You must pass in a code. (e.g.'./main -c 1234') ." ); + abort(); + } + + LOG_DEBUG( "Found code %s", user_input_attempt_s ); + LOG_DEBUG( "We will set our magic sting!" ); + int secret_code = INT_NOT_SET; + + if( user_input_override_s == STRING_NOT_SET ) { + secret_code = generateSecretCode( "1214 Benedum" ); + } else { + printf( "Used Override!!\n" ); + secret_code = atoi( user_input_override_s ); + } + + int input = atoi( user_input_attempt_s ); + + if( input == 0 ) { + LOG_ERROR( "Invalid input: %s", user_input_attempt_s ); + exit_code = INVALID_USER_INPUT; + + } else if ( input == secret_code ) { + exit_code = EXIT_SUCCESS; + printf( "Congrats! You entered in the right code!\n" ); + + } else { + LOG_ERROR( "Your attempt %d was incorrect. Try again.\n", input ); + exit_code = INCORRECT_CODE; + } + + exit ( exit_code ); +} + diff --git a/templates-code/T2/step-1-code-gen/makefile.m4 b/templates-code/T2/step-1-code-gen/makefile.m4 new file mode 100644 index 0000000..1e4d03e --- /dev/null +++ b/templates-code/T2/step-1-code-gen/makefile.m4 @@ -0,0 +1,69 @@ +__code_license_header_hash_style__ + +# https://stackoverflow.com/questions/1079832/how-can-i-configure-my-makefile-for-debug-and-release-builds#1080180 +# Author: ffhaddad , https://stackoverflow.com/users/1952377/ffhaddad +# Compiler flags +# +CC = gcc +CFLAGS = -Wall -Werror -Wextra + +# +# Project files +# +SRCS = main.c lib.c +OBJS = $(SRCS:.c=.o) +EXE = secretPassword + +# +# Debug build settings +# +DBGDIR = debug +DBGEXE = $(DBGDIR)/$(EXE) +DBGOBJS = $(addprefix $(DBGDIR)/, $(OBJS)) +DBGCFLAGS = -g -O0 -DDEBUG + +# +# Release build settings +# +RELDIR = release +RELEXE = $(RELDIR)/$(EXE) +RELOBJS = $(addprefix $(RELDIR)/, $(OBJS)) +RELCFLAGS = -O3 -DNDEBUG -D LOG_LEVEL=0 + +.PHONY: all clean debug prep release remake + +# Default build +all: prep release + +# +# Debug rules +# +debug: $(DBGEXE) + +$(DBGEXE): $(DBGOBJS) + $(CC) $(CFLAGS) $(DBGCFLAGS) -o $(DBGEXE) $^ + +$(DBGDIR)/%.o: %.c + $(CC) -c $(CFLAGS) $(DBGCFLAGS) -o $@ $< + +# +# Release rules +# +release: $(RELEXE) + +$(RELEXE): $(RELOBJS) + $(CC) $(CFLAGS) $(RELCFLAGS) -o $(RELEXE) $^ + +$(RELDIR)/%.o: %.c + $(CC) -c $(CFLAGS) $(RELCFLAGS) -o $@ $< + +# +# Other rules +# +prep: + mkdir -p $(DBGDIR) $(RELDIR) + +remake: clean all + +clean: + rm -f $(RELEXE) $(RELOBJS) $(DBGEXE) $(DBGOBJS) diff --git a/templates-code/T2/step-1-code-gen/test.tcl.m4 b/templates-code/T2/step-1-code-gen/test.tcl.m4 new file mode 100644 index 0000000..f97ef30 --- /dev/null +++ b/templates-code/T2/step-1-code-gen/test.tcl.m4 @@ -0,0 +1,90 @@ +#!/usr/bin/env expect + +__code_license_header_hash_style__ + +proc testMustProvideCode args { + + spawn ./debug/secretPassword -f "Hello World" + expect { + -nocase "you must pass in a code" { + puts "\n[lindex [info level 0] 0] passed\n" + } + default { + puts "\n!! [lindex [info level 0] 0] test failed !!\n" + exit 1 + } + } +} + +proc testProvidedCode args { + + spawn ./debug/secretPassword -c 1234 + expect { + -nocase "Found code 1234" { + puts "\n[lindex [info level 0] 0] passed\n" + } + default { + puts "\n!! [lindex [info level 0] 0] test failed !!\n" + exit 1 + } + } +} + +proc testProvidedInvalideCode args { + + spawn ./debug/secretPassword -c 1234 + expect { + -nocase "was incorrect. Try again." { + puts "\n[lindex [info level 0] 0] passed\n" + } + default { + puts "\n!! [lindex [info level 0] 0] test failed !!\n" + exit 1 + } + } +} + +proc testForceCode args { + + spawn ./debug/secretPassword -c 1234 -f 1234 + expect { + -nocase "Congrats! You entered in the right code!" { + puts "\n[lindex [info level 0] 0] passed\n" + } + default { + puts "\n!! [lindex [info level 0] 0] test failed !!\n" + exit 1 + } + } +} + +proc testInvalidInput args { + + spawn ./debug/secretPassword -c foo -f 1234 + expect { + -nocase "Invalid input" { + puts "\n[lindex [info level 0] 0] passed\n" + } + default { + puts "\n!! [lindex [info level 0] 0] test failed !!\n" + exit 1 + } + } +} + +exec make prep + +if {[catch {exec make debug} result] == 0} { + testMustProvideCode + testProvidedCode + testProvidedInvalideCode + testInvalidInput + testForceCode + + puts "\n\nAll tests passed\n\n" +} else { + puts "Error: $result" + exit 1 +} + + diff --git a/templates-code/T2/step-1-pointers/.gitignore.m4 b/templates-code/T2/step-1-pointers/.gitignore.m4 new file mode 100644 index 0000000..ea18294 --- /dev/null +++ b/templates-code/T2/step-1-pointers/.gitignore.m4 @@ -0,0 +1,5 @@ +__code_license_header_hash_style__ + +main +*.orig +*.o diff --git a/templates-code/T2/step-1-pointers/main.c.m4 b/templates-code/T2/step-1-pointers/main.c.m4 new file mode 100644 index 0000000..4382fa6 --- /dev/null +++ b/templates-code/T2/step-1-pointers/main.c.m4 @@ -0,0 +1,120 @@ +/* Simple program to demonstrate pointers and arrays */ + +__code_license_header_c__ + +#include +#include + +void myPointerFunction( int * pointer, int value ) { + *pointer = value; +} + +void myPointerToPointerFunction( char ** pointer_to_pointer, char* c_string ) { + *pointer_to_pointer = c_string; +} + +int main ( ) { + + // declare my c_string, or my pointer to point to the text "foo" + char *c_string = "foo"; + // will print the letter 'f' + printf( "%-35s%c\n", "First letter of c_string:", c_string[0] ); + // note we need a length of one more than the word we enter + char c_string_with_array[4]; + // we use index counting numbers that start from 0 and go until length minus 1 + c_string_with_array[0] = 'f'; + c_string_with_array[1] = 'o'; + c_string_with_array[2] = 'o'; + c_string_with_array[3] = '\0'; + // will print the letter 'f' + printf( "%-35s%c\n", "First letter, string as array:", c_string_with_array[0] ); + // will print the letter 'f' + printf( "%-35s%c\n", "First letter, pointer access:", *c_string_with_array ); + + // with the cubby example + // each variable will be assigned a cubby spot + int x = 1234; + // Look up the different print codes online for + printf( "%-35s%d\n", "Information in cubby:", x ); + // more detail. In short we tell `printf` how we want to display + // the variable `x` + + // We store the information `x` in a cubby. + // If we want to find out where that `x` was stored and get the + // cubby number we will dereference `x` with the `&` operator + // %x will print the cubby number or memory address using hex values. + printf( "%-35s%x\n", "Address of information:", &x ); + + long cubby_number_of_x_as_long = ( long ) &x; + // %x will print the cubby number or memory + printf( "%-35s%x\n", "Cubby number in long variable:", + cubby_number_of_x_as_long ); + + // we now declare a pointer + int* pointer = ( int* ) cubby_number_of_x_as_long; + // This variable will hold the cubby number of `x`. + printf( "%-35s%d\n", "Cubby number as a pointer:", *pointer ); + printf( "%-35s%x\n", "Cubby number of pointer:", &pointer ); + printf( "%-35s%x\n", "Cubby number of x:", pointer ); + // to see the information stored in the cubby + // we use the pointer operator `*` to access that information + // You must only use the `*` operator with a pointer or array + + // We can't use a `*x` because the `x` variable is not a pointer. + // If we want to use `*`, we must declare a pointer. + // error: invalid type argument of unary '*' (have 'int') + // printf("%u\n", *x); + + int array[2]; + *array = x; // same as array[0] = x; + *( array + 1 ) = 4321; // same as array[1] = 4321; + + printf( "%-35s%d\n", "Array index 0 with pointer access:", *array ); + // to see the information stored in the cubby + printf( "%-35s%d\n", "Array index 0 with array access:", array[0] ); + // to see the information stored in the cubby + printf( "%-35s%x\n", "Address of index 0 (as hex):", array ); + printf( "%-35s%ld\n", "Address of index 0 (as long):", &( array[0] ) ); + + printf( "%-35s%d\n", "Array index 1 with pointer access:", *( array + 1 ) ); + // to see the information stored in the cubby + printf( "%-35s%d\n", "Array index 1 with array access:", array[1] ); + // to see the information stored in the cubby + printf( "%-35s%x\n", "Address of index 1 (as hex):", ( array + 1 ) ); + printf( "%-35s%ld\n", "Address of index 1 (as long):", &( array[1] ) ); + + printf( "%-35s%d\n", "Array index 2 with pointer access:", *( array + 2 ) ); + // You will be able to access this information + // but is not guarenteed to be filled with anything, it may be zero + // it may be some other information that was in memory + printf( "%-35s%d\n", "Array index 2 with array access:", array[2] ); + // to see the information stored in the cubby + + printf( "%-35s%d\n", "Array index 80 with pointer access:", *( array + 80 ) ); + // You will be able to access this information + // but is not guarenteed to be filled with anything, it may be zero + // it may be some other information that was in memory + printf( "%-35s%d\n", "Array index 80 with array access:", array[80] ); + // to see the information stored in the cubby + + // note that C will allow you to access and overwrite + // locations that you may not understand + // this technique is used by hackers to exploit buffer overruns + + // the following line make crash the program or currupt another program + myPointerFunction( ( array + 2 ), 1217 ); + printf( "%-35s%d\n", "After changeing index 2:", *( array + 2 ) ); + + myPointerFunction( &( array[80] ), 1214 ); + printf( "%-35s%d\n", "After changeing index 80:", *( array + 80 ) ); + + myPointerToPointerFunction( &c_string, "Benedum" ); + printf( "%-35s%s\n", "New c_string:", c_string ); + + // what happens if we try to change the c_string_with_array? + // because arrays are allocated at compile time there is no way to get past the initial length + myPointerToPointerFunction( ( char** )&c_string_with_array, "SERC" ); + printf( "%-35s%s\n", "New c_string_with_array:", c_string_with_array ); + + return EXIT_SUCCESS; +} diff --git a/templates-code/T2/step-1-pointers/makefile.m4 b/templates-code/T2/step-1-pointers/makefile.m4 new file mode 100644 index 0000000..c2b460d --- /dev/null +++ b/templates-code/T2/step-1-pointers/makefile.m4 @@ -0,0 +1,24 @@ +__code_license_header_hash_style__ + +CC = gcc +SRCS = main.c +OBJS = $(subst .c,.o,$(SRCS)) +CFLAGS = -Wall -Werror -Wextra +RM = rm -f + +all: main +debug: $(eval CFLAGS := -g -DDBUG) +debug: main + +main: $(OBJS) + $(CC) -o main $(OBJS) $(CFLAGS) + +main.o: main.c + +# We don't glob because this doesn't scale for +# large projects +# %.o: %.c $(DEPS) +# $(CC) -g -c -o $@ $< $(CFLAGS) + +clean: + $(RM) $(OBJS) main diff --git a/templates-code/T2/step-2-brute-force/.gitignore.m4 b/templates-code/T2/step-2-brute-force/.gitignore.m4 new file mode 100644 index 0000000..ea18294 --- /dev/null +++ b/templates-code/T2/step-2-brute-force/.gitignore.m4 @@ -0,0 +1,5 @@ +__code_license_header_hash_style__ + +main +*.orig +*.o diff --git a/templates-code/T2/step-2-brute-force/main.c.m4 b/templates-code/T2/step-2-brute-force/main.c.m4 new file mode 100644 index 0000000..363fa93 --- /dev/null +++ b/templates-code/T2/step-2-brute-force/main.c.m4 @@ -0,0 +1,35 @@ +/* Trivial way to crack the code */ + +__code_license_header_c__ + +#include +#include + +int main ( ) { + + char str[80]; + char* debug_location = "./../step-1-code-gen/debug/"; + char* location = "./../step-1-code-gen/release/"; + char* exe_name = "secretPassword"; + char* args = "-c"; + + int i = 1; + + do { + sprintf( str, "%s%s %s %d", location, exe_name, args, i ); + int exit_code = system( str ); + + if ( exit_code == 0 ) { + printf( "The code is %d\n", i ); + + sprintf( str, "%s%s %s %d", debug_location, exe_name, args, i ); + int exit_code = system( str ); + + break; + } + + i++; + } while( i < 1000 ); + + exit( EXIT_SUCCESS ); +} diff --git a/templates-code/T2/step-2-brute-force/makefile.m4 b/templates-code/T2/step-2-brute-force/makefile.m4 new file mode 100644 index 0000000..c2b460d --- /dev/null +++ b/templates-code/T2/step-2-brute-force/makefile.m4 @@ -0,0 +1,24 @@ +__code_license_header_hash_style__ + +CC = gcc +SRCS = main.c +OBJS = $(subst .c,.o,$(SRCS)) +CFLAGS = -Wall -Werror -Wextra +RM = rm -f + +all: main +debug: $(eval CFLAGS := -g -DDBUG) +debug: main + +main: $(OBJS) + $(CC) -o main $(OBJS) $(CFLAGS) + +main.o: main.c + +# We don't glob because this doesn't scale for +# large projects +# %.o: %.c $(DEPS) +# $(CC) -g -c -o $@ $< $(CFLAGS) + +clean: + $(RM) $(OBJS) main diff --git a/templates-code/test.tcl.m4 b/templates-code/test.tcl.m4 new file mode 100755 index 0000000..bafb77d --- /dev/null +++ b/templates-code/test.tcl.m4 @@ -0,0 +1,74 @@ +#!/usr/bin/env expect +# Test the tutorial +# run from the 'src' directory + +__code_license_header_hash_style__ + +# test files +set t1step1file "./T1/step-1-setup/windows-setup.cmd" +if {[file exists $t1step1file]} { + puts "Success! T1 Step 1 file check" +} else { + puts "Error (file $t1step1file missing)!" + exit 1 +} + +puts "\nSuccess! T1 Step 1\n" + +set t1step2file "./T1/step-2-command-line-101/hello-world.tcl" +set outputT1Step2 { "spawn echo Hello World from TCL/Expect!\n" "Hello World from TCL/Expect!\n" "Error!\n" } + +if {[file exists $t1step2file]} { + puts "Success! T1 Step 2 file check" +} else { + puts "Error (file $t1step2file missing)!" + exit 1 +} + +spawn $t1step2file + +# puts [expr [llength $outputT1Step2]] +for {set index 0} {$index < [expr [llength $outputT1Step2]]} {incr index +1} { + # puts [lindex $outputT1Step2 $index] + expect { + "\n" { + puts "Success (line $index)!" + } + default { + puts "Error (line $index)!" + puts [lindex $outputT1Step2 $index] + exit 1 + } + } +} + +puts "\nSuccess! T1 Step 2\n" + +set t1step3fileList { "./T1/step-3-version-control-101/download-repository.tcl" "./T1/step-3-version-control-101/hello-world.tcl" } +set outputT1Step3 { "spawn echo Hello World from TCL/Expect!\n" "Hello World from TCL/Expect!\n" "Error!\n" } + +for {set index 0} {$index < [expr [llength $t1step3fileList]]} {incr index +1} { + if {[file exists [lindex $t1step3fileList $index]]} { + puts "Success! T1 Step 3 file check" + } else { + puts "Error (file [lindex $t1step3fileList $index] missing)!" + exit 1 + } +} + +spawn [lindex $t1step3fileList 1] + +for {set index 0} {$index < [expr [llength $outputT1Step3]]} {incr index +1} { + expect { + "\n" { + puts "Success (line $index)!" + } + default { + puts "Error (line $index)!" + puts [lindex $outputT1Step3 $index] + exit 1 + } + } +} + +puts "\nSuccess! T1 Step 3\n" diff --git a/Generate-Wiki/Home.md b/templates-wiki/Home.md.m4 similarity index 98% rename from Generate-Wiki/Home.md rename to templates-wiki/Home.md.m4 index 6184463..0b405ce 100644 --- a/Generate-Wiki/Home.md +++ b/templates-wiki/Home.md.m4 @@ -1,3 +1,4 @@ +__project_under_construction_flag__ Welcome to the Programming Tutorial wiki! # Introduction @@ -89,4 +90,7 @@ Lastly, I would like to thank my father Tsuri and my dear friend Jordan H. for t 1. Keeping things simple is harder than it looks, and 1. If you only use a hammer everything looks like a nail +# Updates +* Jan 1, 2021 - Generated from m4 template + [[Previous Page]] | [[Next Page|T1-00]] diff --git a/Generate-Wiki/Tutorial 1/T1-00.md b/templates-wiki/Tutorial 1/T1-00.md.m4 similarity index 90% rename from Generate-Wiki/Tutorial 1/T1-00.md rename to templates-wiki/Tutorial 1/T1-00.md.m4 index 6a84632..764a652 100644 --- a/Generate-Wiki/Tutorial 1/T1-00.md +++ b/templates-wiki/Tutorial 1/T1-00.md.m4 @@ -1,6 +1,7 @@ +__project_under_construction_flag__ # Tutorial 1: “Hello World!” -The first step in any computer language has historically been the “Hello World!” example. The purpose of this exercise to focus on a simple task when setting the system up before getting into the programming complexities. Unlike traditional programming tutorials, we are going to be adding an additional step to this, so bear with us. This step provides a framework to automate the actions of compiling, running, and testing your program. This will set you up in the long run for best practices in programming. To download a complete working version of this program visit this GitHub URL . This tutorial will not get into the details of why different coding languages look different, what variables are and so on. See the later tutorials for more details about programming in C or Python. +The first step in any computer language has historically been the “Hello World!” example. The purpose of this exercise to focus on a simple task when setting the system up before getting into the programming complexities. Unlike traditional programming tutorials, we are going to be adding an additional step to this, so bear with us. This step provides a framework to automate the actions of compiling, running, and testing your program. This will set you up in the long run for best practices in programming. To download a complete working version of this program visit this GitHub URL <{{}}__project_repo_root__{{}}/>. This tutorial will not get into the details of why different coding languages look different, what variables are and so on. See the later tutorials for more details about programming in C or Python. Now before we get into all of this I would like to share a little bit about learning in general. @@ -23,4 +24,7 @@ We will be able to work with this guide and all of the tutorials whether you are One last note, it is often useful to install an Integrated Development Environment (IDE), like CLion, Visual Studio, NetBeans, or Emacs, but it is best to use only a text editor for this tutorial. If learning to program was learning to ride a bike, using an IDE is like adding gears to a bicycle. We first take the harder path, so that you understand the basics and can get along when you don’t have access or a budget to buy the fancy software. +# Updates +* Jan 1, 2021 - Generated from m4 template + [[Previous Page|Home]] | [[Next Page|T1-01]] \ No newline at end of file diff --git a/Generate-Wiki/Tutorial 1/T1-01.md b/templates-wiki/Tutorial 1/T1-01.md.m4 similarity index 94% rename from Generate-Wiki/Tutorial 1/T1-01.md rename to templates-wiki/Tutorial 1/T1-01.md.m4 index 355060a..4d9ce20 100644 --- a/Generate-Wiki/Tutorial 1/T1-01.md +++ b/templates-wiki/Tutorial 1/T1-01.md.m4 @@ -1,3 +1,4 @@ +__project_under_construction_flag__ # Step 1: Setup In every professional computer environment the very first step is always finding the setup instructions and following them very carefully. Again, this is very important. **FOLLOW SETUP INSTRUCTIONS VERY CAREFULLY!** @@ -35,7 +36,7 @@ Finally, if you're still stuck stop by SERC and see us. We'll be happy to help y ## Mac The following instructions were tested on a clean install of MacOS 10.13. If you are running an earlier version of the Mac operating system the following may work. If it does not work see the subsequent instructions. -1. Open up `Terminal.app` in the `\Applications\Utilities` folder or use Spotlight to find it. Once it is open type `gcc` and hit the `enter` key. +1. Open up `Terminal.app` in the `\Applications\Utilities` folder or use Spotlight to find it. Once it is open type `gcc` and hit the enter key. 1. A dialog window will pop up and ask you to download and install the command line developer tools. 1. Click `Install` (estimated 10 min) Thats it! @@ -54,14 +55,14 @@ Once you have installed Xcode run the following command (open up the terminal Ap We will be using Cygwin. You must install it, and the associated packages in order to run through this correctly. If you already have Cygwin installed you should still run this script to install the necessary software. 1. Run Install Setup Batch Script - 1. Navigate to the following URL + 1. Navigate to the following URL <{{}}__project_repo_source_root__{{}}/T1/step-1-setup> 1. Click on `windows-setup.cmd` 1. Click on the `Raw` button 1. Open up notepad and copy-and-paste the text into the empty text file. 1. Save as `setup.cmd` 1. To install the program for all uses, right-click `setup.cmd` and select `Run as administrator`. 1. Follow through the instructions that are displayed on the window that pops up. This script walks through installing Cygwin and the necessary programs for running the rest of the tutorial. -1. Open up a new command window and type `ls` and then the `Enter` key. +1. Open up a new command window and type `ls` and then the enter key. You should see a list of files in your current directory. If you get the following response: @@ -89,6 +90,7 @@ At this point you will have equivalent software for building programs that can b 1. Installing GCC on Windows - http://preshing.com/20141108/how-to-install-the-latest-gcc-on-windows/ # Updates -* Nov 11. 2020 - Added python +* Jan 1, 2021 - Generated from m4 template +* Nov 11, 2020 - Added python [[Previous Page|T1-00]] | [[Next Page|T1-02]] \ No newline at end of file diff --git a/Generate-Wiki/Tutorial 1/T1-02.md b/templates-wiki/Tutorial 1/T1-02.md.m4 similarity index 88% rename from Generate-Wiki/Tutorial 1/T1-02.md rename to templates-wiki/Tutorial 1/T1-02.md.m4 index e1f5744..9964552 100644 --- a/Generate-Wiki/Tutorial 1/T1-02.md +++ b/templates-wiki/Tutorial 1/T1-02.md.m4 @@ -1,5 +1,7 @@ +__project_under_construction_flag__ # Step 2: Command Line 101 -We will get started by opening up a shell or terminal window. Find the `Meta` key on your keyboard as the key with the Windows logo on standard PC keyboards, or as the `command` key on Mac keyboards. We will refer to both these keys as the `Meta` key for the rest of this guide. + +We will get started by opening up a shell or terminal window. Find the meta key on your keyboard as the key with the Windows logo on standard PC keyboards, or as the command key on Mac keyboards. We will refer to both these keys as the meta key for the rest of this guide. Welcome to the command line. Things will look a little scary here if this is the first time you’ve opened up what is called a command-line interface (CLI) shell. Usually, modern systems will open a graphical user interface (GUI) shell that operates with icons, apps, clicks, swipes, etc. A CLI shell is a text-based or keyboard-only interface to your computer. Throughout the rest of this guide we will simply refer to the CLI shell as the Shell. **We will be using the word shell to mean the Windows Command Prompt and \*nix CLI shells.** The Shell is a simple text interface to your computer and will open up a new world of commands for you to run on your machine. @@ -7,9 +9,9 @@ _On the Internet you may sometimes see the *nix system. This is shorthand meanin On Linux, you open the Shell by opening up the terminal, konsole, shell or prompt (depending on your specific flavor of Linux like Red Hat, Ubuntu, SUSE, Fedora etc.). Each flavor has it's preferred name for the Shell. -On Mac, you open the Shell through the Terminal App by pressing `Meta-Space` and typing in `Terminal`. +On Mac, you open the Shell through the Terminal App by pressing meta+space and typing in `Terminal`. -On Windows operating systems, you open up the Shell through the regular command line by pressing `Meta-R` and typing in `cmd`, or the Power-Shell by pressing `Meta-R` and typing in `powershell`. +On Windows operating systems, you open up the Shell through the regular command line by pressing meta+R and typing in `cmd`, or the Power-Shell by pressing meta+R and typing in `powershell`. Your computer will know about the commands available to the Shell because there is a global variable called `PATH` that stores a list of locations for all the programs that the Shell can use. You may have noticed that in the Windows script example we modified this variable with the `setx` command to ensure that Cygwin was added. What this did was add all of the new programs that Cygwin installed so that we can more easily access them in the Shell. On Linux and Mac, these commands are by default installed in a directory ( `/usr/bin` or `/usr/local/bin` ) that is being watched by the Shell so that all new commands are added. @@ -78,19 +80,7 @@ We will output "Hello from TCL!" and use TCL/Expect to verify this from the term ``` 1. Open the file `hello-world.tcl` in a plain text editor (Notepad, Sublime, Nano, etc.) and copy-paste the following. Again, it is very important to keep the white space exactly as is shown in the code: ``` - #!/usr/bin/env expect - spawn echo "Hello World from TCL/Expect!" - - expect { - "Hello world." { - puts "Success!" - exit 0 - } - default { - puts "Error!" - exit 1 - } - } +esyscmd({{sed -n 24,33p ../src/T1/step-2-command-line-101/hello-world.tcl | sed 's/^/ /g' | ghead -c -1}}) ``` 1. To run this program open up a shell and change directories to the saved file. To do this you should type: ``` @@ -104,9 +94,7 @@ We will output "Hello from TCL!" and use TCL/Expect to verify this from the term You should see the following displayed on your command line screen: ``` -$ spawn echo Hello World from TCL/Expect! -Hello World from TCL/Expect! -Error! +$ esyscmd({{expect ../src/T1/step-2-command-line-101/hello-world.tcl | sed -n 1,3p | ghead -c -1}}) ``` ## Troubleshooting Errors @@ -124,9 +112,7 @@ If it doesn't see the text after a default amount of time, then print that we ha What can we do to modify the program to have the following output without changing the code on the line with `"Error!"` to `"Success!"` (change what Expect is expecting)? ``` -$ spawn echo Hello World from TCL/Expect! -Hello World from TCL/Expect! -Success! +$ esyscmd({{expect ../src/T1/step-2-command-line-101/hello-world-fixed.tcl | ghead -c -1}}) ``` ## Summary @@ -141,9 +127,10 @@ Congrats on modifying your first program and fixing a bug! With the TCL/Expect t 1. Additional Windows Shell CMDs - https://ss64.com/nt/ 1. TCL/Expect main wiki - http://wiki.tcl.tk/ 1. Expect tutorials - https://wiki.tcl.tk/11584 -1. Answer - +1. Answer - <{{}}__project_repo_source_root__{{}}/T1/step-2-command-line-101> # Updates -* Nov 11. 2020 - Added good command line reference to ss64. +* Jan 1, 2021 - Generated from m4 template +* Nov 11, 2020 - Added good command line reference to ss64. [[Previous Page|T1-01]] | [[Next Page|T1-04]] \ No newline at end of file diff --git a/Generate-Wiki/Tutorial 1/T1-04.md b/templates-wiki/Tutorial 1/T1-04.md.m4 similarity index 77% rename from Generate-Wiki/Tutorial 1/T1-04.md rename to templates-wiki/Tutorial 1/T1-04.md.m4 index e1bb21b..c1e7332 100644 --- a/Generate-Wiki/Tutorial 1/T1-04.md +++ b/templates-wiki/Tutorial 1/T1-04.md.m4 @@ -1,10 +1,11 @@ +__project_under_construction_flag__ # Step 3: Your First C Program We will move quickly through this next step, but will show you how to download the Git repository with the answers. Open your Shell and navigate to a good location to store the code and run the following: -``` -$ git clone https://github.com/betsalel-williamson/Programming-Tutorial.git +```Bash +$ git clone __project_repo__ $ cd Programming-Tutorial $ ls ``` @@ -20,10 +21,10 @@ This step has the following parts: ## Part 1 Hello World Create a file named `main.c` in the directory `tutorials/step-3-hello-world/1-Hello-World` and copy the following code to it. -``` -int main ( ) { - write(1, "Hello World", 12); - return 0; +```C +int main ( ) { + write( 1, "Hello World", 12 ); + return 0; } ``` @@ -80,14 +81,8 @@ We can run these using the `exec` function in TCL and the programs `rm` and `gcc Next is the code to run our program `main`. For our first test we will `spawn` our program with the argument `"Hello World"`. We can use the `expect` command like in the first step to see that we output the text "Hello World". Finally, we get the exit code of our program with the following code: -``` -expect eof -catch wait result -if {[lindex $result 3] == 0} { - puts "Exited successfully.\n" -} else { - puts "Test failed with code [lindex $result 3].\n" -} +```Tcl +esyscmd({{sed -n '33,38p' ../src/T1/step-4-hello-world/2-Test-Hello-World/test.tcl | sed 's/^/ /g' | ghead -c -1}}) ``` For our second test we only need to test that the exit code is 1. @@ -96,65 +91,15 @@ Once your tests are complete, see that when you run them that they both fail. If Here is a version of the `test.tcl` file you can base your code off of: -``` -#!/bin/env expect - -exec rm main -exec gcc -w main.c -o main - -### Test 1 ### - -spawn ./main "Hello World" -expect { - -nocase "hello world" { - puts "\nFound output of: Hello World\n" - } - default { - puts "\nTest failed. Expected Hello world\n" - } -} - -expect eof -catch wait result -if {[lindex $result 3] == 0} { - puts "Exited successfully.\n" -} else { - puts "Test failed with code [lindex $result 3].\n" -} - -### Test 2 ### - -spawn ./main -expect eof -catch wait result - -if {[lindex $result 3] == 1} { - puts "Exited successfully.\n" -} else { - puts "Test failed with code [lindex $result 3].\n" -} +```Tcl +esyscmd({{sed -n '9,57p' ../src/T1/step-4-hello-world/2-Test-Hello-World/test.tcl | sed 's/^/ /g' | ghead -c -1}}) ``` Now that we have failing tests, we will now modify the main function to accept what is called an input argument and to output this to the Shell. Modify your `main.c` file with the following: -``` -int main ( int argc, const char* argv[] ) { - int exit_value = -1; - - if ( argc == 2 ) { - - while(argv[1][i] != '\0'){ - i = i+1; - } - - exit_value = 0 - } else { - exit_value = 1; - } - - return exit_value; -} +```C +esyscmd({{sed -n '10,25p' ../src/T1/step-4-hello-world/2-Test-Hello-World/main.c | sed 's/^/ /g' | ghead -c -1}}) ``` We've left an error in the code for you to fix. Once it is correct, you should see that your tests now all pass! @@ -173,11 +118,11 @@ With `int exit_value = -1;` we next declare a variable to hold our exit code and Next, we check with `if ( argc == 2 )` that we only have 2 arguments. __We'll come back to this point of 2 arguments in a bit.__ If we have two arguments, then we find the length of the text passed in with the following lines. First we create a variable to hold our place, then while the current character in the string passed in isn't the null character or `\0` (this is how C lets you know that you've reached the end of your string) we increment `i`: -``` -int i = 0; -while(argv[1][i] != '\0'){ - i = i+1; -} + +```C + while( argv[1][i] != '\0' ) { + i = i + 1; + } ``` Next we can output the string in `argv` to the Shell with `write(1, argv[1], i);`. @@ -199,55 +144,44 @@ Welcome to GNU make or the makefile! There is a scripting language called `makef ### Makefile introduction -``` -CC=gcc -OBJ=main.o - -%.o: %.c $(DEPS) - $(CC) -g -c -o $@ $< - -main: $(OBJ) - gcc -o $@ $^ $(CFLAGS) - -clean: - -rm *.o main main.exe +```Makefile +esyscmd({{sed -n '7,28p' ../src/T1/step-4-hello-world/3-Makefile-Hello-World/makefile | sed 's/^ / /g' | ghead -c -1}}) ``` Notice that we are now failing the build process as is shown: ``` $ make -gcc -g -c -o main.o main.c -main.c: In function 'main': -main.c:35:3: warning: implicit declaration of function 'write' [-Wimplicit-function-declaration] - write(1, argv[1], i); - ^~~~~ -gcc -o main main.o -Wall -Werror -Wextra +esyscmd({{pushd ../src/T1/step-4-hello-world/3-Makefile-Hello-World > /dev/null 2>&1 && make clean > /dev/null 2>&1 && make > temp-output.log 2>&1 && popd > /dev/null 2>&1}})dnl +esyscmd({{pushd ../src/T1/step-4-hello-world/3-Makefile-Hello-World > /dev/null 2>&1 && cat temp-output.log && popd > /dev/null 2>&1}})dnl ``` Lets walk through this step by step: 1. `$ make` is the command we typed in the Shell -1. `gcc -g -c -o main.o main.c` is the command that make will run to compile our program +1. `esyscmd({{pushd ../src/T1/step-4-hello-world/3-Makefile-Hello-World > /dev/null 2>&1 && cat temp-output.log | sed -n '1p' | ghead -c -1 && popd > /dev/null 2>&1}})` is the command that make will run to compile our program 1. The following is a chunk that tells us there's something up with the `main` function. ``` - main.c: In function 'main': - main.c:35:3: warning: implicit declaration of function 'write' [-Wimplicit-function-declaration] +esyscmd({{pushd ../src/T1/step-4-hello-world/3-Makefile-Hello-World > /dev/null 2>&1 && cat temp-output.log | sed -n '2p' | sed 's/^/ /g' && popd > /dev/null 2>&1}})dnl ``` - The file that we need to look at is `main.c`, we then need to look at `main.c:35:3` that means the file `main.c`, line 35, column 3. `warning` means that if we wanted to compile, it will work, but this is not recommended by the compiler. `implicit declaration of function 'write'` means that it found a function that we didn't explicitly tell the compiler where to find it. System functions like `printf`, `write`, are assumed to be available if you don't list them with an `include` directive. Lastly the part `[-Wimplicit-function-declaration]` is the computer code for the type of error. -1. The next few lines are the pretty version of what is at line 35, column 3. +pushdef({{__err_line_num__}}, {{esyscmd({{pushd ../src/T1/step-4-hello-world/3-Makefile-Hello-World > /dev/null 2>&1 && cat temp-output.log | perl -lane 'print /main[.]c:(\d+):\d+/' | tr -d '\n' && popd > /dev/null 2>&1}})}})dnl +pushdef({{__err_col_num__}}, {{esyscmd({{pushd ../src/T1/step-4-hello-world/3-Makefile-Hello-World > /dev/null 2>&1 && cat temp-output.log | perl -lane 'print /main[.]c:\d+:(\d+)/' | tr -d '\n' && popd > /dev/null 2>&1}})}})dnl + + The file that we need to look at is `main.c`, we then need to look at `esyscmd({{pushd ../src/T1/step-4-hello-world/3-Makefile-Hello-World > /dev/null 2>&1 && cat temp-output.log | perl -lane 'print /(main[.]c:\d+:\d+)/' | tr -d '\n' && popd > /dev/null 2>&1}})` that means the file `main.c`, line `{{}}__err_line_num__{{}}`, column `{{}}__err_col_num__{{}}`. + + `implicit declaration of function 'write'` means that it found a function that we didn't explicitly tell the compiler where to find it. System functions like `printf`, `write`, are assumed to be available if you don't list them with an `include` directive. Lastly the part `[-Werror,-Wimplicit-function-declaration]` is the computer code for the type of error. +1. The next few lines are the pretty version of what is at line `{{}}__err_line_num__{{}}`, column `{{}}__err_col_num__{{}}`. ``` - write(1, argv[1], i); - ^~~~~ +esyscmd({{pushd ../src/T1/step-4-hello-world/3-Makefile-Hello-World > /dev/null 2>&1 && cat temp-output.log | sed -n '3,4p' && popd > /dev/null 2>&1}})dnl ``` -1. We then see that as the last step gcc will be compiling the program to make sure any warnings are treated as compile errors and should stop any further compilation progress. + We now need to add the information in our code for where the compiler should find the write function. In the next part we will get into more detail about C functions. For now, we can tell gcc where to explicitly find the `write` function with an include statement at the head of our `main.c` file. The include statement will tell the compiler that there are additional code files that we want to include when we make our executable. ``` -#include +esyscmd({{sed -n '18p' ../src/T1/step-4-hello-world/3-Makefile-Hello-World/main-fixed.c | ghead -c -1}}) ``` @@ -289,6 +223,9 @@ Congrats on finishing this last step and for completing the first tutorial! You' 1. About the write function - https://linux.die.net/man/2/write 1. StackOverflow about makefiles - https://stackoverflow.com/questions/2481269/how-to-make-a-simple-c-makefile#2481326 1. StackOverflow about makefiles 2 - https://stackoverflow.com/questions/1079832/how-can-i-configure-my-makefile-for-debug-and-release-builds#1080180 -1. Answers - +1. Answers - <{{}}__project_repo_source_root__{{}}/T1/step-4-hello-world> + +# Updates +* Jan 1, 2021 - Generated from m4 template [[Previous Page|T1-02]] | [[Next Page|T2-00]] \ No newline at end of file diff --git a/Generate-Wiki/Tutorial 2/T2-00.md b/templates-wiki/Tutorial 2/T2-00.md.m4 similarity index 88% rename from Generate-Wiki/Tutorial 2/T2-00.md rename to templates-wiki/Tutorial 2/T2-00.md.m4 index 557e0f7..7696f7d 100644 --- a/Generate-Wiki/Tutorial 2/T2-00.md +++ b/templates-wiki/Tutorial 2/T2-00.md.m4 @@ -1,3 +1,4 @@ +__project_under_construction_flag__ # Crash Course in C - Crack The Code + +# Updates +* Jan 1, 2021 - Generated from m4 template [[Previous Page|T1-04]] | [[Next Page|T2-01]] \ No newline at end of file diff --git a/Generate-Wiki/Tutorial 2/T2-01.md b/templates-wiki/Tutorial 2/T2-01.md.m4 similarity index 99% rename from Generate-Wiki/Tutorial 2/T2-01.md rename to templates-wiki/Tutorial 2/T2-01.md.m4 index 3b93b4d..3ff7fc8 100644 --- a/Generate-Wiki/Tutorial 2/T2-01.md +++ b/templates-wiki/Tutorial 2/T2-01.md.m4 @@ -1,3 +1,4 @@ +__project_under_construction_flag__ # Walkthrough of `secretProgram` We will work through every line of the `secretProgram` and will instruct you how it all works. You should have already completed the first tutorial and downloaded the code. Open up the following two directories at the same time in your text editor program, Windows Explorer, or Finder: @@ -518,8 +519,11 @@ Congratulations! You've made it through to understanding how the `secretProgram` ## References -1. Code - +1. Code - <{{}}__project_repo_source_root__{{}}/T2/step-1-code-gen> 1. Google style guide - 1. Stackoverflow discussion on malloc and strings - +# Updates +* Jan 1, 2021 - Generated from m4 template + [[Previous Page|T2-00]] | [[Next Page|T2-02]] \ No newline at end of file diff --git a/Generate-Wiki/Tutorial 2/T2-02.md b/templates-wiki/Tutorial 2/T2-02.md.m4 similarity index 94% rename from Generate-Wiki/Tutorial 2/T2-02.md rename to templates-wiki/Tutorial 2/T2-02.md.m4 index 7881727..a283eff 100644 --- a/Generate-Wiki/Tutorial 2/T2-02.md +++ b/templates-wiki/Tutorial 2/T2-02.md.m4 @@ -1,3 +1,4 @@ +__project_under_construction_flag__ # Crack the Code Now that we have an understanding of come C programs it is up to you to devise a solution written in C to crack the code! @@ -23,4 +24,7 @@ You may want to copy the makefile to compile your code that is in the solutions Again, the way the `secretProgram` works is that it takes the current date and time down to the minute, `XOR`s this number with a hash and then that is the password. If the correct password was entered then it outputs success message and exits with the code `0`. If not, then the program displays exits with the code `1`. You can try and work out the hash and compute things manually, but in this case it will be easier to build a C program that will run the program as long as it takes to get the correct answer. +# Updates +* Jan 1, 2021 - Generated from m4 template + [[Previous Page|T2-01]] | [[Next Page|T2-03]] \ No newline at end of file diff --git a/Generate-Wiki/Tutorial 3/T1-03.md b/templates-wiki/Tutorial 3/T1-03.md.m4 similarity index 92% rename from Generate-Wiki/Tutorial 3/T1-03.md rename to templates-wiki/Tutorial 3/T1-03.md.m4 index 0fb5c8e..89cc517 100644 --- a/Generate-Wiki/Tutorial 3/T1-03.md +++ b/templates-wiki/Tutorial 3/T1-03.md.m4 @@ -1,3 +1,4 @@ +__project_under_construction_flag__ # Step 3: Version Control 101 With this step you will get a crash course in version control using the Git system and download the rest of the code for you to follow along. Again, nothing is stopping you from looking at the answers to complete this tutorial, but it is for your benefit to sweat things out and to use your critical thinking skills to work through any problems you have as a first step before jumping to the answers. So why are we telling you to download the answers? We are teaching you here about downloading the code from the internet in a way that will allow you to save changes to your code and come back to them later. @@ -15,10 +16,10 @@ _Had I not been using version control software, they would have had to cancel th Open up your shell and navigate to your code directory created in the previous step. Change directories (cd) into `Code` and execute the following command: ``` -$ git clone https://github.com/bhw7/SERC-Pitt-Programming-Tutorial.git +$ git clone __project_repo__ ``` -You should see the shell telling you that it is cloning into ‘SERC-Pitt-Programming-Tutorial’. When it has finished, cd into `SERC-Pitt-Programming-Tutorial`. +You should see the shell telling you that it is cloning into ‘{{}}__project_repo_name__{{}}’. When it has finished, cd into `{{}}__project_repo_name__{{}}`. As a quick tip, you can press the TAB key after typing in SERC to auto-complete the rest of the folder. Most shells will have this auto-completion feature (if the Shell auto-complete feature is not working, use the internet to search your specific shell and find out how to enable it) . @@ -36,7 +37,7 @@ You should now see the `.gitignore` and `.gitattributes` file in addition to a ` ## Part 3 Branch -Because sometimes you want to go down a rabbit hole and try something out, or share your project with other people, we will introduce you to the concept of code branches. This topic will be covered more in detail later on. For now know that Git will store the information by default in the branch with the name `master`. It is a best practice after you finish the initial steps in setting up your repository to start a branch named `develop` and work from it. +Because sometimes you want to go down a rabbit hole and try something out, or share your project with other people, we will introduce you to the concept of code branches. This topic will be covered more in detail later on. For now know that Git will store the information by default in the branch with the name `main`. It is a best practice after you finish the initial steps in setting up your repository to start a branch named `develop` and work from it. In a professional environment, all work should be done in a specific `features` branch, and then merged to the `develop` branch only when you have finished a feature and tested that it works. A merge will synchronize the changes between these two branches. We will wait to cover merging in the later Git tutorial. @@ -139,10 +140,13 @@ Replace the text between the quotes with a short comment on what you did in this If you are already familiar with Git you may have noticed that we did not tell you about pushing the changes or saving the changes back to the cloud. We will be covering this in the later tutorial. ## References -1. Quick start guide to Git - https://rogerdudler.github.io/git-guide/ -1. Git main website - https://git-scm.com/ -1. Highly recommended GUI version of Git - https://www.gitkraken.com/ -1. StackOverflow on Git reverting - https://stackoverflow.com/questions/927358/how-to-undo-the-most-recent-commits-in-git#927386 -1. Answer - https://github.com/bhw7/SERC-Pitt-Programming-Tutorial/blob/master/T1/step-3-version-control-101 +1. Quick start guide to Git - +1. Git main website - +1. Highly recommended GUI version of Git - +1. StackOverflow on Git reverting - +1. Answer - <{{}}__project_repo_source_root__{{}}/T1/step-3-version-control-101> + +# Updates +* Jan 1, 2021 - Generated from m4 template [[Previous Page|T1-02]] | [[Next Page|T1-04]] \ No newline at end of file diff --git a/Generate-Wiki/Tutorial 3/T3-00.md b/templates-wiki/Tutorial 3/T3-00.md.m4 similarity index 76% rename from Generate-Wiki/Tutorial 3/T3-00.md rename to templates-wiki/Tutorial 3/T3-00.md.m4 index 138d252..2a99d7c 100644 --- a/Generate-Wiki/Tutorial 3/T3-00.md +++ b/templates-wiki/Tutorial 3/T3-00.md.m4 @@ -1,7 +1,11 @@ +__project_under_construction_flag__ # The rest The information in this tutorial was other information that was moved outside the initial two tutorials. The reason for this content not being included was becuase it was not directly relevant to a crash course in getting C to run. The information herein is still important for any programmer. I highly recommend that you review this and add these tools to your arsenal. The topics include: Git - Dicussion on using ethical use of code \ No newline at end of file + Dicussion on using ethical use of code + +# Updates +* Jan 1, 2021 - Generated from m4 template \ No newline at end of file diff --git a/templates-wiki/_Footer.md.m4 b/templates-wiki/_Footer.md.m4 new file mode 100644 index 0000000..c54bf10 --- /dev/null +++ b/templates-wiki/_Footer.md.m4 @@ -0,0 +1,3 @@ +Authored by __author__ [{{}}__author_email__{{}}](mailto:{{}}__author_email__{{}}). + +For more information about SERC visit [sercpitt.weebly.com](https://sercpitt.weebly.com/) \ No newline at end of file diff --git a/templates-wiki/_Sidebar.md.m4 b/templates-wiki/_Sidebar.md.m4 new file mode 100644 index 0000000..a91d930 --- /dev/null +++ b/templates-wiki/_Sidebar.md.m4 @@ -0,0 +1,8 @@ +* [[Home]] +* [[Tutorial 1: Introduction|T1-00]] + 1. [[Setup|T1-01]] + 1. [[Command Line 101|T1-02]] + 1. [[Your First C Program|T1-04]] +* [[Tutorial 2: Crash Course|T2-00]] + 1. [[Walkthrough of secretProgram|T2-01]] + 1. [[Crack the Code|T2-02]]