Helpful Hints for C Programming - PowerPoint PPT Presentation

About This Presentation
Title:

Helpful Hints for C Programming

Description:

a partridge in a pear tree. On the second day of Christmas my true love gave to me ... and a partridge in a pear tree. Expertise. New to C or C for TPF? Get ... – PowerPoint PPT presentation

Number of Views:148
Avg rating:3.0/5.0
Slides: 74
Provided by: paulstu
Category:

less

Transcript and Presenter's Notes

Title: Helpful Hints for C Programming


1
Helpful Hints for C Programming
Paul Stuyvesant
2
CLARITY
3
CLARITY
4
Clarity
  • Use space/blank lines to make readable

memcpy(buffer3,ecbptr()-gtebw000,InputLen) if(
ptrInputChar)
memcpy( buffer3, ecbptr()-gtebw000,
InputLen) if( ptr InputChar )
5
Clarity
  • Indent your code

int CVZZ( void ) int LoopCnt 0
ret 0 char buffer20 0
if( levtest( D4 ) ) ret -1
6
Clarity
  • Just because its less source doesnt mean less
    object.

if( num 10 ) num // or
num if( num 10 )
7
include ltstdio.hgt main(t,_,a ) char a
return! 0ltt? tlt3? main(-79,-13,a
main(-87,1-_, main(-86, 0, a1 ) a)) 1,
tlt_? main( t1, _, a ) 3, main ( -94, -27t, a )
t 2 ?_ lt13 ? main ( 2, _1, "s d d\n"
) 916 tlt0?tlt-72? main( _, t, "_at_n','/w/wc
dnr/,r/de,/,/w,/wqn, /l,,/nn,
/n,/qn,/k,/'r 'd'3,wK
w'K' e'dq'l q'd'K!/kq'reKKw'reKK
nl'/qn'))w'))nl'/n'drw' i
)nl!/nn' rw'r ncnl'/l,'Krw'
iKnl'/wqn'wk nw' iwkKKnl!/w'lw' i
nl'/q'ldr'nlwb!/de'c
nl'-rw'/, 'nc,',nw'/kd'e'rdq
w! nr'/ ') rl'n' ') '(!!/") tlt-50?
_a ? putchar(31a) main(-65,_,a1)
main((a '/') t, _, a 1 ) 0ltt? main ( 2,
2 , "s") a'/' main(0, main(-61,a, "!ekdc
i_at_bK'(q)-wnr3l, \nuwloca-Om
.vpbks,fxntdCeghiry") ,a1)
8
On the first day of Christmas my true love gave
to me a partridge in a pear tree. On the second
day of Christmas my true love gave to me two
turtle doves and a partridge in a pear tree. On
the third day of Christmas my true love gave to
me three french hens, two turtle doves and a
partridge in a pear tree. On the fourth day of
Christmas my true love gave to me four calling
birds, three french hens, two turtle doves and a
partridge in a pear tree. On the fifth day of
Christmas my true love gave to me five gold
rings four calling birds, three french hens, two
turtle doves and a partridge in a pear tree.
9
Expertise
  • New to C or C for TPF?
  • Get other people involved
  • Mix TPFers with C programmers
  • Peer review a must for new C programmers
  • There is still a learning curve
  • Online newsgroups are a fantastic resource

10
C or C
  • Up to you!
  • Spend lots of time arguing about it
  • Compile C programs as C
  • Better type checking
  • Can use C features such as function overloading
  • Saves a lot of time later on if you move to full
    C development.

11
C or C
  • Header files should always have conditional
    compilation in them
  • Will save you a lot of hassle later

ifdef __cplusplus extern "C" endif
int function1( char , int ) void
function2( char, int ) ifdef __cplusplus
endif
12
C C DLL
  • Very useful for common routines
  • Easy for the programmer to create
  • However
  • Make sure programmers know about them
  • Make them easy to use
  • Just because you can doesnt mean you should!

13
ECB
  • Still hanging on in there
  • Defined in ceb0eb.h
  • If you want to understand unions this is the
    place to look
  • Not necessarily addressed by R9
  • Accessed as required by ecbptr() macro

14
ecbptr()-gt
define ecbptr() ((struct eb0eb
)0x00000514ul)
00042
ecbptr()-gtebw000 'Z' 0003B2 5810 0514
00042 L r1,1300 0003B6 92E9 1008
00042 MVI ()eb0eb.eb(r1,8),233
15
ecbptr()-gt
  • 5810 0514 L R1,1300
  • Load from Base Register 0, offset X514
  • Address 0 Prefixing Prefix Page
  • Each I/Stream has its own Prefix Page
  • 92E9 1008 MVI 8(R1),233
  • Use offset from R1 for ebw000

16
Useful Compiler Options
  • AGGR/NOAGGR
  • Map of structures in compilation
  • Shows offsets, similar to PRINT GEN
  • XREF/NOXREF
  • Shows information for each symbol
  • Displayed by source line/file/line number

17
Useful Compiler Options
  • ARCH( )
  • Specify machine architecture
  • Generates different object code depending on
    setting
  • ROSTRINGS
  • Place R/O strings in program instead of static.
  • Similar to DC statement

18
Useful Compiler Options
  • OPTIMISATION
  • Code is optimised by compiler
  • Can give unusual looking results
  • Make sure you test optimised code
  • INLINE
  • Functions may be moved inline
  • Saves overhead of epilog/prolog

19
00008 int
a 0, 000068 4100 0000 00008
LA r0,0 00006C 5000 D098
00008 ST r0,a(,r13,152)
00009 b
2 000070 4100 0002 00009
LA r0,2 000074 5000 D09C 00009
ST r0,b(,r13,156)
00011 a 2 000078
5800 D098 00011 L
r0,a(,r13,152) 00007C A70A 0002 00011
AHI r0,H'2' 000080 5000 D098
00011 ST
r0,a(,r13,152) 00013
a b a 000084 5810 D09C
00013 L r1,b(,r13,156)
000088 1A01 00013
AR r0,r1 00008A 5000 D098 00013
ST r0,a(,r13,152)
00015 a 00008E A70A
0001 00015 AHI
r0,H'1' 000092 5000 D098 00015
ST r0,a(,r13,152)
00017 b 000096 5800 D09C
00017 L
r0,b(,r13,156) 00009A A70A 0001 00017
AHI r0,H'1' 00009E 5000 D09C
00017 ST
r0,b(,r13,156) 00019
return a b 0000A2 58F0 D098
00019 L r15,a(,r13,152)
0000A6 1AF0 00019
AR r15,r0 0000A8 47F0 305E 00019
B _at_1L3
20
00007
00008 int a
0, 00009
b 2 00010
00011 a
2 00012
00013 a b
a 00014
00015 a
00016
00017 b
00018
00019 return a b
000060 41F0 0008 00019
LA r15,8 00020
000064 00020
_at_1L3 DS 0H
21
00009
strcpy(buffer, name) 0000D8 4100 D0B4
00009 LA r0,buffer(,r13,180)
0000DC 5000 D0E8 00009 ST
r0,wtemp_1(,r13,232) 0000E0 41E0 D0B4
00009 LA r14,buffer(,r13,180)
0000E4 41F0 D0A8 00009 LA
r15,name(,r13,168) 0000E8 4110 0000
00009 LA r1,0 0000EC
00009 _at_1L6 DS 0H 0000EC 5840
308A 00009 L
r4,A(_at__at_TRT)(,r3,138) 0000F0 DDFF F000 4000
00009 TRT name(256,r15,0)_at__at_TRT,(r4,
0) 0000F6 4770 3062 00009
BNE _at_1L7 0000FA D2FF E000 F000 00009
MVC buffer(256,r14,0)name,(r15,0)
000100 41E0 E100 00009 LA
r14,buffer(,r14,256) 000104 41F0 F100
00009 LA r15,name(,r15,256)
000108 47F0 3042 00009 B
_at_1L6 00010C 00009 _at_1L7
DS 0H 00010C 1B1F 00009
SR r1,r15 00010E 4410 6000
00009 EX r1,MVC_INST(,r6,0)
000112 5800 D0E8 00009 L
r0,wtemp_1(,r13,232) 000116
00009 _at_1L1 DS 0H
22
00009
strcpy(buffer, name) 0000D4 4100 D0B4
00009 LA r0,buffer(,r13,180)
0000D8 5000 D0E8 00009 ST
r0,wtemp_1(,r13,232) 0000DC 4110 D0B4
00009 LA r1,buffer(,r13,180)
0000E0 4120 D0A8 00009 LA
r2,name(,r13,168) 0000E4 4100 0000
00009 LA r0,0 0000E8 B255 0012
00009 MVST r1,r2 0000EC
4710 303E 00009 BO
62(,r3) 0000F0 5800 D0E8 00009
L r0,wtemp_1(,r13,232)
23
typedef
  • Use and enforce company wide
  • It will be a pain when you start
  • In the long run it will make things easier
  • Use names that are logical and easy to remember
  • Place in company header file
  • Do NOT use assembler-ish names!

24
typedef - example
typedef unsigned char Uchar typedef
unsigned short int Uint16 typedef signed
short int Sint16 typedef unsigned long int
Uint32 typedef signed long int Sint32
typedef int Sint32 DO NOT!
typedef unsigned char BYTE typedef unsigned
short int HALFWORD
25
typedef
  • Worth being aware of standard typedefs

typedef char dft_alg typedef char
dft_are typedef unsigned int
dft_fad typedef char dft_fid
typedef struct sw00sr dft_fil typedef char
dft_hdr typedef struct id_list
dft_idl typedef struct sw01sr dft_kyl
26
Pointers
  • The power of C language
  • Use correct type of pointer
  • Calling a function to check a field in specific
    structure?
  • Pass in address of field not address of
    structure.
  • Function is not then tied to a specific structure.

27
int Validate_Whatever1 ( struct wa0aa )
int Validate_Whatever2 ( char ) void
CVZZ(void) int ret 0 struct
wa0aa AaaPtr ecbptr()-gtebccr1 //
Validate_Whatever is tied to wa0aa structure
ret Validate_Whatever1( AaaPtr )
// Validate_Whatever2 can be used for any char
pointer ret Validate_Whatever2(
(AaaPtr-gtwa0xxx) )
28
Pointers
struct xxx pXData calloc( 1, sizeof(struct
xxx) ) Later a change is made to structure
type struct yyy pXData calloc( 1,
sizeof(struct xxx) )
29
Pointers
struct xxx pXData calloc( 1, sizeof( pXData
) ) Later a change is made to structure
type struct yyy pXData calloc( 1, sizeof(
pXData ) )
30
Pointers
  • Pointer and array notation are interchangeable
  • Dont mix and match within same function
  • Causes confusion
  • Is just not good practice
  • Array notation can sometimes be clearer

31
void functionX( char pMi0acc ) char
option pMi0acc option
pMi0acc0 if( (pMi0acc1) A )
if( pMi0acc1 A )
32
Pointers
  • All pointer types can be dereferenced
  • Use this facility to move data around

struct wa0aa pWa0aa ecbptr()-gtebccr1,
pScrWa0aa NULL pScrWa0aa
calloc( 1, sizeof( pWa0aa)) memcpy(
pScrWa0aa, pWa0aa, sizeof( pWa0aa)) OR
pScrWa0aa pWa0aa
33
Converting DSects
  • Dsect are for Assembler Programs
  • Does exact equivalent help with C or C?
  • Try to identify separate structures and declare
    individually.
  • Place in C/C source file when developing
  • Move to header when completed
  • Use AGGR option in compile to view offsets
  • More later in TPFDF discussion

34
Functions
  • Too many parameters - consider parameter list
    structure.
  • Try to keep functions simple, easier said than
    done.
  • Avoid overuse of define to simplify function
    calls.

35
struct param_list char pImsg char
pOutput int Validate_Input( struct
param_list ) void CVZZ(void) struct
param_list parms 0 struct mi0mi
miptr ecbptr()-gtebccr0 int
ret 0 parms.pOutput calloc( 1,
10000 ) parms.pImsg miptr-gtmi0acc ret
Validate_Input( parms )
36
struct param_list char pImsg char
pOutput int CharCount int
Validate_Input( struct param_list ) void
CVZZ(void) struct param_list parms 0
struct mi0mi miptr
ecbptr()-gtebccr0 int ret
0 parms.CharCount miptr-gtmi0cct - 4
parms.pOutput calloc( 1, 10000 )
parms.pImsg miptr-gtmi0acc ret
Validate_Input( parms )
37
define functions
PCS_Link ( p_PCS_Ent, d_PCS_Buff,
p_PCS_Last_Ent,
p_PCS_Next_Ent_Item, st_PCS_Ent_Item ) define
PCS_Link(NEW, BUFFER, PREVIOUS, NEXTFIELD,
STRUCT) \ ( PCS_BuffGet(NEW,BUFFER
,sizeof(STRUCT)), \ PREVIOUS
NEW, \ PREVIOUS (STRUCT )
(NEW-gtNEXTFIELD) ) define PCS_BuffGet(NEW,BUFFE
R,SIZE) \ ( ( (NEW
XXBuffGet(BUFFER,SIZE)) ! NULL ) ? \
( TRUE ) \ ( snapc (SNAPC_RETURN,
0xB00B00, "NO MORE BUFFER", \
NULL, 'U', SNAPC_REGS, SNAPC_ECB, "PCS000"), \
exit (1), \ FALSE
))
38
Default Values
  • Most functions have default values
  • ptr dfopn( FNAME, FID, 0 )
  • What does the 0 in dfopn actually mean?
  • Take a look in ccdfeq.h
  • Contains values used by the various commands
  • These are usually the dft_opt parameter

39
Default Values
define DFOPN_ALG 0x00000001UL
define
DFOPN_FADDR 0x00000002UL
define DFOPN_ORD
0x00000004UL
define DFOPN_SPACE 0x00000008UL
define
DFOPN_TAPE 0x00000010UL
define DFOPN_AREA
0x00000020UL
define DFOPN_HOLD 0x01000000UL
define
DFOPN_NOHOLD 0x00000000UL
define DFOPN_DLI
0x00000000UL define DFOPN_DETAC
0x00008000UL
define DFOPN_NODET 0x00000000UL

40
Default Values
  • Understanding can make problem solving easier.
  • find_record( D6, NULL, PS, 0, UNHOLD)
  • Why does the above line compile OK but cause
    Control 8 at exit?

41
Default Values
  • find_record( D6, NULL, PS, 0, UNHOLD)

/ FIND/FILE constants / enum t_act
NOHOLD, UNHOLD, NOREL define HOLD UNHOLD

find_record( D6, NULL, PS, 0, HOLD)
42
TPFDF
  • Error Handling
  • Use DF_SERRC macro
  • Converting DSECT to Header
  • Separate structures for each LREC
  • Understand the typedefs and defines
  • Check the cdf header files

43
Error Handling
  • Use built in macros in CCDFERR.h
  • DF_SERRC can be particularly useful
  • Check if dump already taken by TPFDF such as
    DB0100 or DB0102
  • Do not repeat dump if already taken

44
pk40lrec dfred( PCSFile, 0 ) if( DF_OK(
PCSFile ) ) // Found Record process
else if( DF_NR( PCSFile ) ) // Not Found
process else serrc_op(
SERRC_RETURN, 0xC0FFEE,
"OH NO - NOT AGAIN", NULL)
45
pk40lrec dfred( PCSFile, 0 ) if( DF_OK(
PCSFile ) ) // Found Record process
else if( DF_NR( PCSFile ) ) // Not Found
process else if( !(DF_SERRC(
PCSFile ))) serrc_op( SERRC_RETURN,
0xC0FFEE, "OH NO -
NOT AGAIN", NULL)
46
DSect Conversion
  • Each Lrec type should be separate structure.
  • No need to build overall structure
  • Makes header much easier to read
  • Why pretend it is Assembler?

47
GR99RECCG1 DS 0CL1 1ST RECORD START
(1VARIABLE,ELSE SIZE) GR99SIZCG1 DS H
SIZE OF LOGICAL RECORD
GR99KEYCG1 DS X LOGICAL RECORD
IDENTIFIER

DATA DEFINITIONS


AIF ('GR99RR1' EQ '1').KEYEQ GO
IF NOT FIRST ISSUE GR99K40 EQU X'40'
LOGICAL RECORD KEY X'40'
GR99L40 EQU GR99E40CG1-GR99RECCG1
LENGTH OF RECORD KEY X'40' GR99K50 EQU
X'50' LOGICAL RECORD KEY X'50'
GR99L50 EQU GR99E50CG1-GR99RECCG1
LENGTH OF RECORD KEY X'50' GR99RR1 SETB 1
INDICATE 1ST TIME THROUGH
.KEYEQ ANOP
GENERATE DSECT NAME GR99ORGCG1
EQU START OF LOGICAL RECORD
DESCRIPTION

DESCRIPTION OF X'40' LOGICAL RECORD TYPE


GR99FIXCG1 DS CL8 NUMBER OF LAST
MESSAGE IN TABLE GR99FRXCG1 DS
CL8 NUMBER OF FIRST MESSAGE IN TABLE
GR99INDCG1 DS X INDICATOR
GR99NBXCG1 DS H
NUMBER OF MESSAGES IN TABLE
GR99E40CG1 EQU END OF LOGICAL
RECORD KEY '40' ORG
GR99ORGCG1

48

DESCRIPTION OF X'50'
LOGICAL RECORD TYPE

GR99LNOCG1 DS CL2
LANGUAGE CODE - NUMBER
GR99NAMCG1 DS CL10 LANGUAGE NAME
GR99LNNCG1 DS XL1
LANGUAGE CODE - BINARY
GR99LSTCG1 DS CL8 NUMBER OF LAST
MESSAGE GR99E50CG1 EQU
END OF LOGICAL RECORD KEY '50'
ORG GRXXORGCG1 DBRED
REFGR99PS,REGR2,ERRORERRORLAB,
KEY1(PKYGR99K40)IF SW00RTN,EQ,Z MVC
EBW000(LGR99LNO),GR99LNO
49
struct gr99rec dft_siz gr99siz
dft_key gr99key union lrecs struct
k40lrec char _gr99fix8
char _gr99frx8 char _gr99ind
unsigned short int _gr99nbx
Key40Lrec struct k50lrec char
_gr99lno2 char _gr99nam10
char _gr99lnn char
_gr99lst8 Key50Lrec
LrecStructs define gr99fix
LrecStructs.Key40Lrec._gr99fix define gr99frx
LrecStructs.Key40Lrec._gr99fix define gr99lnn
LrecStructs.Key50Lrec._gr99lnn
50
dft_fil pGr99fil NULL dft_kyl keys
0 struct gr99rec pLrec
NULL pGr99fil dfopn( GR99FNAME, GR99FID, 0
) SetUpKeys( pGr99fil, keys ) pLrec dfred(
pGr99fil, 0 ) if( DF_OK( pGr99fil ) )
ecbptr()-gtebw000 pLrec-gtgr99lnn // Key 50
lrec ecbptr()-gtebw000 pLrec-gtgr99ind //
Key 40 lrec
51
struct k40lrec dft_siz gr99siz
dft_key gr99key char gr99fix8
char gr99frx8 char gr99ind
unsigned short int gr99nbx struct
k50lrec dft_siz gr99siz dft_key
gr99key char gr99lno2 char
gr99nam10 char gr99lnn char
gr99lst8
52
dft_fil pGr99fil NULL dft_kyl keys
0 struct k40lrec pLrec
NULL pGr99fil dfopn( GR99FNAME, GR99FID, 0
) SetUpKeys( pGr99fil, keys ) pLrec dfred(
pGr99fil, 0 ) if( DF_OK( pGr99fil ) )
ecbptr()-gtebw000 pLrec-gtgr99lnn // COMPILER
ERROR ecbptr()-gtebw000 pLrec-gtgr99ind //
Key 40 lrec
53
printf/sprintf
  • Understand the different modifiers and flags
    available
  • Use a PC compiler for quick what if scenarios
  • The modifier is particularly useful for
    variable length fields

54
printf/sprintf
char name "STUYVESANT" int count
100 printf("s\n", name )
STUYVESANT printf("5s\n", name )
STUYVESANT printf(".5s\n", name )
STUYV printf("d\n", count )
100 printf("5d\n", count )
100 printf(".5d\n", count ) 00100
55
printf/sprintf
int count 171 int negone
-1 printf("x\n", count )
ab printf("X\n", count )
AB printf("X\n", count )
0XAB printf(".4x\n", count )
0x00ab printf("u\n", negone )
4294967295 printf("d\n", negone ) -1
56
modifier
  • Length is not specified in string itself
  • Replaced by integer value in argument
  • Very useful for runtime replacement
  • Can be used in printf/sprintf
  • Has a totally different meaning in scanf

57
char name UNION", fname1 CITY",
fname2 BLUES int len
strlen(name) printf("s s\n", name, fname1
) printf("s s\n", len, " ", fname2 ) UNION
CITY BLUES
printf("s s\n", len, " ", fname2 )
printf("5s s\n", len, " ", fname2 )
58
char name "WALES", fname1
"CHARLES", fname2 "CAMILLA",
fname3 "HARRY", fname4
"WILLIAM" int len strlen(name) printf(
"s s\n", name, fname1 ) printf("s s\n",
len, " ", fname2 ) printf("s s\n", len, " ",
fname3 ) printf("s s\n", len, " ", fname4
) RESULT WALES CHARLES CAMILLA
HARRY WILLIAM
59
char name STEVENSON", fname1
"CHARLES", fname2 "CAMILLA",
fname3 "HARRY", fname4
"WILLIAM" int len strlen(name) printf(
"s s\ns s\ns s\ns s\n",
name, fname1,
len, " ", fname2,
len, " ", fname3, len,
" ", fname4 ) RESULT STEVENSON CHARLES
CAMILLA HARRY WILLIAM
60
sprintf
  • Parameters similar to printf
  • Used to build output into a buffer
  • Returns integer value
  • Count of number of bytes added to the buffer.
  • Make sure buffer is big enough!
  • Can pass buffer off to FMSG/WTOPC
  • Try to avoid multiple calls to sprintf

61
pk40lrec dfred( PCSFile, 0 ) while( DF_OK(
PCSFile ) ) ind sprintf( buffer ind,
"d ", pk40lrec-gtpp40cnt ) ind sprintf(
buffer ind, ".8s ", pk40lrec-gtpp40fld )
ind sprintf( buffer ind, "2X\n",
pk40lrec-gtpp40ind ) pk40lrec dfred(
PCSFile, 0 )
pk40lrec dfred( PCSFile, 0 ) while( DF_OK(
PCSFile ) ) ind sprintf( buffer ind,
"d .8s 2X\n",
pk40lrec-gtpp40cnt,
pk40lrec-gtpp40fld,
pk40lrec-gtpp40ind
) pk40lrec dfred( PCSFile, 0 )
62
pragma map
  • Replaces entry point function with supposedly
    real world name.
  • Adds confusion
  • Removes clarity
  • When I see it in a program it makes me feel like
    this

63
(No Transcript)
64
pragma map
  • Its 2AM and your friendly coverage analyst is
    woken up by a dump on system.
  • Leaps into action

65
pragma map
  • Post processes dump to examine.
  • Looking through stacks in dump finds call to
    Go_Print( ptr ).
  • Searches through component for Go_Print function
    - no luck

66
pragma map
  • Pulls up Build Script for failing program
  • Finds 8 components making up the DLM.
  • Searches through each for Go_Print function.
  • No luck.
  • Thinks!
  • Perhaps it is a DLL function call.
  • Sadly no - after 15 minutes searching imports

67
pragma map
  • At top of program finds include ltproject.hgt
  • Inside finds 25 include statements
  • Starts searching each one.
  • Of course each nested include has nested includes
  • And some are conditional
  • Eventually - 2 hours later our hero finds ...

68
pragma map
  • pragma map (Go_Print, ABCD )
  • Which means the line
  • Go_Print( ptr ) // Is really
  • ABCD( ptr )

69
pragma map
  • Having the entry point to a DLM/Assembler program
    clearly identifiable is a plus point.
  • Having program calls easily identifiable from
    function calls is a plus point.
  • ABCD is just as portable as GoPrint
  • Do standard C programmers feel a need to get rid
    of main() function?

70
Dump Analysis
  • Easier in C/C than Assembler
  • When you know the tricks
  • Understand the DLM/DLL Layout
  • File Map in Link Output or Link Map in dump
  • More information available to help resolve
  • Function Stacks
  • Static Stacks

71
Dump Analysis
  • Know your Register Conventions
  • Stack and Static Pointer
  • Parameter Lists C vs C
  • Understand the Pseudo Assembler Listing
  • What is MXTEMP_2?
  • How are DLL functions accessed?

72
THE END
  • Thanks for staying awake
  • Enjoy the rest of the conference
  • A copy of presentation is available at
  • www.pcs-training.co.uk/downloads.htm
  • Any questions drop me a line at
  • paul_at_pcs-training.co.uk

73
(No Transcript)
Write a Comment
User Comments (0)
About PowerShow.com