This is load_file.c in view mode; [Download] [Up]
/* * PCN Abstract Machine Emulator * Authors: Steve Tuecke and Ian Foster * Argonne National Laboratory * * Please see the DISCLAIMER file in the top level directory of the * distribution regarding the provisions under which this software * is distributed. * * load_file.c - Dynamically load .pam files into the running emulator */ #include "pcn.h" #ifdef DYNAMIC_PAM_LOADING #include "pcno.h" static char_t error_buffer[1024]; static char_t * load_pam_fp(); static proc_header_t * get_proc_header(); static char_t * load_procedure_subsects(); static char_t * read_pcno_integers(); static char_t * read_pcno_string(); static char_t * load_string_list(); static void free_string_list(); static list_t * alloc_list_entry(); static void massage_string_list(); #define TEST_FTELL(Ftell_Value, Stream, Location) \ if ((Ftell_Value = ftell(Stream)) < 0) \ { \ sprintf(error_buffer, "Failed ftell() at location %d", Location); \ return (error_buffer); \ } #define TEST_FSEEK(Stream, Offset, Whence, Location) \ if (fseek(Stream, (long) (Offset), (int) Whence) != 0) \ { \ sprintf(error_buffer, "Failed fseek() at location %d", Location); \ return (error_buffer); \ } #define TEST_READ_PCNO_INTEGERS(Stream, Into, Start, Size) \ if (read_pcno_integers(Stream, Into, Start, Size) != (char_t *) NULL) \ { \ return (error_buffer); \ } #define TEST_READ_PCNO_STRING(Stream, Into, Size) \ if ((eb = read_pcno_string(Stream, Into, Size)) != (char_t *) NULL) \ { \ return (eb); \ } #define TEST_LOAD_STRING_LIST(Stream, N_Entries, Group_Size, String_List) \ if ((eb = load_string_list(Stream, N_Entries, Group_Size, String_List)) != (char_t *) NULL) \ { \ return (eb); \ } /* * _p_load_pam_file_init() * * Initialize any global variables used for dynamic .pam file loading. */ void _p_load_pam_file_init() { } /* _p_load_pam_file_init() */ /* * _p_load_pam_file() * * Load the pam file with the path 'filename' into the emulator. * * Return: A NULL char_t pointer if it loads successfully. * A pointer to an error message string otherwise. */ char_t *_p_load_pam_file(filename) char_t *filename; { FILE *fp; char_t *eb; cell_t *save_heap_ptr; if ((fp = fopen(filename, "r")) == (FILE *) NULL) { sprintf(error_buffer, "Could not open file for reading"); return (error_buffer); } eb = load_pam_fp(fp); fclose(fp); return (eb); } /* _p_load_pam_file() */ /* * load_pam_fp() * * Load the opened pam file, with file pointer 'fp'. * * Return: A NULL char_t pointer if it loads successfully. * A pointer to an error message string otherwise. */ static char_t *load_pam_fp(fp) FILE *fp; { pcno_header_t pcno_header; pcno_module_segment_t pcno_module_header; pcno_procedure_t pcno_proc_header; long current_segment, current_section; u_int_t segment_number, section_number; list_t *list_entry; char_t *module_name, *proc_name; proc_header_t *proc_header; char_t *eb; #ifdef GAUGE int_t *counters, *timers; #endif /* GAUGE */ /* * Read in and check the PCNO header for validity */ TEST_READ_PCNO_INTEGERS(fp, &pcno_header, 0, PCNO_HEADER_SIZE); if (pcno_header.magic != PCNO_MAGIC) { sprintf(error_buffer, "Bad PCNO magic number"); return (error_buffer); } if (pcno_header.version != PCNO_VERSION) { sprintf(error_buffer, "Bad PCNO version number (expected %lu, got %lu)", (unsigned long) PCNO_MAGIC, (unsigned long) pcno_header.version); return (error_buffer); } /* * Iterate over the segments, reading in any module segments we find. */ TEST_FTELL(current_segment, fp, 1); for (segment_number = 0; segment_number < pcno_header.n_segments; segment_number++) { TEST_READ_PCNO_INTEGERS(fp, &pcno_module_header,0,PCNO_BLOCK_HDR_SIZE); if (pcno_module_header.type == PCNO_SEG_MODULE) { /* * This is a module segment, so read it in. */ TEST_READ_PCNO_INTEGERS(fp, &pcno_module_header, 2, (PCNO_SEG_MODULE_HDR_SIZE - PCNO_BLOCK_HDR_SIZE) ); TEST_READ_PCNO_STRING(fp, &module_name, (pcno_module_header.section_offset - (PCNO_SEG_MODULE_HDR_SIZE * PCNO_WORD_SIZE)) ); pcno_module_header.name = module_name; /* * Iterate over the segments, reading them in as we go. */ TEST_FTELL(current_section, fp, 1); for (section_number = 0; section_number < pcno_module_header.n_sections; section_number++) { TEST_READ_PCNO_INTEGERS(fp, &pcno_proc_header, 0, PCNO_BLOCK_HDR_SIZE); if (pcno_proc_header.type == PCNO_MODSECT_PROCEDURE) { /* * This is a procedure section, so read it in. */ TEST_READ_PCNO_INTEGERS(fp, &pcno_proc_header, 2, (PCNO_MODSECT_PROCEDURE_HDR_SIZE - PCNO_BLOCK_HDR_SIZE) ); TEST_READ_PCNO_STRING(fp, &proc_name, (pcno_proc_header.subsect_offset - (PCNO_MODSECT_PROCEDURE_HDR_SIZE * PCNO_WORD_SIZE)) ); pcno_proc_header.name = proc_name; /* * Setup the proc_header for this new procedure. */ proc_header = get_proc_header(module_name, proc_name); proc_header->arity = pcno_proc_header.arity; proc_header->code = (code_t *) NULL; #ifdef GAUGE proc_header->n_counters = pcno_proc_header.n_counters; if ((proc_header->counters = (int_t *) malloc(sizeof(int_t) * proc_header->n_counters)) == (int_t *) NULL) { _p_malloc_error(); } proc_header->n_timers = pcno_proc_header.n_timers; if ((proc_header->timers = (int_t *) malloc(sizeof(int_t) * 2 * proc_header->n_timers)) == (int_t *) NULL) { _p_malloc_error(); } proc_header->idle_timer = proc_header->timers; proc_header->model = (char_t **) NULL; #endif /* GAUGE */ #ifdef PDB proc_header->debugable = 0; proc_header->debug = 0; proc_header->break_num = 0; proc_header->exported = pcno_proc_header.exported; #endif /* PDB */ /* * Load in all of the procedure subsections */ eb = load_procedure_subsects(fp, proc_header, pcno_proc_header.n_subsects); if (eb != (char_t *) NULL) { return (eb); } free(proc_name); } /* * Position the file for reading the next section */ current_section += pcno_proc_header.size; TEST_FSEEK(fp, current_section, 0, 2); } free(module_name); } /* * Position the file for reading the next segment */ current_segment += pcno_module_header.size; TEST_FSEEK(fp, current_segment, 0, 2); } return ((char_t *) NULL); } /* load_pam_fp() */ /* * get_proc_header() * * Return the proc_header for the passed procedures. If it does not * exist, then create one. */ static proc_header_t *get_proc_header(module_name, proc_name) char_t *module_name; char_t *proc_name; { proc_header_t *proc_header; list_t *list_entry; proc_header = _p_proc_lookup(module_name, proc_name); if (proc_header == (proc_header_t *) NULL) { int_t hash_index, hash_head; if ( (proc_header = (proc_header_t *) malloc(sizeof(proc_header_t))) == (proc_header_t *) NULL) { _p_malloc_error(); } if (((proc_header->module_name=(char_t *)malloc(strlen(module_name)+1)) == (char_t *) NULL) || ((proc_header->proc_name =(char_t *)malloc(strlen(proc_name)+1)) == (char_t *) NULL) ) { _p_malloc_error(); } strcpy(proc_header->module_name, module_name); strcpy(proc_header->proc_name, proc_name); _p_em_hash_index_for_procedure_name(module_name, proc_name, &_p_exported_table_size, &hash_index); proc_header->next = _p_exported_table[hash_index]; _p_exported_table[hash_index] = proc_header; } return (proc_header); } /* get_proc_header() */ /* * load_procedure_subsects() * * Load in all of the relevant procedure subsections from 'fp' and * change 'proc_header' appropriately. It is assumed that 'fp' is * positioned at the start of the first subsection. It does not * guarantee anything about the position of 'fp' when it is done. * * Return: A NULL char_t pointer if it loads successfully. * A pointer to an error message string otherwise. */ static char_t *load_procedure_subsects(fp, proc_header, n_subsects) FILE *fp; proc_header_t *proc_header; u_int_t n_subsects; { pcno_code_t code_header; pcno_block_header_t block_header; proc_header_t **pcall_table = (proc_header_t **) NULL; u_int_t *fcall_table = (u_int_t *) NULL; cell_t **double_table = (cell_t **) NULL; cell_t **string_table = (cell_t **) NULL; cell_t **int_table = (cell_t **) NULL; char_t **string_list, *s; long current_subsect; u_int_t subsect_number; u_int_t n_entries, group_size, i, j, k; char_t *eb; bool_t found; static_double_value_t *double_value; static_string_value_t *string_value; static_int_value_t *int_value; cell_t *program_counter; cell_t *end_of_code; instruction_t *instr; char_t *module_name, *proc_name; code_header.code_array = (code_t *) NULL; TEST_FTELL(current_subsect, fp, 10); for (subsect_number = 0; subsect_number < n_subsects; subsect_number++) { TEST_READ_PCNO_INTEGERS(fp, &block_header, 0, PCNO_BLOCK_HDR_SIZE); switch (block_header.type) { case PCNO_PROC_CODE: code_header.type = block_header.type; code_header.size = block_header.size; TEST_READ_PCNO_INTEGERS(fp, &code_header, 2, (PCNO_PROC_CODE_HDR_SIZE - PCNO_BLOCK_HDR_SIZE) ); i = code_header.code_size / PCNO_WORD_SIZE; if ((code_header.code_array = (code_t *) malloc (i * CELL_SIZE)) == (code_t *) NULL) { _p_malloc_error(); } TEST_READ_PCNO_INTEGERS(fp, code_header.code_array, 0, i); break; case PCNO_PROC_PCALL_TABLE: TEST_LOAD_STRING_LIST(fp, &n_entries, &group_size, &string_list); if ((pcall_table = (proc_header_t **) malloc(n_entries * sizeof(proc_header_t *))) == (proc_header_t **) NULL) { _p_malloc_error(); } for (i = 0, j = 0; i < n_entries; i++, j += 2) { module_name = string_list[j]; if (module_name[0] == '\0') module_name = proc_header->module_name; proc_name = string_list[j + 1]; pcall_table[i] = get_proc_header(module_name, proc_name); } free_string_list(n_entries, group_size, string_list); break; case PCNO_PROC_FCALL_TABLE: TEST_LOAD_STRING_LIST(fp, &n_entries, &group_size, &string_list); if ((fcall_table = (u_int_t *) malloc(n_entries * sizeof(u_int_t))) == (u_int_t *) NULL) { _p_malloc_error(); } for (i = 0; i < n_entries; i++) { s = string_list[i];; #ifdef STRIP_TRAILING_UNDERSCORE j = strlen(s) - 1; if (s[j] == '_') { s[j] = '\0'; } #endif found = FALSE; for (j = 0; j < _p_foreign_table_size && !found; j++) { if (strcmp(_p_foreign_table[j].foreign_name, s) == 0) { found = TRUE; fcall_table[i] = (u_int_t) _p_foreign_table[j].foreign_ptr; } } if (!found) { sprintf(error_buffer, "Could not resolve call to foreign procedure %s() from PCN procedure %s:%s()", s, proc_header->module_name, proc_header->proc_name); return (error_buffer); } } free_string_list(n_entries, group_size, string_list); break; case PCNO_PROC_DOUBLE_TABLE: TEST_LOAD_STRING_LIST(fp, &n_entries, &group_size, &string_list); if ((double_table = (cell_t **) malloc(n_entries * sizeof(cell_t *))) == (cell_t **) NULL) { _p_malloc_error(); } for (i = 0; i < n_entries; i++) { if ((double_value = (static_double_value_t *) malloc(sizeof(static_double_value_t) #ifdef PCN_ALIGN_DOUBLES + DOUBLE_WORD_SIZE #endif )) == (static_double_value_t *) NULL) { _p_malloc_error(); } AlignDoubleOnEvenWord((static_double_value_t *), double_value, j); double_value->n_cells = 1 + CELLS_PER_DOUBLE; double_value->h.tag = DOUBLE_TAG; double_value->h.mark = 0; double_value->h.size = 1; double_value->d = atof(string_list[i]); double_table[i] = (cell_t *) double_value; } free_string_list(n_entries, group_size, string_list); break; case PCNO_PROC_STRING_TABLE: TEST_LOAD_STRING_LIST(fp, &n_entries, &group_size, &string_list); massage_string_list(string_list, n_entries * group_size); if ((string_table = (cell_t **) malloc(n_entries * sizeof(cell_t *))) == (cell_t **) NULL) { _p_malloc_error(); } for (i = 0; i < n_entries; i++) { j = strlen(string_list[i]) + 1; k = StringSizeToCells(j); if ((string_value = (static_string_value_t *) malloc(sizeof(static_string_value_t) + (k * CELL_SIZE))) == (static_string_value_t *) NULL) { _p_malloc_error(); } string_value->n_cells = 1 + k; string_value->h.tag = STRING_TAG; string_value->h.mark = 0; string_value->h.size = j; strcpy(string_value->str, string_list[i]); string_table[i] = (cell_t *) string_value; } free_string_list(n_entries, group_size, string_list); break; case PCNO_PROC_INT_TABLE: TEST_LOAD_STRING_LIST(fp, &n_entries, &group_size, &string_list); if ((int_table = (cell_t **) malloc(n_entries * sizeof(cell_t *))) == (cell_t **) NULL) { _p_malloc_error(); } for (i = 0; i < n_entries; i++) { if ((int_value = (static_int_value_t *) malloc(sizeof(static_int_value_t))) == (static_int_value_t *) NULL) { _p_malloc_error(); } int_value->n_cells = 2; int_value->h.tag = INT_TAG; int_value->h.mark = 0; int_value->h.size = 1; int_value->i = (int_t) atol(string_list[i]); int_table[i] = (cell_t *) int_value; } free_string_list(n_entries, group_size, string_list); break; default: /* Ignore this subsection */ break; } current_subsect += block_header.size; TEST_FSEEK(fp, current_subsect, 0, 11); } /* * Now scan though the procedure's code... */ if (code_header.code_array == (code_t *) NULL) { sprintf(error_buffer, "Did not find code for procedure %s:%s()", proc_header->module_name, proc_header->proc_name); return (error_buffer); } program_counter = (cell_t *) code_header.code_array; end_of_code = program_counter + (code_header.code_size/PCNO_WORD_SIZE); while(program_counter < end_of_code) { instr = (instruction_t *) program_counter; switch(instr->I_OPCODE) { case I_FORK: if (pcall_table == (proc_header_t **) NULL) { sprintf(error_buffer, "Instruction scan of %s:%s(): Expected non-empty PCN call table", proc_header->module_name, proc_header->proc_name); return (error_buffer); } i = (u_int_t) instr->I_FORK_PROC; instr->I_FORK_PROC = (cell_t *) pcall_table[i]; program_counter += SIZE_FORK; break; case I_RECURSE: if (pcall_table == (proc_header_t **) NULL) { sprintf(error_buffer, "Instruction scan of %s:%s(): Expected non-empty PCN call table", proc_header->module_name, proc_header->proc_name); return (error_buffer); } i = (u_int_t) instr->I_RECURSE_PROC; instr->I_RECURSE_PROC = (cell_t *) pcall_table[i]; #ifdef GAUGE i = (u_int_t) instr->I_RECURSE_COUNTER; instr->I_RECURSE_COUNTER = proc_header->counters + i; #endif /* GAUGE */ program_counter += SIZE_RECURSE; break; case I_HALT: #ifdef GAUGE i = (u_int_t) instr->I_HALT_COUNTER; instr->I_HALT_COUNTER = proc_header->counters + i; #endif /* GAUGE */ program_counter += SIZE_HALT; break; case I_DEFAULT: #ifdef GAUGE i = (u_int_t) instr->I_DEFAULT_COUNTER; instr->I_DEFAULT_COUNTER = proc_header->counters + i; #endif /* GAUGE */ program_counter += SIZE_DEFAULT; break; case I_TRY: i = (u_int_t) instr->I_TRY_LOCATION; instr->I_TRY_LOCATION = ((cell_t *) code_header.code_array) + i; program_counter += SIZE_TRY; break; case I_RUN: program_counter += SIZE_RUN; break; case I_BUILD_STATIC: program_counter += SIZE_BUILD_STATIC; break; case I_BUILD_DYNAMIC: program_counter += SIZE_BUILD_DYNAMIC; break; case I_BUILD_DEF: program_counter += SIZE_BUILD_DEF; break; case I_PUT_DATA: i = (u_int_t) instr->I_PUT_DATA_PTR; switch (instr->I_PUT_DATA_TAG) { case INT_TAG: if (int_table == (cell_t **) NULL) { sprintf(error_buffer, "%s:%s(): Expected non-empty integer constant table", proc_header->module_name, proc_header->proc_name); return (error_buffer); } instr->I_PUT_DATA_PTR = int_table[i]; break; case STRING_TAG: if (string_table == (cell_t **) NULL) { sprintf(error_buffer, "%s:%s(): Expected non-empty string constant table", proc_header->module_name, proc_header->proc_name); return (error_buffer); } instr->I_PUT_DATA_PTR = string_table[i]; break; case DOUBLE_TAG: if (double_table == (cell_t **) NULL) { sprintf(error_buffer, "%s:%s(): Expected non-empty double constant table", proc_header->module_name, proc_header->proc_name); return (error_buffer); } instr->I_PUT_DATA_PTR = double_table[i]; break; default: sprintf(error_buffer, "Instruction scan of %s:%s(): Found illegal tag in put_data instruction", proc_header->module_name, proc_header->proc_name); return (error_buffer); break; } program_counter += SIZE_PUT_DATA; break; case I_PUT_VALUE: program_counter += SIZE_PUT_VALUE; break; case I_COPY: program_counter += SIZE_COPY; break; case I_GET_TUPLE: program_counter += SIZE_GET_TUPLE; break; case I_EQUAL: program_counter += SIZE_EQUAL; break; case I_NEQ: program_counter += SIZE_NEQ; break; case I_TYPE: program_counter += SIZE_TYPE; break; case I_LE: program_counter += SIZE_LE; break; case I_LT: program_counter += SIZE_LT; break; case I_DATA: program_counter += SIZE_DATA; break; case I_UNKNOWN: program_counter += SIZE_UNKNOWN; break; case I_DEFINE: program_counter += SIZE_DEFINE; break; case I_GET_ELEMENT: program_counter += SIZE_GET_ELEMENT; break; case I_PUT_ELEMENT: program_counter += SIZE_PUT_ELEMENT; break; case I_ADD: program_counter += SIZE_ADD; break; case I_SUB: program_counter += SIZE_SUB; break; case I_MUL: program_counter += SIZE_MUL; break; case I_DIV: program_counter += SIZE_DIV; break; case I_MOD: program_counter += SIZE_MOD; break; case I_LENGTH: program_counter += SIZE_LENGTH; break; case I_COPY_MUT: #ifdef GAUGE i = (u_int_t) instr->I_COPY_MUT_COUNTER; instr->I_COPY_MUT_COUNTER = proc_header->counters + i; #endif /* GAUGE */ program_counter += SIZE_COPY_MUT; break; case I_PUT_FOREIGN: program_counter += SIZE_PUT_FOREIGN; break; case I_CALL_FOREIGN: if (fcall_table == (u_int_t *) NULL) { sprintf(error_buffer, "Instruction scan of %s:%s(): Expected non-empty foreign call table", proc_header->module_name, proc_header->proc_name); return (error_buffer); } i = (u_int_t) instr->I_CALL_FOREIGN_FOR; instr->I_CALL_FOREIGN_FOR = (cell_t *) fcall_table[i]; #ifdef GAUGE i = (u_int_t) instr->I_CALL_FOREIGN_TIMER; instr->I_CALL_FOREIGN_TIMER = proc_header->timers + (i * 2); #endif /* GAUGE */ program_counter += SIZE_CALL_FOREIGN; break; case I_EXIT: program_counter += SIZE_EXIT; break; case I_PRINT_TERM: program_counter += SIZE_PRINT_TERM; break; default: sprintf(error_buffer, "Instruction scan of %s:%s(): Found illegal instruction", proc_header->module_name, proc_header->proc_name); return (error_buffer); break; } } proc_header->code = code_header.code_array; if (pcall_table != (proc_header_t **) NULL) free(pcall_table); if (fcall_table != (u_int_t *) NULL) free(fcall_table); if (double_table != (cell_t **) NULL) free(double_table); if (string_table != (cell_t **) NULL) free(string_table); if (int_table != (cell_t **) NULL) free(int_table); return ((char_t *) NULL); } /* load_procedure_subsects() */ /* * read_pcno_integers() * * Read in 'size' integers from the PCNO file pointed to by 'fp' * and put them into the integer array 'into' starting at location * 'start'. * * This routine needs to do conversions between the external PCNO * format and in the internal integer format. This includes both * byte ordering (big endian to whatever) and word size (4 bytes * integers to whatever). * * Return: A NULL char_t pointer if it loads successfully. * A pointer to an error message string otherwise. */ static char_t *read_pcno_integers(fp, into, start, size) FILE *fp; u_int_t *into; u_int_t start; u_int_t size; { char_t buf[PCNO_WORD_SIZE]; u_int_t *i, *end; char_t *eb; for (i = into + start, end = i + size; i < end; i++) { if (fread(buf, PCNO_WORD_SIZE, 1, fp) != 1) { sprintf(error_buffer, "Failed fread() in read_pcno_integers."); return (error_buffer); } *i = ((int_t) ( (((u_int_t) *((unsigned char *) (buf))) << 24) | (((u_int_t) *(((unsigned char *) (buf)) + 1)) << 16) | (((u_int_t) *(((unsigned char *) (buf)) + 2)) << 8) | (((u_int_t) *(((unsigned char *) (buf)) + 3))) )); } return ((char_t *) NULL); } /* read_pcno_integers() */ /* * read_pcno_string() * * Read 'size' bytes from 'fp' into a malloc'ed array, and set *into * to point to that malloc'ed array. * * Return: A NULL char_t pointer if it loads successfully. * A pointer to an error message string otherwise. */ static char_t *read_pcno_string(fp, into, size) FILE *fp; char_t **into; u_int_t size; { if ((*into = (char_t *) malloc (size)) == (char_t *) NULL) { _p_malloc_error(); } if (fread(*into, size, 1, fp) != 1) { sprintf(error_buffer, "Failed fread() in read_pcno_string."); return (error_buffer); } return ((char_t *) NULL); } /* read_pcno_string() */ /* * load_string_list() * * Load the string list from 'fp'. * Fill in 'n_entries' and 'group_size' with the appropriate values from * the string list header. * Set 'string_list' to be an array of pointers to the strings * in the string list. * * Return: A NULL char_t pointer if it loads successfully. * A pointer to an error message string otherwise. */ static char_t *load_string_list(fp, n_entries, group_size, string_list) FILE *fp; u_int_t *n_entries; u_int_t *group_size; char_t ***string_list; { u_int_t i, n_strings; u_int_t string_len; char_t *eb; TEST_READ_PCNO_INTEGERS(fp, n_entries, 0, 1); TEST_READ_PCNO_INTEGERS(fp, group_size, 0, 1); n_strings = *n_entries * *group_size; if ((*string_list = (char_t **) malloc (n_strings * sizeof(char_t *))) == (char_t **) NULL) { _p_malloc_error(); } for (i = 0; i < n_strings; i++) { TEST_READ_PCNO_INTEGERS(fp, &string_len, 0, 1); TEST_READ_PCNO_STRING(fp, ((*string_list) + i), string_len); } return ((char_t *) NULL); } /* load_string_list() */ /* * free_string_list() * * Free up a string list that was created by load_string_list() */ static void free_string_list(n_entries, group_size, string_list) u_int_t n_entries; u_int_t group_size; char_t **string_list; { u_int_t i, end; for (i = 0, end = n_entries * group_size; i < end; i++) free(string_list[i]); free(string_list); } /* free_string_list() */ /* * alloc_list_entry() * * malloc space for a list_t entry and put 'value' into the new entry */ static list_t *alloc_list_entry(value) void *value; { list_t *l; if ((l = (list_t *) malloc (sizeof(list_t))) == (list_t *) NULL) { _p_malloc_error(); } l->value = value; return (l); } /* alloc_list_entry() */ /* * massage_string_list() * * Go through the entries in the string list (a array of pointers * to malloc'ed strings) and replace each string with its equivalent * except that control sequences have been fixed. For example, * if the original string has a "\n" in it, then replace it with * a string that actually has the '\n' character in place of * the "\n" (two characters). * * Normally, this conversion is done by the C compiler when linking * the pcnt file. But since we are skipping the C compiler, we need * to do this ourself. */ static void massage_string_list(string_list, n_entries) char_t **string_list; u_int_t n_entries; { u_int_t i; char_t *old_string, *o, *new_string, *n; u_int_t v; bool_t done; for (i = 0; i < n_entries; i++) { old_string = string_list[i]; if ((new_string = (char_t *) malloc (strlen(old_string) + 1)) == (char_t *) NULL) { _p_malloc_error(); } o = old_string; n = new_string; while (*o != '\0') { if (*o == '\\') { switch (*(o + 1)) { case 'n': *n++ = '\n'; o += 2; break; case 't': *n++ = '\t'; o += 2; break; case 'v': *n++ = '\v'; o += 2; break; case 'b': *n++ = '\b'; o += 2; break; case 'r': *n++ = '\r'; o += 2; break; case 'f': *n++ = '\f'; o += 2; break; case 'a': *n++ = '\a'; o += 2; break; case '\\': *n++ = '\\'; o += 2; break; case '\?': *n++ = '\?'; o += 2; break; case '\'': *n++ = '\''; o += 2; break; case '\"': *n++ = '\"'; o += 2; break; case 'x': /* hex constant : \x followed by 0 or more hex digits */ o += 2; for (v = 0, done = FALSE; !done; ) { if (*o >= '0' && *o <= '9') { v = 16 * v + (*o - '0'); o++; } else if (*o >= 'a' && *o <= 'f') { v = 16 * v + (*o - 'a' + 10); o++; } else if (*o >= 'A' && *o <= 'F') { v = 16 * v + (*o - 'A' + 10); o++; } else { done = TRUE; } } *n++ = v; break; default: o++; if (*o >= '0' && *o <= '7') { /* * octal constant : * \ followed by 1, 2, or 3 octal digits */ v = *o - '0'; o++; if (*o >= '0' && *o <= '7') { v = 8 * v + (*o - '0'); o++; if (*o >= '0' && *o <= '7') { v = 8 * v + (*o - '0'); o++; } } } else { /* Unknown -- so leave the backslash in */ *n++ = '\\'; *n++ = *o++; } break; } } else { *n++ = *o++; } } *n = '\0'; string_list[i] = new_string; free(old_string); } } /* massage_string_list() */ #endif /* DYNAMIC_PAM_LOADING */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.