CS246 Unix: More Shell Scripting C:Queues April 8 Apropos

CS246 Unix: More Shell Scripting C:Queues April 8 Apropos

CS246 Unix: more shell scripting C:queues April 8 apropos • get a listing of all commands that have the word in a short version of their man page • UNIX> apropos file • not working on my mac • UNIX> apropos file | wc returns 1198 possible items • Contrast with “which” gtowell@benz:~$ apropos gzip gzip (1) - compress or expand files lz (1) - gunzips and shows a listing of a gzip'd 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/bash 2.# Basic while loop • if then if • while do done 4.counter=1 5.while [ $counter -le 10 ] 6.do 7.echo $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=`ls` string, splits it and for name in $names works with each part do echo $name • The string to be split 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 • make a link to the file manipulation. This uses it if [ "$1" != "" ]; then ${VAR/replace/replacement} param=$1 using ln -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 | tr -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 • write 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 rm *.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 at 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 <stdio.h> /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 exit status { printf("%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 compiler (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 DeBugger” • Allows you to inspect program while running • breakpoints • conditional breakpoints • Another way to attack segmentation faults • arguably better • Debuggers arguably give a lot more flexibility than print statements 23 A Program 1 #include <stdio.h> 2 #include <stdlib.h> 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 Free Software Foundation, Inc.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    31 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us