This page contains instructions and examples of using the scripts and data files to create the Sony Notebook Control, ACPI Method Analysis page.
The scripts are being constantly updated to enhance automation in preparing the summary tables.
sortHTML.awk and methodsUsage.awk use a quicksort algorithm and are able to sort on a cascading basis. This allows sorts first by BIOS version, then revision, then model-range. Other sort groupings can be applied simply by a series of calls to the function sortGroup().
methodNames.awk reads a CSV containing the latest method usage descriptions so the table is always repopulated correctly.
updateTables.sh, a shell script, scans the HTML file containing the tables, deletes the existing tables (by matching <!-- comments -->) and replaces them with XXXmethodsUsageTable.html, XXXmethodsModelTable.html, and XXXmethodNamesTable.html, where XXX is the device-name.
analyse.sh runs all the tasks from one script, making updating a trivial issue.
$ sudo acpidump -b -t DSDT -o MODEL-BIOS.aml $ iasl -d MODEL-BIOS.aml
If you need to disassemble more than one .aml file (the output of acpidump) you can do this instead of line 2 of the commands above:
$ find . -maxdepth 1 -name '*.aml' -exec iasl -d {} \;
You will now have a collection of DSL files.
Here is the code:
$ find . -maxdepth 1 -name '*.dsl' -exec awk -v html=1 -v device=SNC -f findDevice.awk {} \; $ cat *.SNC.xhtml >SNC.xhtml $ awk -v outfile=SNCmethodsModelTable.html -f sortHTML.awk SNC.xhtml
sortHTML.awk writes the HTML file SNCmethodsModelTable.html. The contents are sorted and ready for inserting into the target HTML file viewed by users.
When findDevice.awk is passed the variable "html=1" HTML is output by the script to filenames of the form MODEL-BIOS.dsl.SNC.xhtml. The individual xhtml files are then combined using 'cat' into the file SNC.xhtml.
Source-code for findDevice.awk
Source-code for sortHTML.awk
If "html=0" or "html" isn't passed as a variable findDevice.awk writes the raw method-names and argc to filenames of the form MODEL-BIOS.dsl.SNC:
$ find . -maxdepth 1 -name '*.dsl' -exec awk -v device=SNC -f findDevice.awk {} \;
When working with the raw .SNC files it is helpful to sort the method names and output to .sorted filenames:
$ cat *.SNC >SNC.unsorted $ sort SNC.unsorted >SNC.sorted $ rm SNC.unsorted
To collect the unique method-names with count:
$ uniq -c SNC.sorted >SNC.uniq $ rm SNC.sorted
To generate the "Methods and Usage by Model" table:
$ find . -maxdepth 1 -name '*.SNC' -exec awk -v outfile=SNCmethodsUsageTable.html -v device=SNC -f methodsUsage.awk SNC.uniq {} \+
The awk program methodsUsage.awk creates the file
SNCmethodsUsageTable.html which can be inserted into a HTML
page. The rows are sorted by BIOS version, revision, and model.
Source-code for methodsUsage.awk
A separate SNCusage.csv file is kept that is hand-edited. It contains a list of known method names and the usage descriptions. E.g. SNCusage.csv:
AZPW,set Audio Z PoWer CBMF,¿Change Battery Mode Flag? CDPW,set CD PoWer CMGB,
This is combined with the unique method-names list in SNC.uniq and formatted in HTML by methodNames.awk to ensure the HTML table doesn't need to be manually edited.
$ awk -v outfile=SNCmethodNamesTable.html -v device=SNC -v SNCusage.csv -f methodNames.awk SNC.uniq
This will create the HTML table in the file
SNCmethodNamesTable.html
Source-code for methodNames.awk
We now have formatted tables in SNCmethodsModelTable.html, SNCmethodsUsageTable.html and SNCmethodNamesTable.html. We should also have the target HTML file (here called index.html) containing markers where each table is to be inserted:
<!-- startSNCTableMethodsUsage --> <!-- endSNCTableMethodsUsage --> <!-- startSNCTableMethodsModel --> <!-- endSNCTableMethodsModel --> <!-- startSNCTableMethodNames --> <!-- endSNCTableMethodNames -->
Anything between each pair of markers will be deleted and replaced by the contents of the respective *Table.html files.
Running the shell script updateTables.sh will execute a series of sed commands to do the replacement:
$ ./updateTables.sh index.html
The shell script updateTime.sh replaces the timestamp of the file to show readers when it was last updated by looking for another pair of <!-- markers -->.
<!-- startLastUpdated --> <!-- endLastUpdated -->
$ ./updateTime.sh index.html
The scripts are modularised so they can analyse other devices besides SNC. The three related devices we need to study are SNC, EC, and SPIC. The steps above are repeated for each of the three devices. There are <!-- markers --> for all three devices in index.html.
With a suitable directory structure the entire process can be automated to run from one shell script.
./ ./aml/ ./dsl/ ./index.html ./snctables.css ./SNCusage.csv ./ECusage.csv ./SPICusage.csv ./methodNames.awk ./methodsUsage.awk ./findDevice.awk ./sortHTML.awk ./updateTables.sh ./updateTime.sh ./analyse.sh
The DSDT AML (ACPI Machine Language) files extracted by acpidump are stored in ./aml/
Disassembled DSL (DSDT Source Language) files are stored in ./dsl/
index.html is the target HTML file (containing the <!-- markers -->).
To update the target HTML file to contain the details of the analysis of all the DSDT files in ./aml/, simply run:
$ ./analyse.sh index.html
BEGIN { if(device=="") { print "Please specify the device with '-v device=XXX' on the command-line"; exit; } # create a dynamic regular expression based on this device reDevice = "Device \(" device "\)"; # Work around gawk FILENAME bug if ((FILENAME=="") || (FILENAME=="-")) { filename=ARGV[ARGC-1]; } else { filename=FILENAME; } split(filename,model,"\."); if(html==1) { outfile=filename "." device ".xhtml"; } else { outfile=filename "." device; } # change field-separator so spaces can be trimmed FS="@"; inDevice=0; countBraces=0; methodQty=0; } { if ($0 ~ reDevice) { inDevice=1; countMethods=0; } else if(inDevice>0 && $0 ~ /Device \(/) { #sub-device, ignore inDevice++; } if (inDevice==1) { if ($0 ~ /\{/ ) { countBraces++; } if (countBraces>0) { if ($0 ~ /Method/ ) { countMethods++; if(html==1) { tableData=tableData "<td>" trim($0) "</td>"; } else { print(trim($0)) >> outfile; } } } } if (inDevice>0 && $0 ~ /\}/ ) { countBraces--; if (countBraces==0) { inDevice--; if(inDevice==0 && html==1) { methodQty=countMethods; tableRow=tableRow tableData; } } } } function trim (string) { gsub ("^ ", "", string); gsub ("Method \(","",string); split(string,names,","); method=names[1] names[2]; return method; } END { if(html==1) { tableRow="<tr><th class=\"align\">" substr(model[2],2) "</th><td>" methodQty "</td>" tableRow "</tr>"; print(tableRow) >> outfile; } else { # write something so a file is created even if no device section was found # otherwise the model won't be added to the Methods and Usage by Model table print "" > outfile; } }
BEGIN { if(outfile =="") { print "Please specify the output file with '-v outfile=filename' on the command-line"; exit; } countRows=0; tableBody=""; } { countRows++; # find cell containing the model-BIOS (always the first th) modStart=index($0,"<th>")+4; modEnd=index($0, "</th>"); mod=substr($0,modStart,modEnd-modStart); # break out the model and BIOS information split(mod,fields,"-"); series = fields[1]; model = fields[2]; bios = fields[3]; m1 = match(model,/[0-9]/); m2 = match(model,/[0-9][A-Z]/); if(m2==0) { # no features m2=length(model)+1; features="" } else { m2++; features=substr(model, m2); } range=substr(model, 1, m2-1); if(length(bios) > 0) { # some model-names weren't provided with the BIOS version # format is RxxxxVV VV=Version-major, Rxxxx=Version-revision versionMajor=substr(bios,6,2); versionRev=substr(bios,2,4); } else { # set defaults to help sorting unknown BIOS versions together versionMajor="ZZ"; versionRev="0000"; } # find cell containing method qty (always the first td) qtyStart=index($0,"<td>")+4; qtyEnd=index($0, "</td>"); qty=substr($0,qtyStart,qtyEnd-qtyStart); # store rows separately so they can be sorted by number of methods, when all models have been processed tableRows[countRows]= $0; # create an alias to make quicksorts easier, containing 'row,methods,series,versionMajor,versionRev,range,features' sortable[countRows]= "" countRows "," qty "," series "," versionMajor "," versionRev "," range "," features; } # functions to quicksort the rows by number of methods used function quicksort(array, left, right, sortField) { if(right > left) { pivotIndex=left; pivotNewIndex=partition(array, left, right, pivotIndex, sortField); quicksort(array, left, pivotNewIndex-1, sortField); quicksort(array, pivotNewIndex+1, right, sortField); } } function partition(array, left, right, pivotIndex, sortField) { # need to split out value from string array split(array[pivotIndex],fields,","); pivotValue = fields[sortField]; swap(array, pivotIndex, right); storeIndex = left; for(i=left; i < right; i++) { split(array[i],fields,","); if(fields[sortField] <= pivotValue) { if(storeIndex != i) { swap(array, storeIndex, i); } storeIndex++; } } split(array[right],fieldsRight,","); split(array[storeIndex],fieldsIndex,","); if(fieldsRight[sortField] < fieldsIndex[sortField]) { swap(array, right, storeIndex); return storeIndex; } else return right; } function swap(array, pivotIndex, right) { tmp = array[pivotIndex]; array[pivotIndex]=array[right]; array[right]=tmp; } function sortSubGroup(sortable, sortGroup, sortField) { currentGroup=""; for(j=1; j<=countRows; j++) { split(sortable[j],sort,","); if(currentGroup=="") { currentGroup=sort[sortGroup]; groupFirst=j; continue; } # look for change of group, or last item if(sort[sortGroup]!=currentGroup) { groupLast=j-1; # sort within the major-version, only if more than one item in the group if(groupFirst < groupLast) { quicksort(sortable, groupFirst, groupLast, sortField); } currentGroup=sort[sortGroup]; groupFirst=j; } else if(j==countRows) { groupLast=j; # sort within the major-version, only if more than one item in the group if(groupFirst < groupLast) { quicksort(sortable, groupFirst, groupLast, sortField); } } } } END { # sortable fields: row,qty,series,versionMajor,versionRev,range,features,model # sort into order by BIOS version quicksort(sortable, 1, countRows, 4); # now sort each group of BIOSversions by revision sortSubGroup(sortable,4,5); # finally sort by model range sortSubGroup(sortable,5,6); # build table from rows, sorting as we go colspan=1; for(i=1; i <= countRows; i++ ) { # break out the 'row,methods,...' values which are now in BIOS version order split(sortable[i],fields,","); # strip out tr tags so the backlight classes can be added trStart=index(tableRows[fields[1]],"<tr>")+4; trEnd=index(tableRows[fields[1]], "</tr>"); cells=substr(tableRows[fields[1]],trStart,trEnd-trStart); # alternate backlight for each row to aid the eye when scanning the table tableRow="<tr class=\"nowrap backlight" ((i % 2) ? 1 : 2) "\">" cells "</tr>\r\n"; # build table tableBody=tableBody tableRow; if(fields[2] > colspan) { # get maximum method qty for the header column-span colspan=fields[2]; } } tableHeader="<tr><th>Model-BIOS</th><th>Qty</th><th colspan=\"" colspan "\">Methodname argc</th></tr>\r\n"; table="<table><tbody>\r\n" tableHeader tableBody "</tbody></table>\r\n"; print( table ) > outfile; }
BEGIN { if(outfile =="") { print "Please specify the output file with '-v outfile=filename' on the command-line"; exit; } if(device=="") { print "Please specify the device with '-v device=XXX' on the command-line"; exit; } deviceFile=device ".uniq"; methodQty=0; countRows=0; tableHeader=""; tableRow=""; filename=""; } FILENAME == deviceFile { if($2 != "") { # ignore lines with no method-name methods[methodQty+1] = $2; used[methodQty+1] = 0; tableHeader=tableHeader "<th>"; for(i=1; i <= length(methods[methodQty+1]); i++ ) { tableHeader=tableHeader substr(methods[methodQty+1],i,1) "<br/>"; } tableHeader=tableHeader "</th>"; methodQty++; next; } } FILENAME != deviceFile { if(filename != FILENAME) { if(filename!="") { buildRow(filename); } # start a new row filename=FILENAME; tableRow=""; countMethods=0; } for (i=1;i <= methodQty; i++) { if($1 == methods[i]) { used[i] = 1; countMethods++; } } } function buildRow(file) { for(i=1; i <= methodQty; i++) { if(used[i]==1) { content="X"; } else { content=" "; } # reset flag for next file used[i] = 0; tableRow=tableRow "<td>" content "</td>"; } # completed row countRows++; split(file,mod,"\."); # store rows separately so they can be sorted by number of methods, when all models have been processed tableRows[countRows]= tableRow; # break out the model and BIOS information tmp=substr(mod[2],2); split(tmp,fields,"-"); series = fields[1]; model = fields[2]; bios = fields[3]; m1 = match(model,/[0-9]/); m2 = match(model,/[0-9][A-Z]/); if(m2==0) { # no features m2=length(model)+1; features=""; } else { m2++; features=substr(model, m2); } range=substr(model, 1, m2-1); if(length(bios) > 0) { # some model-names weren't provided with the BIOS version # format is RxxxxVV VV=Version-major, Rxxxx=Version-revision versionMajor=substr(bios,6,2); versionRev=substr(bios,2,4); } else { # set defaults to help sorting unknown BIOS versions together versionMajor="ZZ"; versionRev="0000"; } # create an alias to make quicksorts easier, containing 'row,methods,series,versionMajor,versionRev,range,features,model' sortable[countRows]= "" countRows "," countMethods "," series "," versionMajor "," versionRev "," range "," features "," tmp; } # functions to quicksort the rows by number of methods used function quicksort(array, left, right, sortField) { if(right > left) { pivotIndex=left; pivotNewIndex=partition(array, left, right, pivotIndex, sortField); quicksort(array, left, pivotNewIndex-1, sortField); quicksort(array, pivotNewIndex+1, right, sortField); } } function partition(array, left, right, pivotIndex, sortField) { # need to split out value from string array split(array[pivotIndex],fields,","); pivotValue = fields[sortField]; swap(array, pivotIndex, right); storeIndex = left; for(i=left; i < right; i++) { split(array[i],fields,","); if(fields[sortField] <= pivotValue) { if(storeIndex != i) { swap(array, storeIndex, i); } storeIndex++; } } split(array[right],fieldsRight,","); split(array[storeIndex],fieldsIndex,","); if(fieldsRight[sortField] < fieldsIndex[sortField]) { swap(array, right, storeIndex); return storeIndex; } else return right; } function swap(array, pivotIndex, right) { tmp = array[pivotIndex]; array[pivotIndex]=array[right]; array[right]=tmp; } function sortSubGroup(sortable, sortGroup, sortField) { currentGroup=""; for(j=1; j<=countRows; j++) { split(sortable[j],sort,","); if(currentGroup=="") { currentGroup=sort[sortGroup]; groupFirst=j; continue; } # look for change of group, or last item if(sort[sortGroup]!=currentGroup) { groupLast=j-1; # sort within the major-version, only if more than one item in the group if(groupFirst < groupLast) { quicksort(sortable, groupFirst, groupLast, sortField); } currentGroup=sort[sortGroup]; groupFirst=j; } else if(j==countRows) { groupLast=j; # sort within the major-version, only if more than one item in the group if(groupFirst < groupLast) { quicksort(sortable, groupFirst, groupLast, sortField); } } } } END { # build final row (loop always has one in hand) buildRow(filename); # sortable fields: row,qty,series,versionMajor,versionRev,range,features,model # sort into order by BIOS version quicksort(sortable, 1, countRows, 4); # now sort each group of BIOSversions by revision sortSubGroup(sortable,4,5); # finally sort by model range sortSubGroup(sortable,5,6); # build table from rows, sorting as we go for(i=1; i <= countRows; i++ ) { # break out the 'row,methods,model' values which are now in 'methods' order split(sortable[i],fields,","); # alternate backlight for each row to aid the eye when scanning the table tableRow="<tr class=\"backlight" ((i % 2) ? 1 : 2) "\"><th class=\"align\">" fields[8] "</th><td>" fields[2] "</td>" tableRows[fields[1]] "<th>" fields[8] "</th></tr>\r\n"; # build table tableBody=tableBody tableRow; } tableHeader="<tr><th>Model-BIOS</th><th>Qty</th>" tableHeader "<th>Model-BIOS</th></tr>\r\n"; table="<table><tbody>\r\n" tableHeader tableBody "</tbody></table>\r\n"; print( table ) > outfile; }
BEGIN { if(outfile =="") { print "Please specify the output file with '-v outfile=filename' on the command-line"; exit; } if(device=="") { print "Please specify the device with '-v device=XXX' on the command-line"; exit; } if(csv=="") { print "Please specify the CSV file with '-v csv=filename' on the command-line"; exit; } deviceFile=device ".uniq"; # read the csv usage file while(getline < csv == 1) { split($0,fields,","); # associative array: methods["AZPW"] = "???" methods[fields[1]] = fields[2]; } close(csv); tableHeader="<tr><th>Method</th><th>argc</th><th>Used</th><th>Usage</th></tr>\r\n"; tableRows=""; } { if($2 != "") { # ignore lines with no method-name tableRow="<tr><th>" $2 "</th><td>" $3 "</td><td>" $1 "</td><td>" methods[$2] "</td></tr>\r\n"; tableRows=tableRows tableRow; } } END { print( "<table><tbody>\r\n" tableHeader tableRows "</tbody></table>\r\n") > outfile; }
#!/bin/bash if [ "x$1" = "x" ]; then target="index.html" else target=$1 fi # back-up HTML cp ${target} ${target}.bak # delete SNC tables sed '/<!-- startSNCTable/,/<!-- endSNCTable/ {; /^.[^!][^-][^-]/ d; /^$/ d ;}' <${target} >${target}.1.html # insert replacement tables sed '/<!-- startSNCTableMethodsUsage -->/ r SNCmethodsUsageTable.html' <${target}.1.html >${target}.2.html sed '/<!-- startSNCTableMethodsModel -->/ r SNCmethodsModelTable.html' <${target}.2.html >${target}.3.html sed '/<!-- startSNCTableMethodNames -->/ r SNCmethodNamesTable.html' <${target}.3.html >$target #cp ${target}.1.html ${target} rm ${target}.?.html # delete EC tables sed '/<!-- startECTable/,/<!-- endECTable/ {; /^.[^!][^-][^-]/ d; /^$/ d ;}' <${target} >${target}.1.html # insert replacement tables sed '/<!-- startECTableMethodsUsage -->/ r ECmethodsUsageTable.html' <${target}.1.html >${target}.2.html sed '/<!-- startECTableMethodsModel -->/ r ECmethodsModelTable.html' <${target}.2.html >${target}.3.html sed '/<!-- startECTableMethodNames -->/ r ECmethodNamesTable.html' <${target}.3.html >$target #cp ${target}.1.html ${target} rm ${target}.?.html # delete SPIC tables sed '/<!-- startSPICTable/,/<!-- endSPICTable/ {; /^.[^!][^-][^-]/ d; /^$/ d ;}' <${target} >${target}.1.html # insert replacement tables sed '/<!-- startSPICTableMethodsUsage -->/ r SPICmethodsUsageTable.html' <${target}.1.html >${target}.2.html sed '/<!-- startSPICTableMethodsModel -->/ r SPICmethodsModelTable.html' <${target}.2.html >${target}.3.html sed '/<!-- startSPICTableMethodNames -->/ r SPICmethodNamesTable.html' <${target}.3.html >$target #cp ${target}.1.html ${target} rm ${target}.?.html
#!/bin/bash if [ "x$1" = "x" ]; then target="index.html" else target=$1 fi # back-up HTML cp ${target} ${target}.bak # update time stamp cmd='/<!-- startLastUpdated/,/<!-- endLastUpdated/ {; s/^Last Updated: .*/Last Updated: '"`date`/; }" sed "$cmd" <${target} >${target}.tmp cp ${target}.tmp ${target} rm ${target}.tmp
#!/bin/bash if [ "x$1" = "x" ]; then target="index.html" else target=$1 fi cp ${target} ${target}.old cd dsl echo "Disassembling ACPI Machine Language files..." find ../aml/ -maxdepth 1 -name '*.aml' -exec iasl -d {} \; &>/dev/null # Analyse the SNC device echo "Generating HTML files containing SNC device methods summary..." find . -maxdepth 1 -name '*.dsl' -exec awk -v html=1 -v device=SNC -f ../findDevice.awk {} \; echo "Putting all SNC HTML into one file" cat *.SNC.xhtml >SNC.xhtml echo "Generating SNC Methods Models table..." awk -v outfile=../SNCmethodsModelTable.html -f ../sortHTML.awk SNC.xhtml echo "Creating raw files containing SNC device methods summary..." find . -maxdepth 1 -name '*.dsl' -exec awk -v device=SNC -f ../findDevice.awk {} \; echo "Concatenating raw SNC into one file" cat *.SNC >SNC.unsorted echo "Sorting the SNC method summaries" sort SNC.unsorted >SNC.sorted rm SNC.unsorted echo "Creating a list and count of unique SNC method-names" uniq -c SNC.sorted >SNC.uniq rm SNC.sorted echo "Generating SNC Methods Usage table..." find . -maxdepth 1 -name '*.SNC' -exec awk -v outfile=../SNCmethodsUsageTable.html -v device=SNC -f ../methodsUsage.awk SNC.uniq {} \+ echo "Generating SNC Method Names table..." awk -v outfile=../SNCmethodNamesTable.html -v device=SNC -v csv=../SNCusage.csv -f ../methodNames.awk SNC.uniq rm *.SNC # Now analyse the EC device echo "Generating HTML files containing EC device methods summary..." find . -maxdepth 1 -name '*.dsl' -exec awk -v html=1 -v device=EC -f ../findDevice.awk {} \; echo "Putting all EC HTML into one file" cat *.EC.xhtml >EC.xhtml echo "Generating EC Methods Models table..." awk -v outfile=../ECmethodsModelTable.html -f ../sortHTML.awk EC.xhtml echo "Creating raw files containing EC device methods summary..." find . -maxdepth 1 -name '*.dsl' -exec awk -v device=EC -f ../findDevice.awk {} \; echo "Concatenating raw EC into one file" cat *.EC >EC.unsorted echo "Sorting the EC method summaries" sort EC.unsorted >EC.sorted rm EC.unsorted echo "Creating a list and count of unique EC method-names" uniq -c EC.sorted >EC.uniq rm EC.sorted echo "Generating EC Methods Usage table..." find . -maxdepth 1 -name '*.EC' -exec awk -v outfile=../ECmethodsUsageTable.html -v device=EC -f ../methodsUsage.awk EC.uniq {} \+ echo "Generating EC Method Names table..." awk -v outfile=../ECmethodNamesTable.html -v device=EC -v csv=../ECusage.csv -f ../methodNames.awk EC.uniq rm *.EC # Now analyse the SPIC device echo "Generating HTML files containing SPIC device methods summary..." find . -maxdepth 1 -name '*.dsl' -exec awk -v html=1 -v device=SPIC -f ../findDevice.awk {} \; echo "Putting all SPIC HTML into one file" cat *.SPIC.xhtml >SPIC.xhtml echo "Generating SPIC Methods Models table..." awk -v outfile=../SPICmethodsModelTable.html -f ../sortHTML.awk SPIC.xhtml echo "Creating raw files containing SPIC device methods summary..." find . -maxdepth 1 -name '*.dsl' -exec awk -v device=SPIC -f ../findDevice.awk {} \; echo "Concatenating raw SPIC into one file" cat *.SPIC >SPIC.unsorted echo "Sorting the SPIC method summaries" sort SPIC.unsorted >SPIC.sorted rm SPIC.unsorted echo "Creating a list and count of unique SPIC method-names" uniq -c SPIC.sorted >SPIC.uniq rm SPIC.sorted echo "Generating SPIC Methods Usage table..." find . -maxdepth 1 -name '*.SPIC' -exec awk -v outfile=../SPICmethodsUsageTable.html -v device=SPIC -f ../methodsUsage.awk SPIC.uniq {} \+ echo "Generating SPIC Method Names table..." awk -v outfile=../SPICmethodNamesTable.html -v device=SPIC -v csv=../SPICusage.csv -f ../methodNames.awk SPIC.uniq rm *.SPIC cd .. echo "Updating ${target}..." ./updateTables.sh ${target} echo "Updating time stamp" ./updateTime.sh ${target} echo "Creating archive containing DSL files..." tar -czf Vaio-DSDT-dsl.tar.gz dsl/*.dsl echo "Cleaning Up temporary files..." rm dsl/*.uniq rm dsl/*.xhtml echo "Done"
© 2007 TJ, licensed under Creative-Commons Non-Commerical With-Attribution License