When writing software in POWER C, there are some peculiarities that must be accounted for. POWER C is a programming language from 1986, meaning that its keywords and its syntax are pre C89 / ANSI C, which had been defined as a standard in 1989. In this article I am documenting the things I noticed when writing software in POWER C. This is by far no complete list.
Commenting a single line
| Not working | Working |
| // This is a comment | /* This is a comment */ |
Initializing an array right after declaring it
| Not working | Working |
| int arr[] = { 1,2,3 }; | int arr[]; arr[0] = 1; arr[1] = 2; arr[3] = 3; |
Counting the elements in a fixed-size array
| Not working | Working |
| int arr[5] = {10, 20, 30, 40}; size_t n = sizeof(arr) / sizeof(arr[0]); printf(„The array has %zu elements.\n“, n); | int arr[5]; arr[0] = 10; arr[1]=20; arr[2]=30; arr[3]=40; arr[4] = ‚\0‘; int n = 0; while(arr[n] != ‚\0‘) n++; printf(„The array has %d elements.\n“, n); |
| int arr[5] = {10, 20, 30, 40}; int n = 0; while(arr[n] != ‚\0‘) n++; printf(„The array has %zu elements.\n“, n); | See above |
Declaring a variable inside the for function
| Not working | Working |
| for (int i=0; i<10;i++) { } | int i; for (i=0; i<10;i++) { } |
Declaring a variable as an argument to a function
| Not working | Working |
| int isPrime (unsigned int n) { } | unsigned int n; int isPrime (n) { } |
| has_space(s) char s[]; { | has_space(s) char *s; { |
Type casting directly after the declaration
| Not working | Working |
| char byte = (char) integer; | char byte; byte = (char) integer; |
Explicitly declaring that a function returns no value
| Not working | Working |
| void main (int) | main (int) /* or */ int main(int) /* for a function that returns an integer and takes an integer */ |
| main() { int i; } | main() { int i; return; } |
Variables of type const
| Not working | Working |
| const int i = 10; const char *str; | int i = 10; /* or: #define INT 10 */ char *str; |
Variables of type unsigned long
| Not working | Working |
| unsigned long number; | long number; /* No format specifier %ul */ number = abs(number); |
Using free() on a NULL initialized array
| Not working | Working |
| int *arr = NULL; free (arr); /* This will crash the computer */ | int *arr; arr=(int *)malloc(2*sizeof(int)); /* optional */ free (arr); |
Declaring and initializing an array (a string) within a function
| Not working | Working |
| int main(void) { char str[] = „Hello World!“; /* illegal assignment */ printf („%s\n“, str); return 0; } | char str[] = „Hello World!“; int main(void) { printf („%s\n“, str); return 0; } /* arrays must be declared as global */ |
| char str[]; int main(void) { str = „Klingel“; /* illegal assignment */ | char str[] = „Klingel“; int main(void) { printf(„Lastname: %s\n“, str); |
Initializing a variable with a literal that ends with a data type suffix
| Not working | Working |
| floatValue = 3.14f; longValue = 82787293729372L; unsignedIntValue = 10u; | floatValue = 3.14f; intValue = 12345; unsignedIntValue = 10; |
Format conversion
| Not working | Working |
| printf („float : %*f\n“, 3, 1.2345); printf („%0*d“, 5, 3); printf („int: %+d\n“, i); scanf („Number: %ld“, &n); printf(„integer: %i\n“, i); /* POWER C does not support the i, e, and p conversion types and does not understand the tab \t */ | printf (float: %.3f\n“, 1.2345); /* POWER C does not use flags like ‚0‘ */ /* POWER C does not use flags like ‚+‘ */ scanf („Number: %d“, &n); printf(„integer: %d\n“, i); printf („pointer int: %d\n“, p); |
Conversation from string to integer
| Not working | Working |
| #include <stdlib.h> const char *str = „12345“; char *endptr; value = strtol(str, &endptr, 10); | /* No need to include stdlib.h! */ char str[] = „1234“; int main() { int num; num = atoi(str); |
Automatic type casting
| Not working | Working |
| int main() { int i; float f = 2.5; i = f; printf(„f: %f\ti: %f\n“, f, i); return(0); } /* In POWER C, i stays an integer and is not casted to a floating point */ | int main() { int i = 2; float f; f = i; printf(„f: %f i: %d\n“, f, i); return(0); } /* In POWER C, only down casting works */ |
stdlib.h
| Not working | Working |
| #include <stdlib.h> | /* POWER C has separate object files for i.e. free() and malloc(), which the linker will find when referenced */ |
Reading memory address
| Not working | Working |
| volatile unsigned char *ptr = (volatile unsigned char *)0x800; unsigned char value = *ptr; printf („%c“, value); | unsigned int adr = 0x800; /* POWER C does not support the data type (volatile) unsigned char */ unsigned int *ptr = adr; printf („%u\n“, *(ptr)); /* dereference ptr */ |
Digraphs and trigraphs
| Not working | Working |
| %:include <stdio.h> int main(void) <% return(0); %> | Neither digraphs (two character replacements for characters like {, [, and #) nor trigraphs (three character replacements) are working in POWER C. Use intended characters instead |
Sys function
| Not working | Working |
| /* POWER C Instruction Manual */ /* from Spinnaker, page 46 */ char *s, x, y; s = „Jan Klingel“; while(*s++) sys(15, 0xffd2, s, &x, &y); /* Contrary to the manual, the sys com- */ /* mand does not take a bank number as */ /* the first argument! */ | #define CHROUT 0xffd2 char s[] = „Jan Klingel“; int main(void) { char x, y; unsigned int i; unsigned int len; len = sizeof(s)/sizeof(s[0]); for(i=0;i<len;i++) sys(CHROUT,&s[i],&x,&y); return(0); } |
Inverting binary numbers
| Not working | Working |
| t = ~t; /* The compiler will error out with „*** illegal use of ‚_'“, as the tidle ~ in the editor will be displayed to the compiler as an underscore _ */ | Have not found a solution yet |
Note that there is a typo on page 30 of the POWER C Instruction Manual from Spinnaker:
for ((c = getc(5)) != EOF)
putchar(c);
Replace the „for“ with a „while“ statement to fix this.
Also, note that calling free( ) on a type that is not a pointer will halt your program und you have to press RUN/STOP to exit. Setting the variable to NULL does not help.
A char with the left-most bit set to 1 is always a positive value in POWER C:
int main() {
char test = 255;
printf("Test: %d\n", test);
return(0);
}
Some CPU architectures (PDP-11, AMD x86 with GCC) would print -1 instead of 255 in above example. GCC would need the declaration „unsigned char test = 255“ to print the value 255.