How to format flags in c? - c

Assume that there are flag definitions such as:
SHF_WRITE 0x1
SHF_ALLOC 0x2
SHF_EXECINSTR 0x4
SHF_MASKPROC 0xf0000000
Given a flag, I need to output SHF_WRITE|SHF_ALLOC if the bits 0x1 and 0x2 is on.
How to do the trick in C?

#define V(n) { n, #n }
struct Code {
int value;
char *name;
} decode[] = {
V(SHF_WRITE),
V(SHF_ALLOC),
{ 0, NULL },
};
void f(const int x) {
struct Code *c = decode;
int beenthere = 0;
for(; c->name; ++c)
if(x & c->value)
printf("%s%s", beenthere++ ? "|" : "", c->name);
if(beenthere)
printf("\n");
}

Just create a character buffer with enough space to hold all possible combinations of strings and add to it the appropriate strings for each applicable bit set. (or you could ditch the buffer and write straight to stdout, your choice) Here's a naive implementation of how you could do such a thing:
void print_flags(int flag)
{
#define BUFLEN (9+9+13+12+3+1)
/* for the text, pipes and null terminator*/
#define PAIRLEN 4
static struct { int value; const char *string; } pair[] =
{
{ SHF_WRITE, "SHF_WRITE" },
{ SHF_ALLOC, "SHF_ALLOC" },
{ SHF_EXECINSTR, "SHF_EXECINSTR" },
{ SHF_MASKPROC, "SHF_MASKPROC" },
};
char buf[BUFLEN]; /* declare the buffer */
char *write = buf; /* and a "write" pointer */
int i;
for (i = 0; i < PAIRLEN; i++)
{
if ((flag & pair[i].value) == pair[i].value) /* if flag is set... */
{
size_t written = write - buf;
write += _snprintf(write, BUFLEN-written, "%s%s",
written > 0 ? "|" : "",
pair[i].string); /* write to the buffer */
}
}
if (write != buf) /* if any of the flags were set... */
{
*write = '\0'; /* null terminate (just in case) */
printf("(%s)", buf); /* print out the buffer */
}
#undef PAIRLEN
#undef BUFLEN
}

PROBLEM:
"SHF_WRITE|SHF_ALLOC" says "bit 0x1 OR bit 0x2", not "bits 0x1 AND 02x".
Nevertheless, if you wanted to print "SOME MSG" if the bits 0x1 and 0x2 were both "on" in some value "flag", here's how:
if (flag & SHF_WRITE & SHF_ALLOC)
printf ("SOME MSG, flag= 0x%x\n", flag);
If you wanted to print the text represtation of ANY bits that were "on" in the value, you might do something like this:
char buf[80] = '\0';
if (flag & SHF_WRITE)
strcpy (buf, " SHF_WRITE");
if (flag & SHF_ALLOC)
strcpy (buf, " SHF_ALLOC");
...
printf ("SOME MSG, flag= %s\n", buf);
And finally, if you DON'T want to print if NO bit is set, just do this:
if (flag)
{
... do printing ...
}
else
{
... do nothing? ...
}

Related

copying string in c in a microcontroller

I have a string "Revision: BG96MAR02A07M1G" which is stored in char tempdata[512]
I'm trying to parse and copy only that part BG96MAR02A07M1G
this what I did, but I get garbage values in firmwareVersion
signed char updateBG96FirmwareVersion(int timeout)
{
char firmwareVersion[24];
char *ret = NULL;
if (GSMCommand("I", tempdata, timeout) != AT_OK)
return FEHLER;
ret = strstr(tempdata, "Revision:");
if (ret)
{
strncpy(firmwareVersion, tempdata+9, 24);
firmwareVersion[sizeof(firmwareVersion)] = '\0';
}
else
return FEHLER;
}
test
You can just do this:
#include <string.h>
#define FEHLER 123 // ?
#define SUCCESS 0
signed char updateBG96FirmwareVersion(int timeout)
{
char firmwareVersion[24];
char* ret = NULL;
#if 1
char tempdata[] = "Revision: BG96MAR02A07M1G"; // Test data for my test
#else
if (GSMCommand("I", tempdata, timeout) != AT_OK)
return FEHLER;
#endif
const char revision[] = "Revision: ";
ret = strstr(tempdata, revision);
if (ret)
{
strcpy(firmwareVersion, tempdata + strlen(revision));
return SUCCESS;
}
else
return FEHLER;
}
int main() // main function initializing here
{
updateBG96FirmwareVersion(0);
}
This assumes that the revision string BG96MAR02A07M1G is never longer than 24 characters. Otherways you probably should use strncpy and terminate the string with a 0 manually.

How can I dump memory from an arbitrary virtual address, ignoring SIGSEGV

I'm looking for a way to iterate over memory and print it (or do anything with it really), but if the virtual address hasn't been allocated I'll get a segfault. How can I attempt to read arbitrary addresses in my program and not crash?
This is primarily for debugging so safety/defined behaviour isn't a high priority. For example, I might want to dump the memory a pointer points to and some surrounding values to check for corruption.
Out of interest, is there any reason this cannot be made safe, e.g. side effects of reads?
The actual memory dump is simple, for example the following. This question is really about ignoring the segfault.
how to get hexdump of a structure data
https://gist.github.com/domnikl/af00cc154e3da1c5d965
EDIT:
I'm running ubuntu 18.04
Use sigaction to catch signals such as SIGBUS and SIGSEGV
Use siglongjmp to exit the handler safely
Set SA_NODEFER to be able to catch the signal again
Based on this answer: Catching Segmentation Violations and Getting on with Life
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <setjmp.h>
sigjmp_buf badAddressRead;
void badAddressReadHandler(int signo) {
siglongjmp(badAddressRead, signo);
}
void hexDump(const char *desc, void *addr, int len)
{
int i;
unsigned char buff[17];
unsigned char *pc = (unsigned char*)addr;
struct sigaction segvActionOld;
struct sigaction busActionOld;
struct sigaction readAction = {};
readAction.sa_handler = badAddressReadHandler;
sigemptyset(&readAction.sa_mask);
readAction.sa_flags = SA_NODEFER;
sigaction(SIGBUS, &readAction, &segvActionOld);
sigaction(SIGSEGV, &readAction, &busActionOld);
// Output description if given.
if (desc != NULL)
printf("%s:\n", desc);
printf("address = %p\n", addr);
// Process every byte in the data.
for (i = 0; i < len; i++) {
// Multiple of 16 means new line (with line offset).
if ((i % 16) == 0) {
// Just don't print ASCII for the zeroth line.
if (i != 0)
printf(" %s\n", buff);
// Output the offset.
printf(" %04x ", i);
}
// Attempt to read memory that may not be accessible
unsigned char byte;
int caughtSignal;
if ((caughtSignal = sigsetjmp(badAddressRead, 0)) == 0) {
// Now the hex code for the specific character.
byte = pc[i];
printf(" %02x", byte);
} else {
byte = 0;
if (caughtSignal == SIGSEGV) {
printf(" SV");
} else if (caughtSignal == SIGBUS) {
printf(" BS");
} else {
printf(" ??");
}
}
// And store a printable ASCII character for later.
if ((byte < 0x20) || (byte > 0x7e)) {
buff[i % 16] = '.';
} else {
buff[i % 16] = pc[i];
}
buff[(i % 16) + 1] = '\0';
}
// Pad out last line if not exactly 16 characters.
while ((i % 16) != 0) {
printf(" ");
i++;
}
// And print the final ASCII bit.
printf(" %s\n", buff);
sigaction(SIGBUS, &busActionOld, NULL);
sigaction(SIGSEGV, &segvActionOld, NULL);
}
int main(void) {
int test = 123;
hexDump("test", &test, 8000); // dump 'test' and a whole bunch more after it
return 0;
}
(hexdump code modified from https://gist.github.com/domnikl/af00cc154e3da1c5d965)

How do I return a pointer to location in a buffer? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm currently working on a project in C which I'm required to create a buffer program. For the most part my program is finished but I'm just missing one required function: a location function to return the distance between the head (beginning of array) to the desired location designated by short loc_offset.
Given what I already have, how do I return a pointer to an index or location from my short?
Here is my given and created code:
Main (plat_bt.c):
/* File name: platy_bt.c
* Purpose:This is the main program for Assignment #1, CST8152
* Version: 1.18.1
* Author: Svillen Ranev
* Date: 16 January 2018
*/
/* The #define _CRT_SECURE_NO_WARNINGS should be used in MS Visual Studio projects
* to suppress the warnings about using "unsafe" functions like fopen()
* and standard sting library functions defined in string.h.
* The define directive does not have any effect on other compiler projects (gcc, Borland).
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include "buffer.h"
/* constant definitions */
#define INIT_CAPACITY 200 /* initial buffer capacity */
#define INC_FACTOR 15 /* increment factor */
/*check for ANSI C compliancy */
#define ANSI_C 0
#if defined(__STDC__)
#undef ANSI_C
#define ANSI_C 1
#endif
/* Declaration of an error printing function with
* variable number of arguments
*/
void err_printf(char *fmt, ...);
/* Declaration of a buffer contents display function */
void display (Buffer *ptr_Buffer);
long get_filesize(char *fname);
int main(int argc, char **argv){
pBuffer ptr_Buffer; /* pointer to Buffer structure */
FILE *fi; /* input file handle */
int loadsize = 0; /*the size of the file loaded in the buffer */
int ansi_c = !ANSI_C; /* ANSI C compliancy flag */
/* Check if the compiler option is set to compile ANSI C */
/* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/
if(ansi_c){
err_printf("Date: %s Time: %s",__DATE__, __TIME__);
err_printf("ERROR: Compiler is not ANSI C compliant!\n");
exit(1);
}
/* missing file name or/and mode parameter */
if (argc <= 2){
err_printf("\nDate: %s Time: %s",__DATE__, __TIME__);
err_printf("\nRuntime error at line %d in file %s\n", __LINE__, __FILE__);
err_printf("%s\b\b\b\b%s%s",argv[0],": ","Missing parameters.");
err_printf("Usage: platybt source_file_name mode");
exit(1);
}
/* create a source code input buffer */
switch(*argv[2]){
case 'f': case 'a': case 'm': break;
default:
err_printf("%s%s%s",argv[0],": ","Wrong mode parameter.");
exit(1);
}
/*create the input buffer */
ptr_Buffer = b_allocate(INIT_CAPACITY,INC_FACTOR,*argv[2]);
if (ptr_Buffer == NULL){
err_printf("%s%s%s",argv[0],": ","Cannot allocate buffer.");
exit(1);
}
/* open the source file */
if ((fi = fopen(argv[1],"r")) == NULL){
err_printf("%s%s%s%s",argv[0],": ", "Cannot open file: ",argv[1]);
exit (1);
}
/* load a source file into the input buffer */
printf("Reading file %s ....Please wait\n",argv[1]);
loadsize = b_load (fi,ptr_Buffer);
if(loadsize == RT_FAIL1)
err_printf("%s%s%s",argv[0],": ","Error in loading buffer.");
/* close the source file */
fclose(fi);
/*find the size of the file */
if (loadsize == LOAD_FAIL){
printf("The input file %s %s\n", argv[1],"is not completely loaded.");
printf("Input file size: %ld\n", get_filesize(argv[1]));
}
/* display the contents of the input buffer */
display(ptr_Buffer);
/* compact the buffer
* add end-of-file character (EOF) to the buffer
* display again
*/
if(!b_compact(ptr_Buffer,EOF)){
err_printf("%s%s%s",argv[0],": ","Error in compacting buffer.");
}
display(ptr_Buffer);
/* free the dynamic memory used by the buffer */
b_free(ptr_Buffer);
/* make the buffer invalid
It is not necessary here because the function terminates anyway,
but will prevent run-time errors and crashes in future expansions
*/
ptr_Buffer = NULL;
/*return success */
return (0);
}
/* error printing function with variable number of arguments*/
void err_printf( char *fmt, ... ){
/*Initialize variable list */
va_list ap;
va_start(ap, fmt);
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
/* Move to new line */
if( strchr(fmt,'\n') == NULL )
fprintf(stderr,"\n");
}
void display (Buffer *ptr_Buffer){
printf("\nPrinting buffer parameters:\n\n");
printf("The capacity of the buffer is: %d\n",b_capacity(ptr_Buffer));
printf("The current size of the buffer is: %d\n",b_limit(ptr_Buffer));
printf("The operational mode of the buffer is: %d\n",b_mode(ptr_Buffer));
printf("The increment factor of the buffer is: %lu\n",b_incfactor(ptr_Buffer));
printf("The current mark of the buffer is: %d\n", b_mark(ptr_Buffer, b_limit(ptr_Buffer)));
/*printf("The reallocation flag is: %d\n",b_rflag(ptr_Buffer));*/
printf("\nPrinting buffer contents:\n\n");
b_rewind(ptr_Buffer);
b_print(ptr_Buffer);
}
long get_filesize(char *fname){
FILE *input;
long flength;
input = fopen(fname, "r");
if(input == NULL){
err_printf("%s%s","Cannot open file: ",fname);
return 0;
}
fseek(input, 0L, SEEK_END);
flength = ftell(input);
fclose(input);
return flength;
}
That main file has no errors or warnings, it was given to me to be used as my main.
Here is my edited source file (buffer.c):
/* File name: buffer.c
* Purpose: This is the main program for Assignment #01, CST8152
* Version: 1.0.3
* Author: Jack Loveday
* Date: 7 Febuary, 2018
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include "buffer.h"
/* b_allocate: Creates new buffer on heap
Tries to allocate memory for:
- one Buffer (calloc)
- one dynamic character buffer (char array) (malloc)
Sets buffer operational mode and inc factor
Copies given init_capacity into Buffer capacity val */
Buffer * b_allocate(short init_capacity, char inc_factor, char o_mode) {
Buffer *pBuffer;
if (init_capacity < 0 || (unsigned char)inc_factor < 0)
return NULL;
pBuffer = (Buffer *)calloc(1, sizeof(Buffer));
if (!pBuffer) {
free(pBuffer);
return NULL;
}
pBuffer->cb_head = (char *)malloc(init_capacity);
if (o_mode == 'f' || (unsigned char)inc_factor == 0) {
pBuffer->mode = 0;
pBuffer->inc_factor = 0;
}
else if (o_mode == 'a') {
pBuffer->mode = ADD_MODE;
pBuffer->inc_factor = (unsigned char)inc_factor;
}
else if (o_mode == 'm' && (unsigned char)inc_factor <= 100) {
pBuffer->mode = MULTI_MODE;
pBuffer->inc_factor = (unsigned char)inc_factor;
}
else {
free(pBuffer->cb_head);
free(pBuffer);
return NULL;
}
pBuffer->capacity = init_capacity;
return pBuffer;
}
/* b_addc: resets r_flag to 0 & tries to add symbol to char array pointed by pBD */
pBuffer b_addc(pBuffer const pBD, char symbol) {
char *tBuffer;
short aSpace = 0, newInc = 0, newCapacity = 0;
if (!pBD)
return NULL;
pBD->r_flag = 0;
if ((short)(pBD->addc_offset * sizeof(char)) < pBD->capacity) {
pBD->cb_head[pBD->addc_offset] = symbol;
pBD->addc_offset++;
}
else if ((short)(pBD->addc_offset * sizeof(char)) == pBD->capacity) {
if (pBD->mode == 0)
return NULL;
else if (pBD->mode == 1) {
newCapacity = pBD->capacity + (unsigned char)pBD->inc_factor * sizeof(char);
if (newCapacity <= 0)
return NULL;
pBD->capacity = newCapacity;
}
else if (pBD->mode == -1) {
if (pBD->capacity == SHRT_MAX)
return NULL;
else {
aSpace = SHRT_MAX - pBD->capacity;
newInc = (short)((aSpace * pBD->inc_factor) / 100);
if (!newInc)
newInc = NEW_ONE;
newCapacity = (short)((pBD->capacity + newInc));
if (newCapacity <= 0)
newCapacity = SHRT_MAX;
}
}
tBuffer = (char *)realloc(pBD->cb_head, newCapacity);
if (tBuffer != pBD->cb_head)
pBD->r_flag = SET_R_FLAG;
pBD->cb_head = tBuffer;
pBD->cb_head[pBD->addc_offset] = symbol;
pBD->addc_offset++;
pBD->capacity = newCapacity;
}
return pBD;
}
/* b_clear: retains memory space currently allocated to buffer, but
re-initializes all appropriate members of given Buffer */
int b_clear(Buffer * const pBD){
if (!pBD)
return RT_FAIL1;
pBD->capacity = 0;
pBD->addc_offset = 0;
pBD->getc_offset = 0;
pBD->eob = 0;
return 1;
}
/* b_free: de-allocates memory for char array & Buffer struct */
void b_free(Buffer * const pBD) {
if (pBD) {
free(pBD->cb_head);
free(pBD);
}
}
/* b_isfull: returns 1 if buffer is full, otherwise returns 0, if rt error return -1 */
int b_isfull(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
if ((short)(pBD->addc_offset * sizeof(char)) == pBD->capacity)
return 1;
else
return 0;
}
/* b_limit: returns current limit of buffer, return -1 on error */
short b_limit(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->addc_offset;
}
/* b_capacity: returns current capacity of buffer, return -1 on error */
short b_capacity(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->capacity;
}
/* b_mark: sets markc_offset to mark, must be between 0 and addc_offset, return -1 on error */
short b_mark(pBuffer const pBD, short mark) {
if (!pBD || mark < 0 || mark > pBD->addc_offset)
return RT_FAIL1;
pBD->markc_offset = mark;
return pBD->markc_offset;
}
/* b_mode: returns value of mode, or -1 on error */
int b_mode(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->mode;
}
/* b_infactor: returns non-negative value of inc_factor, return 0x100 (256) */
size_t b_incfactor(Buffer * const pBD) {
if (!pBD)
return NEW_FULL;
return (unsigned char)pBD->inc_factor;
}
/* b_load: returns value of mode */
int b_load(FILE * const fi, Buffer * const pBD) {
char c;
int cNum = 0;
if (!fi || !pBD)
return RT_FAIL1;
for (;;) {
c = (char)fgetc(fi);
if (feof(fi))
break;
if (!b_addc(pBD, c))
return LOAD_FAIL;
++cNum;
}
fclose(fi);
return cNum;
}
/* b_isempty: if addc_offset is 0 return 1, otherwise return 0, return -1 on error */
int b_isempty(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
if (!pBD->addc_offset)
return 1;
else
return 0;
}
/* b_eob: returns eob (end of buffer), returns -1 on error */
int b_eob(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->eob;
}
/* b_getc: checks logic, if not valid returns -2, if getc_offset and addc_offset
are equal, set eob to 1 and returns -1, otherwise set eob to 0 */
char b_getc(Buffer * const pBD) {
char returner;
if (!pBD || !pBD->cb_head)
return RT_FAIL2;
if (pBD->getc_offset == pBD->addc_offset) {
pBD->eob = 1;
return RT_FAIL1;
}
else {
pBD->eob = 0;
}
returner = *(pBD->cb_head + pBD->getc_offset);
pBD->getc_offset++;
return returner;
}
/* b_print: used for diagnostic purposes only, returns -1 on error */
int b_print(Buffer * const pBD) {
int numOfChars = 0;
char c;
if (!pBD->addc_offset) {
printf("The Buffer is empty.\n");
return numOfChars;
}
pBD->getc_offset = 0;
while (1) {
c = b_getc(pBD);
if (b_eob(pBD))
break;
printf("%c", c);
++numOfChars;
}
numOfChars = pBD->getc_offset;
pBD->getc_offset = 0;
printf("\n");
return numOfChars;
}
/* b_compact: shrinks buffer to new capacity, before returning to a pointer add symbol
to the end of buffer, must set r_flag appropriatley */
Buffer * b_compact(Buffer * const pBD, char symbol) {
char *tempBuffer;
short tempCap;
if (!pBD)
return NULL;
tempCap = (pBD->addc_offset + 1) * sizeof(char);
if (tempCap == SHRT_MAX)
return pBD;
tempBuffer = (char *)realloc(pBD->cb_head, (unsigned short)tempCap);
if (tempCap == 0)
return NULL;
if (tempBuffer != pBD->cb_head)
pBD->r_flag = SET_R_FLAG;
pBD->cb_head = tempBuffer;
pBD->capacity = tempCap;
return pBD;
}
/* b_rflag: returns r_flag, returns -1 on error */
char b_rflag(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->r_flag;
}
/* b_retract: decrements getc_offset by 1, returns -1 on error, otherwise returns getc_offset */
short b_retract(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->getc_offset--;
return pBD->getc_offset;
}
/* b_reset: sets getc_offset to current markc_offset, returns -1 on error and getc_offset otherwise */
short b_reset(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->getc_offset = pBD->markc_offset;
return pBD->getc_offset;
}
/* b_getcoffset: returns getc_offset, or returns -1 on error */
short b_getcoffset(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->getc_offset;
}
/* b_rewind: set getc_offset and markc_offset to 0, return -1 on error and 0 otherwise */
int b_rewind(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->addc_offset = 0;
pBD->markc_offset = 0;
return 0;
}
/* b_location: returns a pointer to location indicated by loc_offset, returns null on error */
char * b_location(Buffer * const pBD, short loc_offset) {
if (!pBD)
return NULL;
return *loc_offset;
}
And finally my buffer.h:
/*File Name: buffer.h
* Version: 1.18.1
* Author: S^R
* Date: 16 January 2018
* Preprocessor directives, type declarations and prototypes necessary for buffer implementation
* as required for CST8152-Assignment #1.
* The file is not completed.
* You must add your function declarations (prototypes).
* You must also add your constant definitions and macros,if any.
*/
#ifndef BUFFER_H_
#define BUFFER_H_
/*#pragma warning(1:4001) *//*to enforce C89 type comments - to make //comments an warning */
/* standard header files */
#include <stdio.h> /* standard input/output */
#include <malloc.h> /* for dynamic memory allocation*/
#include <limits.h> /* implementation-defined data type ranges and limits */
/* constant definitions */
/* You may add your own constant definitions here */
#define RT_FAIL1 -1 /* fail return value */
#define RT_FAIL2 -2 /* fail return value */
#define LOAD_FAIL -2 /* load fail error */
#define SET_R_FLAG 1 /* realloc flag set value */
#define ADD_MODE 1; /* named constant for additive mode */
#define MULTI_MODE -1; /* named constant for multiplicative mode */
#define NEW_ONE 1; /* generic named constant value of 1 */
#define NEW_FULL 256; /* generic named constant value of 256 */
/* user data type declarations */
typedef struct BufferDescriptor {
char *cb_head; /* pointer to the beginning of character array (character buffer) */
short capacity; /* current dynamic memory size (in bytes) allocated to character buffer */
short addc_offset; /* the offset (in chars) to the add-character location */
short getc_offset; /* the offset (in chars) to the get-character location */
short markc_offset; /* the offset (in chars) to the mark location */
char inc_factor; /* character array increment factor */
char r_flag; /* reallocation flag */
char mode; /* operational mode indicator*/
int eob; /* end-of-buffer flag */
} Buffer, *pBuffer;
/* function declarations */
/*
Place your function declarations here.
Do not include the function header comments here.
Place them in the buffer.c file
*/
Buffer * b_allocate(short init_capacity, char inc_factor, char o_mode);
pBuffer b_addc(pBuffer const pBD, char symbol);
int b_clear(Buffer * const pBD);
void b_free(Buffer * const pBD);
int b_isfull(Buffer * const pBD);
short b_limit(Buffer * const pBD);
short b_capacity(Buffer * const pBD);
short b_mark(pBuffer const pBD, short mark);
int b_mode(Buffer * const pBD);
size_t b_incfactor(Buffer * const pBD);
int b_load(FILE * const fi, Buffer * const pBD);
int b_isempty(Buffer * const pBD);
int b_eob(Buffer * const pBD);
char b_getc(Buffer * const pBD);
int b_print(Buffer * const pBD);
Buffer * b_compact(Buffer * const pBD, char symbol);
char b_rflag(Buffer * const pBD);
short b_retract(Buffer * const pBD);
short b_reset(Buffer * const pBD);
short b_getcoffset(Buffer * const pBD);
int b_rewind(Buffer * const pBD);
char * b_location(Buffer * const pBD, short loc_offset);
#endif
So again, I need to find the location of loc_offset in my b_location function and return it as a pointer. Thanks in advance!
char * b_location(Buffer * const pBD, short loc_offset) {
if (!pBD)
return NULL;
/* Make sure loc_offset doesn't go beyond the length of the array */
if( ! in_bounds )
return NULL;
return &(pBD->cb_head[loc_offset]);
}

Converting hexadecimal to ASCII in c

I'm working on an Android rom for a mobile phone and I want to make the kernel load the wifi MAC address from the device's NV partition. My code looks like this:
#include <linux/kernel.h>
#include <linux/random.h>
#include <linux/syscalls.h>
#define ETHER_ADDR_LEN 6
#define FILE_WIFI_MACADDR "/dev/block/mmcblk0p7"
static int bcm_wifi_get_mac_addr(unsigned char *buf)
{
int ret = 0;
mm_segment_t oldfs;
int i;
int fp;
int macbyte;
int readlen = 0;
uint rand_mac;
static unsigned char mymac[ETHER_ADDR_LEN] = {0,};
const unsigned char nullmac[ETHER_ADDR_LEN] = {0,};
const unsigned char bcastmac[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
if (buf == NULL)
return -EAGAIN;
memset(buf, 0x00, ETHER_ADDR_LEN);
oldfs = get_fs();
set_fs(get_ds());
fp = sys_open(FILE_WIFI_MACADDR, O_RDONLY, 0);
if (fp < 0) {
pr_err("%s: Failed to read error %d for %s\n",
__FUNCTION__, fp, FILE_WIFI_MACADDR);
goto random_mac;
}
for (i = 0; i<12; i++) {
macbyte=0;
sys_lseek( fp,i+7680,SEEK_SET);
readlen = sys_read(fp,&macbyte,1);
if (i)
sprintf(macaddr,"%s%c",macaddr,macbyte);
else
sprintf(macaddr,"%c",macbyte);
}
if (readlen > 0) {
unsigned char* macbin;
macbin = (unsigned char*)macaddr;
pr_info("%s: READ MAC ADDRESS %02X:%02X:%02X:%02X:%02X:%02X\n",
__FUNCTION__,
macbin[0], macbin[1], macbin[2],
macbin[3], macbin[4], macbin[5]);
if (memcmp(macbin, nullmac, ETHER_ADDR_LEN) == 0 ||
memcmp(macbin, bcastmac, ETHER_ADDR_LEN) == 0) {
sys_close(fp);
goto random_mac;
}
memcpy(buf, macbin, ETHER_ADDR_LEN);
} else {
sys_close(fp);
goto random_mac;
}
sys_close(fp);
return ret;
random_mac:
set_fs(oldfs);
pr_debug("%s: %p\n", __func__, buf);
if (memcmp( mymac, nullmac, ETHER_ADDR_LEN) != 0) {
/* Mac displayed from UI is never updated..
So, mac obtained on initial time is used */
memcpy(buf, mymac, ETHER_ADDR_LEN);
return 0;
}
srandom32((uint)jiffies);
rand_mac = random32();
buf[0] = 0x00;
buf[1] = 0x90;
buf[2] = 0x4c;
buf[3] = (unsigned char)rand_mac;
buf[4] = (unsigned char)(rand_mac >> 8);
buf[5] = (unsigned char)(rand_mac >> 16);
memcpy(mymac, buf, 6);
pr_info("[%s] Exiting. MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
__FUNCTION__,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5] );
return 0;
}
The idea is to load the nv parition, located at /dev/block/mmcblk0p7, then read the mac address, which is located at offset 7680 on the nv. The problem is that the MAC address is written in hex, so I'm trying to print it to an ASCII string using sprintf().
for (i = 0; i<12; i++) {
macbyte=0;
sys_lseek( fp,i+7680,SEEK_SET);
readlen = sys_read(fp,&macbyte,1);
if (i)
sprintf(macaddr,"%s%c",macaddr,macbyte);
else
sprintf(macaddr,"%c",macbyte);
}
In the nv the MAC looks something like this: 34 30 42 30 46 41 36 35 39 33 34 39, which in ASCII is 40B0FA659349. But instead the resulting MAC is 34:30:42:30:46:41, which tells me that the hex values are not getting converted at all.
What would be the proper way to export the hex values into an ASCII string? I'm new to programming and i was hoping someone could give me some tips.
Thanks in advance.
In your loop you are reading single bytes and converting them to hex strings, while what you actually need to do is read the hex string and convert it byte values. Unless you actually want a hex string, in which case no conversion is necessary.
You have 12 hex characters representing 6 bytes so:
#define MAC_LEN 6
uint8_t macbytes[MAC_LEN] ;
for( i = 0; i < MAC_LEN; i++ )
{
char hex_str[3] ;
unsigned byte_val ;
sys_lseek( fp, (i*2) + 7680, SEEK_SET ) ;
readlen = sys_read( fp, hex_str, 2 ) ;
sscanf( hex_str, "%2X", &byte_val ) ;
macbytes[i] = (uint8_t)byte_val ) ;
}
The data in NV is already ASCII coded hexadecimal; for example 0x34 is the ASCII code for the hex digit '4', and 0x30 that for '0', together the ASCII character pair "40" represent the single 8 bit integer value 0x40. So the conversion you need is ASCII to byte array, not "hex to ASCII" (which makes no semantic sense).
I think this is OP's stubbing block: forming a string version of the MAC address.
I'll make this wiki for anyone to modify, borrow or steal.
sys_lseek( fp,i+7680,SEEK_SET);
char macaddr[100];
char *p = macaddr;
const char *sep = "";
for (i = 0; i < 12; i++) {
unsigned char macbyte;
int readlen = sys_read(fp, &macbyte, 1);
if (readlen != 1) Handle_Error();
p += sprintf(p, "%s%02X", sep, macbyte);
sep = ":";
}
puts(macaddr);

How to print an integer in Nios 2?

I've written code than handles interrupts and I added a function that will do something "useful" (calculating the next prime) and that should handle interrupts. The interrupts are working but not printing the calculated primes from within the while loop, while it is printing the time if I don't try to print the prime.
I think that putchar can't be used since a) It's for characters and I want to print an int and b) putchar uses interrupts so I must do it some other way.
When I tried with printf("%d",next) it didn't work either, why? How should I do to print the next prime from the main loop?
The program is
#include <stddef.h>
#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_alarm.h"
#include "alt_types.h"
#include "alt_irq.h"
extern int initfix_int(void);
extern void puttime(int* timeloc);
extern void puthex(int time);
extern void tick(int* timeloc);
extern void delay(int millisec);
extern int hexasc(int invalue);
#define TRUE 1
#define KEYS4 ( (unsigned int *) 0x840 )
#define TIMER1 ( (unsigned int *) 0x920 )
#define PERIOD (49999)
#define NULL_POINTER ( (void *) 0)
#define NULL ( (void *) 0)
#define PRIME_FALSE 0 /* Constant to help readability. */
#define PRIME_TRUE 1 /* Constant to help readability. */
volatile int timeloc = 0x5957;
volatile int RUN = 1;
volatile int * const de2_pio_keys4_base = (volatile int *) 0x840;
volatile int * const de2_pio_keys4_intmask = (volatile int *) 0x848;
volatile int * const de2_pio_keys4_edgecap = (volatile int *) 0x84c;
volatile int * de2_pio_hex_low28 = (volatile int *) 0x9f0;
const int de2_pio_keys4_intindex = 2;
const int de2_pio_keys4_irqbit = 1 << 2;
/* The alt_alarm must persist for the duration of the alarm. */
static alt_alarm alarm;
/*
* The callback function.
*/
alt_u32 my_alarm_callback(void* context) {
/* This function is called once per second */
if (RUN == 1) {
tick(&timeloc);
puttime(&timeloc);
puthex(timeloc);
}
return alt_ticks_per_second();
}
void n2_fatal_error() {
/* Define the pattern to be sent to the seven-segment display. */
#define N2_FATAL_ERROR_HEX_PATTERN ( 0xcbd7ff )
/* Define error message text to be printed. */
static const char n2_fatal_error_text[] = "FATAL ERROR";
/* Define pointer for pointing into the error message text. */
register const char * cp = n2_fatal_error_text;
/* Send pattern to seven-segment display. */
*de2_pio_hex_low28 = N2_FATAL_ERROR_HEX_PATTERN;
/* Print the error message. */
while (*cp) {
//out_char_uart_0( *cp );
cp = cp + 1;
}
/* Stop and wait forever. */
while (1)
;
}
/*
* Interrupt handler for de2_pio_keys4.
* The parameters are ignored here, but are
* required for correct compilation.
* The type alt_u32 is an Altera-defined
* unsigned integer type.
*/
void irq_handler_keys(void * context, alt_u32 irqnum) {
alt_u32 save_value;
save_value = alt_irq_interruptible(de2_pio_keys4_intindex);
/* Read edge capture register of the de2_pio_keys4 device. */
int edges = *de2_pio_keys4_edgecap;
*de2_pio_keys4_edgecap = 0;
/* If action on KEY0 */
if (edges & 1) {
/* If KEY0 is pressed now */
if ((*de2_pio_keys4_base & 1) == 0) {
if (RUN == 0) {
RUN = 1;
} else {
RUN = 0;
}
}
/* If KEY0 is released now */
else if ((*de2_pio_keys4_base & 1) != 0) {
}
alt_irq_non_interruptible(save_value);
} else if (edges & 2) {
/* If KEY1 is pressed now */
if ((*de2_pio_keys4_base & 2) == 0) {
tick(&timeloc);
puttime(&timeloc);
puthex(timeloc);
}
/* If KEY1 is released now */
else if ((*de2_pio_keys4_base & 2) != 0) {
}
alt_irq_non_interruptible(save_value);
}
else if (edges & 4) {
/* If KEY2 is pressed now */
if ((*de2_pio_keys4_base & 4) == 0) {
timeloc = 0x0;
puttime(&timeloc);
puthex(timeloc);
}
/* If KEY2 is released now */
else if ((*de2_pio_keys4_base & 4) != 0) {
}
alt_irq_non_interruptible(save_value);
}
else if (edges & 8) {
/* If KEY3 is pressed now */
if ((*de2_pio_keys4_base & 8) == 0) {
timeloc = 0x5957;
puttime(&timeloc);
puthex(timeloc);
}
/* If KEY3 is released now */
else if ((*de2_pio_keys4_base & 8) != 0) {
}
alt_irq_non_interruptible(save_value);
}
}
/*
* Initialize de2_pio_keys4 for interrupts.
*/
void keysinit_int(void) {
/* Declare a temporary for checking return values
* from system-calls and library functions. */
register int ret_val_check;
/* Allow interrupts */
*de2_pio_keys4_intmask = 15;
/* Set up Altera's interrupt wrapper for
* interrupts from the de2_pio_keys4 device.
* The function alt_irq_register will enable
* interrupts from de2_pio_keys4.
* Return value is zero for success,
* nonzero for failure. */
ret_val_check = alt_irq_register(de2_pio_keys4_intindex, NULL_POINTER,
irq_handler_keys);
/* If there was an error, terminate the program. */
if (ret_val_check != 0)
n2_fatal_error();
}
/*
* NextPrime
*
* Return the first prime number larger than the integer
* given as a parameter. The integer must be positive.
*/
int nextPrime(int inval) {
int perhapsprime; /* Holds a tentative prime while we check it.
*/
int testfactor; /* Holds various factors for which we test
perhapsprime. */
int found; /* Flag, false until we find a prime. */
if (inval < 3) /* Initial sanity check of parameter. */
{
if (inval <= 0)
return (1); /* Return 1 for zero or negative input. */
if (inval == 1)
return (2); /* Easy special case. */
if (inval == 2)
return (3); /* Easy special case. */
} else {
/* Testing an even number for primeness is pointless, since
* all even numbers are divisible by 2. Therefore, we make sure
* that perhapsprime is larger than the parameter, and odd. */
perhapsprime = (inval + 1) | 1;
}
/* While prime not found, loop. */
for (found = PRIME_FALSE; found != PRIME_TRUE; perhapsprime += 2) {
/* Check factors from 3 up to perhapsprime/2. */
for (testfactor = 3; testfactor <= (perhapsprime >> 1); testfactor +=
1) {
found = PRIME_TRUE; /* Assume we will find a prime. */
if ((perhapsprime % testfactor) == 0) { /* If testfactor divides perhapsprime... */
found = PRIME_FALSE; /* ...then, perhapsprime was non-prime. */
goto check_next_prime;
/* Break the inner loop,
go test a new perhapsprime. */
}
}
check_next_prime: ; /* This label is used to break the inner loop. */
if (found == PRIME_TRUE) /* If the loop ended normally,
we found a prime. */
{
return (perhapsprime); /* Return the prime we found. */
}
}
return (perhapsprime); /* When the loop ends,
perhapsprime is a real prime. */
}
int main() {
int next = 3;
/* Remove unwanted interrupts.
* A nonzero return value indicates failure. */
if (initfix_int() != 0)
n2_fatal_error();
keysinit_int();
if (alt_alarm_start(&alarm, alt_ticks_per_second(), my_alarm_callback, NULL)
< 0) {
printf("No system clock available\n");
}
while( 1 ) /* Loop forever. */
{
next = nextPrime(next);
//printf("%d",next);
//printf("P %d ", next);
}
return 0;
}
int hex7seg(int digit) {
int trantab[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00,
0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e };
register int tmp = digit & 0xf;
return (trantab[tmp]);
}
void puthex(int inval) {
unsigned int hexresult;
hexresult = hex7seg(inval);
hexresult = hexresult | (hex7seg(inval >> 4) << 7);
hexresult = hexresult | (hex7seg(inval >> 8) << 14);
hexresult = hexresult | (hex7seg(inval >> 12) << 21);
IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_HEX_LOW28_BASE, hexresult);
}
Basically your code is working fine on me. The only problem is with printing, for some reason you should print a newline before such as:
printf("start program\n");
while( 1 ) /* Loop forever. */
{
next = nextPrime(next);
printf("%d",next);
}

Resources