CS246 : shell scripting :queues April 8

• get a listing of all commands that have the word in a short version of their

• UNIX> apropos • not working on my mac • UNIX> apropos file | returns 1198 possible items • Contrast with “which” gtowell@benz:~$ apropos gzip (1) - compress or expand files lz (1) - gunzips and shows a listing of a gzip' tar'd archive tgz (1) - makes a gzip'd tar archive uz (1) - gunzips and extracts a gzip'd tar'd archive zforce (1) - force a '.gz' extension on all gzip files 2 Shell script loops

• while loop looks a lot like if execpt 1.#!/bin/ 2.# Basic while loop • if then if • while do done 4.counter=1 5.while [ $counter -le 10 ] 6.do 7. $counter 8.((counter++)) 9.done

11.echo All done 12.

3 loops in shell scripts

• $(( )) in shell script mean — roughly “I am doing #!/bin/bash math inside here” counter=1 • hence “counter=$(($counter+1))” does what you think while [ $counter -le 10 ] • unlike [] not space sensitive do echo $counter • ${} notation for vars is never wrong to use counter=$(($counter+1)) • counter=$((${counter}+1)) ((counter++)) # shortcut form • Sometimes there are shortcuts done • ((counter++)) echo All done • note no leading $ • putting $ would indicate that the math returned a value • I tend away from shortcuts because I never remember them

4 shell loops

#!/bin/bash • Several forms of for # Basic for loop loops exist. names='Stan Kyle Cartman' • This one takes # names=`` string, splits it and for name in $names works with each part do echo $name • The string to be done can come from echo All done anywhere • for instance, from executing ls

5 more shell loops

• note (( )) to #!/bin/bash #!/bin/bash # Basic range in for loop # Basic C-like for loop invoke math- for (( i=1; i<=5; i++ )) like for value in {1..5} do do operations, echo $value echo $i done done • again, the echo All done shortcut echo All done form

6 file l5.sh Space used by files FILES=`ls *.${1}` with an extension TOT=0 for FILE in $FILES • usage: UNIX> l5.sh sh do DET=`ls -l $FILE` • This gives the number of bytes CNT=0 used by all files with .sh extension for DETP in $DET in the current directory do #echo "$CNT $DETP" if [ $CNT -eq 4 ] • The FILES var is actually then unnecessary TOT=$(( $TOT + $DETP )) • kind of wasteful also #echo $DETP • change fi for FILE in $FILES ((CNT++)) to done for FILE in *.$1 done echo $TOT 7 the publish problem Solution #!/bin/bash param="java" bash has some built in text • a link to the file manipulation. This uses it if [ "$1" != "" ]; then ${VAR/replace/replacement} param=$1 using -s where the fi link has a browser- for f in *.$param; known extension do Suppose you did not know of echo ${f/./} bash text manipulation • e.g. “.txt” ln -s $f ${f/./}.txt • Allows updating aa=`echo $f | -d .` done without having to recopy a lot or

• Create a shell script to aa=`echo $f | tr . d` do this in bulk. ln -s $f ${a}.txt

8 LAB

a shell script that lists all files in the current directory and all direct subdirectories. • This should not be a recursive listing of all subdirectories. Just go one down

9 char* removeTail(DLL *dll) { if (dll->count<=0) Queues return NULL; dll->count--; DLLItem *itm = dll->tail; • Use the DLL struct DLLItem *tprev = itm->prev; • needs more if (tprev==NULL) { • removeTail dll->head = NULL; dll->tail = NULL; return; • Revisit DLLItem } constructor/destructor dll->tail = tprev; and eliminate the copy tprev->next = NULL; into new memory. Just char *rtn = malloc((strlen(itm->payload) + 1) * sizeof(char)); take the thing supplied strcpy(rtn, itm->payload); freeDLLItem(itm); • Otherwise need to take } care to free the returned thing!! required because the info would be lost otherwise, but!!!! 10 typedef struct { Q Basics DLL *internal; } Queue;

• Constructor, Queue* makeQueue() { destructor, and Queue *rtn = malloc(1 * sizeof(Queue)); struct are pretty rtn->internal = makeDLL(); minimal return rtn; }

void freeQueue(Queue* q) { freeDLL(q->internal); free(q); }

11 Q more

void add2Queue(Queue* q, char* item) { • rest is pretty basic addDLLHead(q->internal, item); also }

char* pullFromQueue(Queue* q) { • Essentially all work return removeTail(q->internal); done by DLL! }

12 Splitting & Making CFLAGS = -g -O2

• I made a single dll.c and dll: dll.c dll.h dll.h gcc $(CFLAGS) -o dll dll.c

• IMHO DLLItem is more queue: dll.o queue.c a private inner class gcc $(CFLAGS) -o queue dll.o queue.c and so it does not get its own file(s) dll.o: dll.c dll.h gcc $(CFLAGS) -c -D DOTO=1 dll.c • but this is a style choice clean: • Also a .c and .h for *.o dll queue queue

13 file a.h file b.h

typedef struct { #include "a.h" Splitting Issues 1 int v1; typedef struct { } A; A oneA; } B; • C does not allow typedefs to be declared multiple times • explicitly forbidden in C11 • Consider three files right file b.c • when compile get error • a.h:3:3: note: previous declaration of #include "a.h" ‘A’ was here #include "b.h" 3 | } A; B b; • Solution 1 … instruct users to avoid the issue … A a; • do not actually need the a.h include since it comes int main(int argc, char const *argv[]) { in with b.h return 0; • lousy solution since it relies on everyone knowing and REMEMBERING } • Also, a.h may come in via some other .h file so even if you assume people remember a conflict can occur

14 file a.h

Splitting issues 1 #ifndef TYPE_A_DEFINED typedef struct { continued int v1; } A; • Better solution is to ensure #define TYPE_A_DEFINED 1 that definitions can only occur #endif once!! • use #ifndef … #endif file b.h

#include "a.h"

#ifndef TYPE_B_DEFINED typedef struct { A oneA; } B; #define TYPE_B_DEFINED 1 #endif 15 file s1.h file s1.c

int doS1(); #include "s1.h" Splitting Issues 2 int doS1() { return 42; } • Problem • this all looks correct … and it is file s2.c

• but gcc fails #include "s1.h" [gtowell@powerpuff L14]$ gcc s2.c #include /bin/ld: /tmp/cc8w1v2M.o: in function `main': s2.c:(.text+0x15): undefined reference to `doS1' int main(int argc, char const *argv[]) collect2: error: ld returned 1 status { ("%d\n", doS1()); • Why? return 0; } • Linking issues!!!

16 Splitting Issues 2 Continued • Recall that gcc actually takes 3 steps • 1. Preprocess • 2. Compile • 3. Link • In this case preprocess and compile both work fine. • Those steps take the function prototypes as promises that the definition will appear later • later MUST be in the link.

• in this case there is no body supplied for Use a makefile!!! doS1()

[gtowell@powerpuff L14]$ gcc -c s1.c [gtowell@powerpuff L14]$ gcc -o s2 s2.c s1.o 17 file m1.h file m2.h Splitting issue 3 int dom1(); int doS1();

• I want each of my .c files to file m1.c file m2.c have a main function for int dom1() { #include "m1.h" testing purposes. But if I do return 42; that, the (actually } int dom2() { the linker) complains return 84; int main(int argc, } [gtowell@powerpuff L14]$ gcc m1.c char const [gtowell@powerpuff L14]$ ./a.out *argv[]) int main(int argc, M1 42 char const *argv[]) [gtowell@powerpuff L14]$ gcc -c m1.c { [gtowell@powerpuff L14]$ gcc m2.c m1.o printf("M1 { /bin/ld: m1.o: in function `main': %d\n", dom1()); printf("M2 %d m1.c:(.text+0xb): multiple definition of `main'; /tmp/ return 0; %d", dom1(), cctzIOI8.o:m2.c:(.text+0xb): first defined here } dom2()); collect2: error: ld returned 1 exit status return 0; } 18 Splitting issue 3 continued file m1.c • The problem is that there are two implementations of main and they conflict. int dom1() { • Once solution would be to put the main functions into return 42; their own file and compile/link appropriately }

• This gets cumbersome (lots of files) and it looses the #ifndef M1C_MAIN clear linkage between the main and the functions being int main(int argc, tested. char const • Better is to wrap main #ifndef *argv[]) { • then when compiling with -c flag a -D to define printf("M1 M1C_MAIN %d\n", dom1()); return 0; [gtowell@powerpuff L14]$ gcc -c -DM1C_MAIN m1.c } [gtowell@powerpuff L14]$ gcc m2.c m1.o #endif [gtowell@powerpuff L14]$ a.out 19 Review

• Pointers, pointers and more pointers • recursion and tail recursion • why tail recursion matters • typedefs • structs • why not pass by value • constructors and destructors • malloc and free • UNIX • putting it all together with scripts

20 STOP HERE

21 Garbage Collection in Java

• Why doesn’t java need free?

22 GDB

• “Gnu ” • Allows you to inspect program while running • breakpoints • conditional breakpoints • Another way to attack segmentation faults • arguably better • arguably give a lot more flexibility than print statements

23 A Program 1 #include 2 #include that breaks 3 4 void smashing() { • gdb loves line numbers 5 int aa[10]; 6 for (int i = 0; i < 20; i++) { • cat -n xxx.c 7 aa[i] = i; 8 } 9 } 10 int main(int argc, char const *argv[]) • Program has three 11 { issues 12 int strt = atoi(argv[1]); 13 int aa[strt]; 14 smashing(); 15 for (int i = 0; i < 1000; i++) 16 { 17 printf("%d %d\n", i, aa[i]); 18 } 19 return 0; 20 }

24 [gtowell@powerpuff L14]$ gcc -g broken.c [gtowell@powerpuff L14]$ gdb a.out gbd usage GNU gdb (GDB) 9.1 Copyright (C) 2020 Foundation, Inc. License GPLv3+: GNU GPL version 3 or later • gcc This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. • compile with -g flag "show copying" and "show warranty" for details. • like This GDB was configured as "x86_64-pc--". Type "show configuration" for configuration details. • UNIX> gdb executable For bug reporting instructions, please see: • Equivalently . the GDB manual and other documentation resources online at: • UNIX> gdb .

• (gdb) file executable For help, type "help". • like valgrind Type "apropos word" to search for commands related to "word"... --Type for more, q to quit, c to continue without paging--q Quit • Does not start the program (gdb)

25 gdb help

• gdb is interactive and runs its own shell-like thing • tab completion for commands • file name completion • help

• (gdb) help [command]

26 gdb basic usage

• quit • exit gdb • run • runs the program without args • run arg1 arg2 … • exactly like UNIX> executable arg1 arg2 …

27 gdb breakpoints

• places where the program execution will stop • you can set as many as you want

• by line number • (gdb) break filename:linenumber • if only a single file can omit filename • gdb broken.c:12 • by function: • (gdb) break smashing • no filename since function names are unique in C

28 gdb doing things at a pause

• (gdb) continue • resume program execution • (gdb) step • advance one line in program • will go into called functions • (gdb) next • does not go into called functions • other debuggers call this “step over” • (gdb) repeat last command

29 gdb — inspecting when program paused

• to look at the value of a variable when program is paused • (gdb) print varName

• (gdb) watch varName • program pauses whenever named var changes!

30 Conditional breakpoints

• (gdb) break 12 if i>10 •

31