Unicode support for !define /file and !searchparse /file
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6329 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
936244da8d
commit
5fb2e9e166
2 changed files with 79 additions and 51 deletions
|
@ -52,6 +52,31 @@ using namespace std;
|
|||
|
||||
#define MAX_INCLUDEDEPTH 10
|
||||
|
||||
static UINT read_line_helper(NStreamLineReader&lr, TCHAR*buf, UINT cch)
|
||||
{
|
||||
// Helper function for reading lines from text files. buf MUST be valid and cch MUST be > 1!
|
||||
// Returns 0 on error or the number of characters read including the first \n, \r or \0.
|
||||
// When it returns 0, buf[0] is 0 for EOF and NStream::ERR_* for errors.
|
||||
UINT lrr = lr.ReadLine(buf, cch), eof = 0;
|
||||
if (NStream::OK != lrr)
|
||||
{
|
||||
++eof;
|
||||
if (!lr.IsEOF())
|
||||
{
|
||||
buf[0] = (TCHAR) lrr;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
const bool unicode = lr.IsUnicode();
|
||||
for(cch = 0;; ++cch)
|
||||
{
|
||||
TCHAR ch = buf[cch];
|
||||
if (!ch || NStream::IsNewline(ch, unicode)) break;
|
||||
}
|
||||
if (cch) eof = 0; // Read something, postpone EOF
|
||||
return ++cch - eof;
|
||||
}
|
||||
|
||||
#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
|
||||
// Added by Sunil Kamath 11 June 2003
|
||||
TCHAR *CEXEBuild::set_file_predefine(const TCHAR *filename)
|
||||
|
@ -3064,34 +3089,33 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
} else if (!_tcsicmp(define,_T("/file")) || !_tcsicmp(define,_T("/file_noerr"))) {
|
||||
|
||||
if (line.getnumtokens()!=4) PRINTHELP()
|
||||
|
||||
define=line.gettoken_str(2);
|
||||
const TCHAR *filename=line.gettoken_str(3);
|
||||
FILE *fp=FOPENTEXT(filename,"r");
|
||||
|
||||
if (!fp && _tcsicmp(define,_T("/file_noerr"))) {
|
||||
ERROR_MSG(_T("!define /file: file not found (\"%s\")\n"),filename);
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
TCHAR *str=m_templinebuf;
|
||||
for (;;) {
|
||||
TCHAR *p=str;
|
||||
*p=0;
|
||||
_fgetts(str,MAX_LINELENGTH,fp);
|
||||
linecnt++;
|
||||
if (feof(fp)&&!str[0]) break;
|
||||
|
||||
while (*p) p++;
|
||||
if (p > str) p--;
|
||||
while (p >= str && (*p == _T('\r') || *p == _T('\n'))) p--;
|
||||
*++p=0;
|
||||
if (file_buf.getlen()) file_buf.add(_T("\n"),1);
|
||||
file_buf.add(str,_tcslen(str));
|
||||
const TCHAR *const filename=line.gettoken_str(3), *const swit=define;
|
||||
NIStream filestrm;
|
||||
if (!filestrm.OpenFileForReading(filename)) {
|
||||
if (!swit[5]) { // "/file" vs "/file_noerr"
|
||||
ERROR_MSG(_T("!define /file: file not found (\"%s\")\n"),filename);
|
||||
return PS_ERROR;
|
||||
}
|
||||
} else {
|
||||
NStreamLineReader lr(filestrm);
|
||||
TCHAR *str=m_templinebuf;
|
||||
for (UINT linnum = 0;;) {
|
||||
++linnum;
|
||||
UINT cch=read_line_helper(lr,str,MAX_LINELENGTH);
|
||||
if (!cch) {
|
||||
if (*str) {
|
||||
tstring lrmsg=lr.GetErrorMessage((UINT)*str,filename,linnum);
|
||||
ERROR_MSG(_T("!define %s: %s"),swit,lrmsg.c_str());
|
||||
return PS_ERROR;
|
||||
}
|
||||
break; // EOF
|
||||
}
|
||||
str[--cch]=_T('\0'); // Remove \r or \n, we always append \n
|
||||
if (file_buf.getlen()) file_buf.add(_T("\n"),sizeof(TCHAR));
|
||||
file_buf.add(str,cch*sizeof(TCHAR));
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
define = line.gettoken_str(2);
|
||||
file_buf.add(_T("\0"),1);
|
||||
value = (TCHAR *)file_buf.get();
|
||||
|
||||
|
@ -3359,9 +3383,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
return PS_OK;
|
||||
case TOK_P_SEARCHPARSESTRING:
|
||||
{
|
||||
bool ignCase=false;
|
||||
bool noErrors=false;
|
||||
bool isFile=false;
|
||||
bool ignCase=false, noErrors=false, isFile=false;
|
||||
int parmOffs=1;
|
||||
while (parmOffs < line.getnumtokens())
|
||||
{
|
||||
|
@ -3381,34 +3403,40 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
|
||||
if (isFile)
|
||||
{
|
||||
FILE *fp=FOPENTEXT(source_string,"r");
|
||||
if (!fp)
|
||||
const TCHAR *const filename = source_string;
|
||||
NIStream filestrm;
|
||||
if (!filestrm.OpenFileForReading(filename))
|
||||
{
|
||||
ERROR_MSG(_T("!searchparse /file: error opening \"%s\"\n"),source_string);
|
||||
ERROR_MSG(_T("!searchparse /file: error opening \"%s\"\n"),filename);
|
||||
return PS_ERROR;
|
||||
}
|
||||
|
||||
int req_parm = (line.getnumtokens() - parmOffs)/2;
|
||||
|
||||
NStreamLineReader lr(filestrm);
|
||||
GrowBuf tmpstr;
|
||||
TCHAR *str=m_templinebuf;
|
||||
UINT linnum=0;
|
||||
for (;;)
|
||||
{
|
||||
tmpstr.resize(0);
|
||||
for (;;)
|
||||
{
|
||||
str[0]=0;
|
||||
_fgetts(str,MAX_LINELENGTH,fp);
|
||||
if (!str[0]) break; // eof
|
||||
++linnum;
|
||||
UINT cch=read_line_helper(lr,str,MAX_LINELENGTH);
|
||||
if (!cch)
|
||||
{
|
||||
if (*str)
|
||||
{
|
||||
tstring lrmsg=lr.GetErrorMessage((UINT)*str,filename,linnum);
|
||||
ERROR_MSG(_T("!searchparse: %s"),lrmsg.c_str());
|
||||
return PS_ERROR;
|
||||
}
|
||||
break; // EOF
|
||||
}
|
||||
str[--cch]=_T('\0'); // remove newline
|
||||
|
||||
TCHAR *p=str;
|
||||
while (*p) p++;
|
||||
if (p > str) p--;
|
||||
while (p >= str && (*p == _T('\r') || *p == _T('\n'))) p--;
|
||||
*++p=0;
|
||||
|
||||
bool endSlash = (str[0] && str[_tcslen(str)-1] == _T('\\'));
|
||||
if (tmpstr.getlen() || endSlash) tmpstr.add(str,sizeof(TCHAR)*_tcslen(str));
|
||||
const bool endSlash = cch && _T('\\') == str[cch-1];
|
||||
if (endSlash) --cch; // don't include the slash character
|
||||
if (tmpstr.getlen() || endSlash) tmpstr.add(str,cch*sizeof(TCHAR));
|
||||
|
||||
// if we have valid contents and not ending on slash, then done
|
||||
if (!endSlash && (str[0] || tmpstr.getlen())) break;
|
||||
|
@ -3436,7 +3464,6 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
}
|
||||
// parse line
|
||||
}
|
||||
fclose(fp);
|
||||
if (!noErrors)
|
||||
{
|
||||
if (!list)
|
||||
|
|
|
@ -387,23 +387,24 @@ tstring NStreamLineReader::GetErrorMessage(UINT Error, const TCHAR*Filename, UIN
|
|||
switch(Error)
|
||||
{
|
||||
case NStream::ERR_BUFFEROVERFLOW:
|
||||
msg = _T("Line too long: ");
|
||||
msg = _T("Line too long");
|
||||
break;
|
||||
case NStream::ERR_IOERROR:
|
||||
msg = _T("I/O error"), Filename = 0;
|
||||
msg = _T("I/O error"), Filename = 0;
|
||||
break;
|
||||
case NStream::ERR_UNSUPPORTEDENCODING:
|
||||
StreamEncoding().GetCPDisplayName(buf);
|
||||
msg = tstring(buf) + _T(" is not supported"), Filename = 0;
|
||||
break;
|
||||
default:
|
||||
msg = _T("Bad text encoding: ");
|
||||
msg = _T("Bad text encoding");
|
||||
break;
|
||||
}
|
||||
if (Filename)
|
||||
{
|
||||
_stprintf(buf,_T("%u"),Line);
|
||||
msg = msg + Filename + _T(":") + buf;
|
||||
const TCHAR *filelinesep = *Filename ? _T(":") : _T("");
|
||||
_stprintf(buf,_T("%s%u"),filelinesep,Line);
|
||||
msg = msg + _T(": ") + Filename + buf;
|
||||
}
|
||||
return msg + _T("\n");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue