- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /**
- * Constant
- */
- enum
- {
- IDENTIFIERS_MAX_COUNT = 100,
- };
- enum
- {
- IDENTIFIER_POS_MAX_ASIZE = 1000,
- };
- enum
- {
- IDENTIFIER_MAX_STRLEN = 100,
- IDENTIFIER_MAX_ASIZE,
- };
- /**
- * Data Type
- */
- struct Record_
- {
- char *identifier;
- short *positions;
- short *positions_last_ptr;
- };
- typedef struct Record_ Record;
- /**
- * Function Prototype
- */
- void record_write(char const *identifier, int line_number);
- Record *record_bsearch(char const *identifier, Record **ptr_insert_entry);
- int is_reserved_word(char const *token);
- int is_valid_identifier_char(int chr);
- /**
- * Global Variables
- */
- /* Allocation Pool */
- char g_identifier_pool[IDENTIFIERS_MAX_COUNT][IDENTIFIER_MAX_ASIZE];
- short g_identifier_pos_pool[IDENTIFIERS_MAX_COUNT][IDENTIFIER_POS_MAX_ASIZE];
- /* Allocator Pointer */
- char (*g_identifier_alloc)[IDENTIFIER_MAX_ASIZE] = g_identifier_pool;
- short (*g_identifier_pos_alloc)[IDENTIFIER_POS_MAX_ASIZE] =
- g_identifier_pos_pool;
- /* Record Array */
- Record g_identifier_records[IDENTIFIERS_MAX_COUNT];
- size_t g_identifier_records_count = 0;
- /**
- * Main Function
- */
- int
- main()
- {
- int line_number = 1;
- int chr;
- char token[IDENTIFIER_MAX_ASIZE] = {'\0'};
- char *token_ptr = token;
- do
- {
- chr = fgetc(stdin);
- if (is_valid_identifier_char(chr))
- {
- *token_ptr++ = (char)chr;
- }
- else
- {
- if (strlen(token) > 0 &&
- !isdigit(token[0]) &&
- !is_reserved_word(token))
- {
- record_write(token, line_number);
- }
- memset(token, '\0', sizeof(token));
- token_ptr = token;
- }
- if (chr == '\n')
- {
- ++line_number;
- }
- }
- while (chr != EOF);
- int i;
- short *position_ptr;
- for (i = 0; i < g_identifier_records_count; ++i)
- {
- printf("%s:", g_identifier_records[i].identifier);
- position_ptr = g_identifier_records[i].positions;
- while (position_ptr <= g_identifier_records[i].positions_last_ptr)
- {
- printf(" %d", *position_ptr++);
- }
- printf("\n");
- }
- return EXIT_SUCCESS;
- }
- /**
- * Function Implememnts
- */
- int
- is_valid_identifier_char(int chr)
- {
- return (isdigit(chr) || isupper(chr) || islower(chr) || chr == '_');
- }
- int
- is_reserved_word(char const *token)
- {
- static char reserved_words[][9] =
- {
- "auto", "break", "case", "char", "const", "continue", "default",
- "do", "double", "else", "enum", "extern", "float", "for", "goto",
- "if", "int", "long", "register", "return", "short", "signed",
- "sizeof", "static", "struct", "switch", "typedef", "union",
- "unsigned", "void", "volatile", "while"
- };
- static size_t reserved_words_count =
- sizeof(reserved_words)/sizeof(char[9]);
- size_t i = 0;
- for (i = 0; i < reserved_words_count; ++i)
- {
- if (strcmp(token, reserved_words[i]) == 0)
- {
- return 1;
- }
- }
- return 0;
- }
- void
- record_write(char const *identifier, int line_number)
- {
- Record *insert_entry = NULL;
- Record *record_entry = record_bsearch(identifier, &insert_entry);
- if (!record_entry)
- {
- size_t index = insert_entry - g_identifier_records;
- if (index < g_identifier_records_count)
- {
- memmove((insert_entry + 1),
- (insert_entry),
- (sizeof(Record) * (g_identifier_records_count - index)));
- }
- g_identifier_records_count++;
- record_entry = insert_entry;
- record_entry->identifier = *g_identifier_alloc++;
- record_entry->positions = *g_identifier_pos_alloc++;
- record_entry->positions_last_ptr = record_entry->positions;
- strcpy(record_entry->identifier, identifier);
- *(record_entry->positions_last_ptr) = line_number;
- }
- else
- {
- if (*(record_entry->positions_last_ptr) != line_number)
- {
- *(++record_entry->positions_last_ptr) = line_number;
- }
- }
- }
- Record *
- record_bsearch(char const *identifier, Record **ptr_insert_entry)
- {
- int compare = 0;
- /* -- Check No Record -------- */
- if (g_identifier_records_count == 0)
- {
- *ptr_insert_entry = g_identifier_records;
- return NULL;
- }
- /* -- Check Two (Less) Record -------- */
- if (g_identifier_records_count <= 2)
- {
- Record *curr = NULL;
- for (curr = g_identifier_records;
- curr < g_identifier_records + g_identifier_records_count;
- curr++)
- {
- compare = strcmp(identifier, curr->identifier);
- if (compare == 0)
- {
- *ptr_insert_entry = curr;
- return curr;
- }
- else if (compare < 0)
- {
- *ptr_insert_entry = curr;
- return NULL;
- }
- }
- *ptr_insert_entry = curr;
- return NULL;
- }
- /* -- More than Two -------- */
- Record *begin = g_identifier_records;
- Record *end = g_identifier_records + (g_identifier_records_count - 1);
- compare = strcmp(identifier, begin->identifier);
- if (compare == 0)
- {
- *ptr_insert_entry = begin;
- return begin;
- }
- else if (compare < 0)
- {
- *ptr_insert_entry = begin;
- return NULL;
- }
- compare = strcmp(identifier, end->identifier);
- if (compare == 0)
- {
- *ptr_insert_entry = end;
- return end;
- }
- else if (compare > 0)
- {
- *ptr_insert_entry = end + 1;
- return NULL;
- }
- while (end - begin > 1)
- {
- Record *mid = begin + (end - begin) / 2;
- compare = strcmp(identifier, mid->identifier);
- if (compare == 0)
- {
- *ptr_insert_entry = mid;
- return mid;
- }
- else if (compare < 0)
- {
- end = mid;
- }
- else /* if (compare > 0) */
- {
- begin = mid;
- }
- }
- *ptr_insert_entry = end;
- return NULL;
- }
- /* -- eof -------- */
Raw Paste