/*---------------------------------------------------------------------------* Project: TwlSDK - tools - makerom File: defval.c Copyright 2003-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2008-09-18#$ $Rev: 8573 $ $Author: okubata_ryoma $ *---------------------------------------------------------------------------*/ #include #include // getenv() #include // isspace() #include // strcasecmp() #include // getopt() #include "misc.h" #include "defval.h" #include "makelcf.h" typedef struct tValdef { struct tValdef *next; char *name; char *value; } tValdef; tValdef *valdef_top = NULL; // // Add new define value via file // // opt : "DEFINE=VALUE" // BOOL AddDefValFromFile(char *filename) { char *buffer; int buffer_size; int read_size; FILE *fp; if (filename[0] == '-' && filename[1] == '\0') { fp = stdin; } else if (NULL == (fp = fopen(filename, "rb"))) { fprintf(stderr, "Cannot open file \"%s\".\n", filename); return FALSE; } buffer_size = DEFVAL_DEFAULT_BUFFER_SIZE; if (NULL == (buffer = malloc(buffer_size))) { fprintf(stderr, "Cannot allocate memory.\n"); return FALSE; } read_size = 0; while (NULL != fgets(buffer + read_size, buffer_size - read_size, fp)) { read_size = strlen(buffer); if (read_size == buffer_size - 1 && buffer[read_size - 1] != '\n') { buffer_size *= 2; if (NULL == (buffer = realloc(buffer, buffer_size))) { fprintf(stderr, "Cannot allocate memory.\n"); return FALSE; } continue; } AddDefVal(buffer); read_size = 0; } if (fp != stdin) { fclose(fp); } free(buffer); return TRUE; } // // Add new define value // // opt : "DEFINE=VALUE" // void AddDefVal(char *opt) { int i, lastword; tValdef *t; for (i = lastword = 0;; i++) { if ('=' == opt[i] || '\0' == opt[i]) { break; } if (!isspace(opt[i])) { lastword = i + 1; } } if (lastword > 0) { t = Alloc(sizeof(tValdef)); t->name = strncpy(Alloc(lastword + 1), opt, lastword); t->name[lastword] = '\0'; if (opt[i] == '=') { i++; } t->value = strdup(opt + i); lastword = strlen(t->value) - 1; while (lastword >= 0) { if ('\r' != t->value[lastword] && '\n' != t->value[lastword]) { break; } t->value[lastword] = '\0'; lastword--; } t->next = valdef_top; valdef_top = t; debug_printf("DEFINE:$(%s)=\"%s\"\n", t->name, t->value); } return; } // // Search define value // // Return: value of specified name // const char *SearchDefVal(const char *name) { tValdef *t; for (t = valdef_top; t; t = t->next) { if (!strcmp(t->name, name)) { return t->value; } } return getenv(name); } // // SearchDefVal with NULL string handling // const char *SearchDefValCleaned(const char *name) { const char *result = NULL; if (name != NULL) { result = SearchDefVal(name); } return result ? result : ""; } // // Resolve modifier // // Return: duplicated value of specified name modified by :x option // char *ResolveStringModifier(const char *in_value, char modifier) { char *value; if (in_value == NULL) { value = NULL; } else if (!modifier) // No modifier { value = strdup(in_value); } else { const int NO_EXTENSION = -1; int value_len = strlen(in_value); int col_extension = NO_EXTENSION; int col_filename = 0; int i; for (i = 0; i < value_len; i++) { switch (in_value[i]) { case '.': if (col_filename == i && (in_value[i + 1] == '\0' || (in_value[i + 1] == '.' && in_value[i + 2] == '\0'))) { i = value_len; // exit loop if last entry is '.' or '..' } else { col_extension = i; // Save the last dot column } break; case '/': case '\\': case ':': col_filename = i + 1; // Save the last filename col_extension = NO_EXTENSION; // Reset dot position break; default: ; } } switch (modifier) { case 'h': // Dirname with the last slash value = strdup(in_value); value[col_filename] = '\0'; break; case 't': // Filename value = strdup(in_value + col_filename); break; case 'r': // All without . file extension value = strdup(in_value); if (col_extension >= 0) { value[col_extension] = '\0'; } break; case 'e': // File extension if (col_extension >= 0) { value = strdup(in_value + col_extension + 1); } else { value = strdup(""); } break; default: // Unknown fprintf(stderr, "Unknown modifier ':%c'... Ignored.\n", modifier); value = strdup(in_value); break; } } return value; } // // Search define value and Modify it by ':' modifier // // Return: duplicated value of specified name modified by ':X' // char *SearchDefValWithOption(const char *in_name) { char *name = strdup(in_name); int len_name = strlen(in_name); char modifier = '\0'; char *value; if (len_name > 2 && name[len_name - 2] == ':') { name[len_name - 2] = '\0'; modifier = name[len_name - 1]; } value = ResolveStringModifier(SearchDefVal(name), modifier); debug_printf("REFERED(%s)=[%s]\n", in_name, value ? value : "(NULL)"); free(name); return value; } // // Resolve define value // // Return: new string // char *ResolveDefVal(char *str) { int i, j; char *val; VBuffer buf; InitVBuffer(&buf); for (i = 0; '\0' != str[i]; i++) { // search $(XXX) if ('$' == str[i] && '(' == str[i + 1]) { for (j = i + 2; '\0' != str[j]; j++) { if (')' == str[j]) { str[j] = '\0'; // get value of XXX val = SearchDefValWithOption(&str[i + 2]); // copy value of XXX if (val) { char *s = val; while (*s) { PutVBuffer(&buf, *s); s++; } free(val); } i = j; goto next; } } } PutVBuffer(&buf, str[i]); next:; } return GetVBuffer(&buf); // pass allocated buffer, should be freed by caller }