CS246 Unix: Shell Script Parameters C:Doing More with Structs

CS246 Unix: Shell Script Parameters C:Doing More with Structs

CS246 Unix: shell script parameters C:doing more with structs April 21 file: printer.c Lab 4/19 void parray2(void * base, size_t nmemb, size_t size, char* fmt) { for (int i = 0; i < nmemb; i++) { • char c = *((char *)base); // problematic line suggest, and printf(fmt, c); provide an base += size; implementation } for, a way to printf(“\n"); make the array } printer program int main(int argc, char const *argv[]) { truly generic srand(time(NULL)); • Hint — function char aa[100]; for (int i = 0; i < 100; i++) pointers!!! aa[i] = 'a' + (rand() % 26); parray2(aa, 100, sizeof(char), "%c"); } 2 char * pprinter3(void * item) { char *citem = (char *)item; char *rtn = malloc(6 * sizeof(char)); A v3 sprintf(rtn, "<%c>", *citem); return rtn; } • Problems ?? void parray3(void * base, size_t nmemb, size_t size, char *(*f)(void *)) { for (int i = 0; i < nmemb; i++) { printf("%s ", f(base)); base += size; } printf("\n"); } int main(int argc, char const *argv[]) { srand(time(NULL)); char aa[100]; for (int i = 0; i < 100; i++) aa[i] = 'a' + (rand() % 26); parray3(aa, 10, sizeof(char), pprinter3); 3 } void parray3(void * base, size_t nmemb, size_t size, char*(*f)(void*)) { A v3a, v4 for (int i = 0; i < nmemb; i++) { char *tmp = f(base); printf("%s ", tmp); base += size; • free the memory!! free(tmp); } printf("\n"); • Or statically declare } void pprinter4(void * item, char* printInto) { char array and pass char *citem = (char *)item; it sprintf(printInto, "[%c]", *citem); } • advantages/ void parray4(void * base, size_t nmemb, size_t size, disadvantages?? void(*f)(void*,char*)) { char aa[100]; for (int i = 0; i < nmemb; i++) { f(base, aa); printf("%s ", aa); base += size; } printf("\n"); 4 } Shell Scripts — command line params • recall $1 … $9 are arguments 1..9 on command line • $0 is the name of the script • just like main in C • If you have more than 9, then ${12}, • can do this on all … ${4} == $4 • BUT this does not • FOU=4 ${$FOU} • So … how to loop through command line args???? 5 Working with lots of command line args • When would this come up?? • Recall script from 2 weeks ago for totaling up size of executables with an extension • This was limited as it required that the files have a common extension. • Better would be just to take a set of files as command line args • for instance “p.sh *.exe L*” • This would pass to the script p.sh all files that either begin with L or end with .exe • There could be 100s 6 shell scripts with lots of command line params • This approach works #!/bin/bash • kind of PP="$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}“ • When there are less for aa in $PP than 10 CLPs they do get put into the echo $aa string PP as blanks so done the iteration only goes for existing values • Problem: more than 10 7 Handling larges number of CLPs • $* and $@ #!/bin/bash • both “expand into the list of for aa in $* positional parameters do echo "A $aa" done • $# for aa in $@ • the number of positional do parameters echo "B $aa" done • GACKK — this is feeling like Perl 8 Loop over all Command line params file: summer.sh command line params FILES=`ls *.${1}` TOT=0 TOT=0 for FILE in $@ for FILE in $FILES do do if [[ -x $FILE && -f $FILE ]] Added condition that DET=`ls -l $FILE` item must be a file then CNT=0 and be executable DET=`ls -l $FILE` for DETP in $DET CNT=0 do for DETP in $DET #echo "$CNT $DETP" do if [ $CNT -eq 4 ] if [ $CNT -eq 4 ] then then TOT=$(( $TOT + $DETP )) TOT=$(( $TOT + $DETP )) #echo $DETP echo $FILE $DETP fi fi ((CNT++)) ((CNT++)) done done done fi echo $TOT done 9 echo $TOT HAIRBALL!!! Shell Script Arrays actually the number of items in array #!/bin/bash AA=(ONE TWO THREE) for ((i=0; i<${#AA[@]}; i++)) Create an array do echo $i ${AA[$i]} $AA[$i] done This will print the Correct way to get value of $AA followed array value by value of $i inside [] 10 Putting this together #!/bin/bash TOT=0 for FILE in $@ do String result of command is if [[ -x $FILE && -f $FILE ]] broken apart then put into then array! ADET=( `ls -l $FILE` ) TOT=$(( $TOT + ${ADET[4]} )) echo $FILE ${ADET[4]} ((CNT++)) fi Using array index avoids done awkward and strange loop. echo $TOT 11 Making structs more Object like • transparent inheritance • functions • private vars 12 #include <stdio.h> typedef struct { int x; Transparent int y; } aa; inheritance Anonymous union typedef struct { contains both • anonymous structures/ union { anonymous struct and aa; unions named struct. aa aaa; • allow referring to items in }; You can use either!! int z; included structures without } bb; annoying extra dots (which I always forget) int main(int argc, char const *argv[]) { • MUST COMPILE USING bb b; Using both! gcc -fms-extensions b.aaa.x = 10; typedef struct { b.y = 40; int x; b.z = 20; int y; printf("%d %d %d\n", b.z, b.aaa.x, b.y); } aa; return 0; typedef struct { } aa; Simple use int z; 13 } bb; file: sp1.h function pointers typedef struct qq { int a; int b; in structs void (*printer)(struct qq *); } qq; • Why: qq *makeQQ(int a, int b); • stylistic choice • can fewer naming collisions • the public name is inside file: sp1.c struct so that name does not conflict with anything Name only #include <stdio.h> exists within #include "sp1.h" • In feels “Object-y” this file #include <stdlib.h> • Why not: static void printer(qq * p) { printf("QQ: %d %d\n", p->a, p->b); • space for the pointer } • Cannot do this for qq* makeQQ(int a, int b) { constructors & destructors qq *q = malloc(1 * sizeof(qq)); q->a = a; q->b = b; q->printer = printer; 14 } function pointers #include <stdio.h> in structs #include "sp1.h" • static keyword on void printer(qq* q3) { printer function on printf("333 a:%d b:%d\n", q3->a, q3->b); previous page means } that printer here does not conflict. int main(int argc, char const *argv[]) { • ideally all “private” qq *q = makeQQ(4, 5); functions are static q->printer(q); printer(q); • function is only return 0; “public” through } pointer within the struct. 15 typedef struct { int private1; Private Vars } privNAM; int getYear(privNAM* pn) { • DO NOT EXIST!! return pn->private1; } • But void setYear(privNAM* pn, int yr) { • Privacy through pn->private1 = yr; naming } privNAM* makePrivNAM() { • Idea: name return malloc(1 * sizeof(privNAM)); variable to indicate } they are private int main(int argc, char const *argv[]) { • provide well- privNAM *pn = makePrivNAM(); named get/set setYear(pn, 1961); • People can still printf("%d\n", getYear(pn)); directly read but it is return 0; clear they should not. } 16 typedef struct { need to void* private1; handle if } privOI; not int getYear(privOI* pn) { allocated Private Variables int *ip = pn->private1; return *ip; } • Privacy through obscure void setYear(privOI* pn, int yr) { indirection Only if (pn->private1 == NULL) { • Idea, store private vars allocate pn->private1 = malloc(1 * sizeof(int)); space } when behind void * pointers int *ip = pn->private1; needed • again, well named get/ *ip = yr; set } privOI* makePrivOI() { • People can change the privOI* poi = malloc(1 * sizeof(privOI)); pointer, but clear they } should not. int main(int argc, char const *argv[]) { privOI *pn = makePrivOI(); • Unreadable!! except setYear(pn, 1961); through determined idiocy. printf("%d\n", getYear(pn)); return 0; } 17 Roll your own typedef struct { garbage collector char *string; } stringRC; • Suppose a struct that contains string • its own private copy typedef struct { stringRC* string; • Also a substring struct int strt; • a pointer to the string struct int len; • starting point for substring } substringRC; • length of substring void printSubstr(substringRC* sstr) { • Problem: for (int i = 0; i < sstr->len; i++) • should not free the string struct until printf("%c", sstr->string->string[sstr->strt + i]); all of the substrings using it are free! printf("\n"); } HOW?? • void printString(stringRC *str) { printf("%s\n", str->string); • Create your own mini garbage collector!! } 18 Implement void freeStringRC(stringRC* str) { if (str->refCount==0) { printf(“NO Refs -- freeing\n"); reference counting free(str->string); free(str); typedef struct { Free main string iff there are no } else { char *string; references to it printf("Not freeing -- still has refs [%d]\n", str->refCount); int refCount; Otherwise mark it as ready to str->mainFreed = 1; int mainFreed; be freed } } stringRC; } void freeSubstringRC(substringRC* src) { stringRC* makeStringRC(char * src) { stringRC *tmp = src->string; // stuff not shown free(src); rc->refCount = 0; tmp->refCount--; rc->mainFreed = 0; if (tmp->refCount==0 && tmp->mainFreed) { return rc; freeStringRC(tmp); } } } substringRC* makeSubstringRC(stringRC* str, int call free on main string iff the st, int len) { only reason main string exists is // stuff not shown because of references str->refCount++; return src; 19 } int main(int argc, char const *argv[]) int main(int argc, char const *argv[]) { { stringRC *rc = makeStringRC("now stringRC *rc = makeStringRC("now is the time of all good people to come is the time of all good people to come to the aid of their country"); to the aid of their country"); substringRC *src1 = substringRC *src1 = makeSubstringRC(rc, 0, 5); makeSubstringRC(rc, 0, 5); printSubstr(src1); printString(rc); freeSubstringRC(src1); freeStringRC(rc); printString(rc); printSubstr(src1); freeStringRC(rc); freeSubstringRC(src1); return 0; return 0; } } 20 Lab • Write a shell script that sums the size of all writeable files in this directory and all directories immediately below this directory. • The shell script should not do any directory traversal or listing on its own. Rather all of the file names should be given as command line parameters • Send me a copy of your script and the unix command line through which this script would be invoked to do the above task.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    21 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