Coverity #1099128, #1099549, #1099550 fixed
[scilab.git] / scilab / modules / completion / src / c / completeLine.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009-2010 - DIGITEO - Allan CORNET
4 * Copyright (C) 2010 - DIGITEO - Vincent LEJEUNE
5 * Copyright (C) 2011 - DIGITEO - Allan CORNET
6 *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15 *
16 */
17
18 /*--------------------------------------------------------------------------*/
19 #include <string.h>
20 #include <ctype.h>
21 #include "completeLine.h"
22 #include "sci_malloc.h"
23 #include "os_string.h"
24 #include "getPartLine.h"
25 #include "splitpath.h"
26 #include "PATH_MAX.h"
27 #include "stristr.h"
28
29 /*--------------------------------------------------------------------------*/
30 /*!  Get the position of the longest suffix of string that match with a prefix of find
31 *  @param[in] string  A string that has a suffix that match a prefix of find ; Assumed to be non null because of the first guard in completeLine
32 *  @param[in] find A string that has a prefix that match with a suffix of string
33 *  @return Position in string where suffix of string and prefix of find does match
34 *
35 */
36 static int findMatchingPrefixSuffix(const char* string, const char* find, BOOL stringToAddIsPath)
37 {
38     char* pointerOnString = NULL;
39     char* pointerOnFindCopy = NULL;
40     char* movingPointerOnFindCopy = NULL;
41     char lastchar;
42     size_t stringLength = 0;
43
44     //get a working copy of find
45     pointerOnFindCopy = os_strdup(find);
46     //last character of string
47     lastchar = *(string + strlen(string) - 1);
48     stringLength = strlen(string);
49
50     // Convert to upper-case
51     {
52         char* str;
53         for (str = pointerOnFindCopy; *str != '\0'; str++)
54         {
55             *str = toupper(*str);
56         }
57     }
58
59     //Tips : no infinite loop there, tmpfind string length is always reduced at each iteration
60     movingPointerOnFindCopy = strrchr(pointerOnFindCopy, toupper(lastchar));
61
62     while ( movingPointerOnFindCopy )
63     {
64         //find the last occurence of last char of string in tmpfind
65         movingPointerOnFindCopy = strrchr(pointerOnFindCopy, toupper(lastchar));
66         if (movingPointerOnFindCopy == NULL)
67         {
68             break;
69         }
70         // Cut tmpfind at this position
71         movingPointerOnFindCopy[0] = '\0';
72         //Check if the cutted tmpfind match with the suffix of string that has adequat length
73         pointerOnString = (char*)(string + stringLength - 1 - strlen(pointerOnFindCopy));
74         if ( !strnicmp(pointerOnFindCopy, pointerOnString, strlen(pointerOnFindCopy)) )
75         {
76             FREE(pointerOnFindCopy);
77             pointerOnFindCopy = NULL;
78             return (int)(pointerOnString - string);
79         }
80
81     }
82     //if no return, no position is correct, return last char of string.
83     FREE(pointerOnFindCopy);
84     pointerOnFindCopy = NULL;
85     return (int)stringLength;
86 }
87 /*--------------------------------------------------------------------------*/
88 char *completeLine(char *currentline, char *stringToAdd, char *filePattern,
89                    char *defaultPattern, BOOL stringToAddIsPath, char *postCaretLine)
90 {
91     char *new_line = NULL;
92     int lengthNewLine = 0;
93
94     char *stringToAddAtTheEnd = NULL;
95     int lenstringToAddAtTheEnd = 0;
96
97     char *res = NULL;
98
99     int lencurrentline = 0;
100
101     int iposInsert = 0;
102
103     if (currentline == NULL)
104     {
105         return  os_strdup("");
106     }
107     lencurrentline = (int)strlen(currentline);
108
109     if (postCaretLine == NULL)
110     {
111         stringToAddAtTheEnd = os_strdup("");
112         lenstringToAddAtTheEnd = (int)strlen(stringToAddAtTheEnd);
113     }
114     else
115     {
116         stringToAddAtTheEnd = os_strdup(postCaretLine);
117         lenstringToAddAtTheEnd = (int)strlen(stringToAddAtTheEnd);
118     }
119
120     if ( (stringToAdd == NULL)  || (strcmp(stringToAdd, "") == 0) )
121     {
122         lengthNewLine = lencurrentline + lenstringToAddAtTheEnd;
123         new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
124         if (new_line)
125         {
126             strcpy(new_line, currentline);
127             strcat(new_line, stringToAddAtTheEnd);
128         }
129
130         FREE(stringToAddAtTheEnd);
131         stringToAddAtTheEnd = NULL;
132
133         return new_line;
134     }
135
136     if (stringToAddIsPath == FALSE)
137     {
138         char *filePatternBuf = NULL;
139         BOOL bfilePatternBuf = FALSE;
140
141         if (filePattern != NULL)
142         {
143             filePatternBuf = filePattern;
144         }
145         else
146         {
147             filePatternBuf = getFilePartLevel(currentline);
148             bfilePatternBuf = TRUE;
149         }
150
151         if (filePatternBuf)
152         {
153             char* drv = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
154             char* dir = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
155             char* name = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
156             char* ext = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
157
158             splitpath(filePatternBuf, TRUE, drv, dir, name, ext);
159
160             if (bfilePatternBuf)
161             {
162                 FREE(filePatternBuf);
163                 filePatternBuf = NULL;
164             }
165
166             if ( strcmp(drv, "") || strcmp(dir, "") )
167             {
168                 /* bug 4365 */
169                 /*cd SCI/modules/arnoldi/nonreg_tes */
170
171                 FREE(drv);
172                 drv = NULL;
173                 FREE(dir);
174                 dir = NULL;
175                 FREE(name);
176                 name = NULL;
177                 FREE(ext);
178                 ext = NULL;
179
180                 lengthNewLine = lencurrentline + lenstringToAddAtTheEnd;
181                 new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
182                 if (new_line)
183                 {
184                     strcpy(new_line, currentline);
185                     strcat(new_line, stringToAddAtTheEnd);
186                 }
187
188                 FREE(stringToAddAtTheEnd);
189                 stringToAddAtTheEnd = NULL;
190
191                 return new_line;
192             }
193
194             FREE(drv);
195             drv = NULL;
196             FREE(dir);
197             dir = NULL;
198             FREE(name);
199             name = NULL;
200             FREE(ext);
201             ext = NULL;
202         }
203     }
204
205     // Does the end of line (currentLine) matches the beginning of completed word (stringToAdd) ?
206     iposInsert = findMatchingPrefixSuffix(currentline, stringToAdd, stringToAddIsPath);
207     res = stristr(stringToAdd, &currentline[iposInsert]);
208
209     if (res == NULL)
210     {
211         // No, find the last occurence of completed word word in line
212         char* foundCompletedWordPtr = NULL;
213         char* nextFoundCompletedWordPtr = stristr(currentline, stringToAdd);
214         while (nextFoundCompletedWordPtr)
215         {
216             foundCompletedWordPtr = nextFoundCompletedWordPtr;
217             nextFoundCompletedWordPtr =
218                 stristr(foundCompletedWordPtr + strlen(foundCompletedWordPtr), stringToAdd);
219         }
220
221         if (foundCompletedWordPtr)
222         {
223             iposInsert = (int) (foundCompletedWordPtr - currentline);
224         }
225     }
226
227     // if it is a path, we add at the end
228     if ((currentline[lencurrentline - 1] == '/') || (currentline[lencurrentline - 1] == '\\'))
229     {
230         iposInsert = lencurrentline;
231     }
232
233     lengthNewLine = (int)(strlen(currentline) + strlen(stringToAdd) + lenstringToAddAtTheEnd);
234     new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
235     if (new_line)
236     {
237         strcpy(new_line, currentline);
238         new_line[iposInsert] = 0;
239
240         strcat(new_line, stringToAdd);
241         strcat(new_line, stringToAddAtTheEnd);
242     }
243
244     FREE(stringToAddAtTheEnd);
245     stringToAddAtTheEnd = NULL;
246
247     return new_line;
248 }
249 /*--------------------------------------------------------------------------*/