/***** $Source: d:\gunther\source\grc/RCS/rcutils.c,v $ $Author: gunther $ $Date: 1996/01/02 23:17:24 $ $Revision: 1.4 $ Changed by: Fred Kiefer (kiefer@isys.de) 1996/6/2 *****/ #include #include #include #include #include #include #include #include #include "port.h" #include "rcutils.h" #include "wstring.h" #include "resnt.h" extern int yyerror(); void * xmalloc(size_t n) { long *q; q = malloc(n); if (q == NULL) err_msg(GRC_ERR_MEM | GRC_ERR_FATAL); return q; } node* list_new() { /* Creation of a new list. This function and the next two implement a very simple list with a dummy head, that can store any kind of data. A count of the elements in the list is kept in the head as an optimisation */ node* list; list = (node*)xmalloc(sizeof(node)); list->u.count = 0; list->next = NULL; return list; } void list_add(node *a_list, void *entry) { /* Add a new entry to a list. The entry may be what ever fits into a void *, even just an integer. */ node *p; node *fresh = (node*)xmalloc(sizeof(node)); fresh->next = NULL; fresh->u.data = entry; /* go to the end of the list */ for (p = a_list; p->next; p = p->next); a_list->u.count++; p->next = fresh; } void list_free(node *a_list, int free_entries) { /* Frees the entries of the list and the list itself. The data of the entries is also freeed if free_entries is true. */ node *p; node *q; for(p = a_list->next; p; p = q) { q = p->next; if (free_entries) free(p->u.data); free(p); } free(a_list); } char * strtoupper(char *text) { /* Uppercases a string in place */ /* This is here in case we ever decide to implement a special handling for extra characters */ char *p; for(p = text; *p; p++) { *p = toupper(*p); } return text; } int expand_string(char *to, char *from) { /* Does all the special processing a C compiler normaly does on its string input. NOTE: If the next character after '\' isnt a special character it is thrown away. */ char *s; int i = 0; debug(("Expanding string %s", from)); for(s = from; *s; s++) { if (*s == '\\') { switch(*(++s)){ case 'n': to[i++] = '\n'; break; case 't': to[i++] = '\t'; break; case 'v': to[i++] = '\v'; break; case 'b': to[i++] = '\b'; break; case 'r': to[i++] = '\r'; break; case 'f': to[i++] = '\f'; break; case 'a': to[i++] = '\a'; break; case '\\': to[i++] = '\\'; break; case '\?': to[i++] = '\?'; break; case '\'': to[i++] = '\''; break; case '\"': to[i++] = '\"'; break; case 'x': { /* hex number */ char c = '\0'; while(isxdigit(*(++s))) { c = c << 4; if (isdigit(*s)) { c += *s - '0'; } else { c += toupper(*s) - 'A' + 10; } } s--; to[i++] = c; break; } default: { /* oct number */ char c = '\0'; char *t = s; while(isdigit(*s) && *s < '8') { c = c << 3; c += *s - '0'; s++; } if (t != s) { s--; to[i++] = c; } break; } } } else { to[i++] = *s; } } to[i] = '\0'; return i; } int int_log2(int n) { /* Integer logarithmn of n. We should find a better way here */ return (int) ceil(log((double) n) / log(2.0)); } int getIDlength(wchar_t *id) { if(*id == INVAL_WCHAR) /* id points to a WORD identifier */ return 2 * sizeof(wchar_t); else /* id points to an UNICODE identifier string */ return (wstrlen(id) + 1) * sizeof(wchar_t); } char * search_include(char *filename) { static char path[260]; _searchenv(filename, "C_INCLUDE_PATH", path); if (*path) return path; _searchenv(filename, "CPLUS_INCLUDE_PATH", path); if (*path) return path; _searchenv(filename, "RCINCLUDE", path); if (*path) return path; return filename; } int filesize(const char *filename) { struct stat s; stat(filename, &s); return s.st_size; } int is_header(const char *filename) { char *ptr = (char *) filename; char *ptr1; while((ptr1 = strchr(ptr, '.')) != 0) ptr = ptr1+1; return !stricmp(ptr, "h"); } int is_resfile(const char *filename) { char *ptr = (char *) filename; char *ptr1; while((ptr1 = strchr(ptr, '.')) != 0) ptr = ptr1+1; return !stricmp(ptr, "res"); } int is_rcfile(const char *filename) { char *ptr = (char *) filename; char *ptr1; while((ptr1 = strchr(ptr, '.')) != 0) ptr = ptr1+1; return !stricmp(ptr, "rc"); } /*----------------------------------------- * basefile() * - returns the real filename from a * complete path string (like the UNIX * 'basename' command) * * Parameters: * - path: points to the complete * path string * * Returns: * the filename portion of the complete path *-----------------------------------------*/ char * basefile(char *path) { char *ptr = strchr(path, 0); #if defined(_WIN32) || defined(_MSDOS_) while((*ptr != '/') && (*ptr != '\\') && (ptr >= path)) ptr--; #else while((ptr != '/') && (ptr >= path)) ptr--; #endif ptr++; return ptr; } struct errmsg { int code; char *text; }; /* some error messages */ static const struct errmsg error_messages[] = { {GRC_OK, "No error"}, { GRC_ERR_OPEN, "Error opening file" }, { GRC_ERR_READ, "Error reading file" }, { GRC_ERR_WIN32, "Win32 error" }, { GRC_ERR_MEM, "Out of memory" }, { GRC_ERR_FILENOTFOUND, "File not found" }, { GRC_NO_RESOURCE, "That's no resource." }, { GRC_ERR_SYNTAX, "Syntax error" }, { GRC_ERR_EOF, "Unexpected end of file" }, { GRC_ERR_INVALIDSTRING, "String value expected" }, { GRC_ERR_UNEXPECTED_EOF, "Unexpected end of file" }, { GRC_ERR_UNDEFINED, "Undefined symbol" }, { GRC_ERR_BEGIN_UNEXPECT, "Unexpected BEGIN statement" }, { GRC_ERR_END_UNEXPECT, "Unexpected END statement" }, { GRC_ERR_NUMBER_EXPECTED, "Numeric value expected." }, { GRC_ERR_PARSE, "Parse error" }, { GRC_COMPLETE, "Item already complete." }, { GRC_ERR_CTRL_UNEXPECT, "Dialog: unexpected control definition" }, { GRC_ERR_CTRL_EXPECT, "Dialog: control definition expected" }, { GRC_ERR_EXPR, "Error in expression" }, { GRC_ERR_SUBLANG_EXPECT, "Sub-language specifier expected" }, { GRC_NOT_IMPLEMENTED_YET, "Feature not implemented yet." }, { GRC_err_bmp_filename_expected, "Bitmap filename expected" }, { GRC_err_ico_filename_expected, "Icon filename expected" }, { GRC_err_font_filename_expected, "Font filename expected" }, { GRC_err_dlg_invalid, "Invalid DIALOG definition" }, { GRC_err_invalid_stmnt, "Invalid statement at this place" }, { GRC_err_dlg_ctl_expected, "dialog item statement expected" }, { GRC_err_menu_invalid, "Invalid MENU definition" }, { GRC_err_menuitem_invalid, "Invalid MENUITEM definition" }, { GRC_err_strtable_invalid, "Invalid STRINGTABLE definition" }, { GRC_err_string_invalid, "Invalid string definition" }, { GRC_err_invalid_accelerator, "Invalid ACCELERATORS definition" }, { GRC_err_one_char, "Multi-character strings are not supported at this place" }, { GRC_err_invalid_icon_file, "Invalid icon file" }, { GRC_err_invalid_cursor_file, "Invalid cursor file" }, { GRC_err_nomem, "Insufficient memory available" }, { GRC_err_unicode_ansi_conversion, "UNICODE to ANSI string conversion failed" }, { GRC_err_ansi_unicode_conversion, "ANSI to UNICODE string conversion failed" }, { GRC_err_invalid_userres, "Invalid user defined ressource" }, { GRC_err_invalid_rcdata, "Invalid rcdata ressource" }, { GRC_err_invalid_versioninfo, "Invalid version info ressource" }, { 0, 0 } }; void err_msg(int code) { /* Display matchin error message and exit if it is fatal */ int fatal = code & GRC_ERR_FATAL; code = code & ~GRC_ERR_FATAL; yyerror(getErrorText(code)); if (fatal) exit(code); } char * getErrorText(int code) { int i; for(i = 0; error_messages[i].text; i++) { if(error_messages[i].code == code) return error_messages[i].text; } return "No special error message found."; } void open_error(const char *filename) { char err[512]; sprintf(err, "Could not open '%s': %s", filename, strerror(errno)); yyerror(err); } void read_error(const char *filename) { char err[512]; sprintf(err, "Could not read from '%s': %s", filename, strerror(errno)); yyerror(err); } void write_error(const char *filename) { char err[512]; sprintf(err, "Could not write to '%s': %s", filename, strerror(errno)); yyerror(err); } void seek_error(const char *filename) { char err[512]; sprintf(err, "Could not seek inside '%s': %s", filename, strerror(errno)); yyerror(err); }