#include "ver.h"\r
\r
#define CUSTOM_ACTION_TYPE_MASK 0x3F\r
+#define REG_PROGRESS_VALUE 13200\r
+#define COMPONENT_PROGRESS_VALUE 24000\r
\r
WINE_DEFAULT_DEBUG_CHANNEL(msi);\r
\r
WCHAR Directory[96];\r
INT Attributes;\r
\r
- INSTALLSTATE State;\r
- BOOL Enabled;\r
+ INSTALLSTATE Installed;\r
+ INSTALLSTATE ActionRequest;\r
+ INSTALLSTATE Action;\r
+\r
INT ComponentCount;\r
INT Components[1024]; /* yes hardcoded limit.... I am bad */\r
INT Cost;\r
WCHAR Condition[0x100];\r
WCHAR KeyPath[96];\r
\r
- INSTALLSTATE State;\r
- BOOL FeatureState;\r
+ INSTALLSTATE Installed;\r
+ INSTALLSTATE ActionRequest;\r
+ INSTALLSTATE Action;\r
+\r
BOOL Enabled;\r
INT Cost;\r
} MSICOMPONENT;\r
\r
typedef struct tagMSIFOLDER\r
{\r
- WCHAR Directory[96];\r
- WCHAR TargetDefault[96];\r
- WCHAR SourceDefault[96];\r
+ LPWSTR Directory;\r
+ LPWSTR TargetDefault;\r
+ LPWSTR SourceDefault;\r
\r
- WCHAR ResolvedTarget[MAX_PATH];\r
- WCHAR ResolvedSource[MAX_PATH];\r
- WCHAR Property[MAX_PATH]; /* initially set property */\r
+ LPWSTR ResolvedTarget;\r
+ LPWSTR ResolvedSource;\r
+ LPWSTR Property; /* initially set property */\r
INT ParentIndex;\r
INT State;\r
/* 0 = uninitialized */\r
\r
typedef struct tagMSIFILE\r
{\r
- WCHAR File[72];\r
+ LPWSTR File;\r
INT ComponentIndex;\r
- WCHAR FileName[MAX_PATH];\r
+ LPWSTR FileName;\r
INT FileSize;\r
- WCHAR Version[72];\r
- WCHAR Language[20];\r
+ LPWSTR Version;\r
+ LPWSTR Language;\r
INT Attributes;\r
INT Sequence; \r
\r
/* 2 = present but replace */\r
/* 3 = present do not replace */\r
/* 4 = Installed */\r
- WCHAR SourcePath[MAX_PATH];\r
- WCHAR TargetPath[MAX_PATH];\r
+ LPWSTR SourcePath;\r
+ LPWSTR TargetPath;\r
BOOL Temporary; \r
}MSIFILE;\r
\r
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);\r
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);\r
\r
+static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq);\r
UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action);\r
\r
static UINT ACTION_LaunchConditions(MSIPACKAGE *package);\r
const LPWSTR target, const INT type);\r
static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, \r
const LPWSTR target, const INT type);\r
-static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, \r
+static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source,\r
const LPWSTR target, const INT type);\r
-static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, \r
+static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source,\r
const LPWSTR target, const INT type);\r
-static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, \r
+static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source,\r
const LPWSTR target, const INT type);\r
\r
static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data);\r
-static UINT resolve_folder(MSIPACKAGE *package, LPCWSTR name, LPWSTR path, \r
+static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name,\r
BOOL source, BOOL set_prop, MSIFOLDER **folder);\r
\r
static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);\r
********************************************************/\r
inline static void reduce_to_longfilename(WCHAR* filename)\r
{\r
- if (strchrW(filename,'|'))\r
- {\r
- WCHAR newname[MAX_PATH];\r
- strcpyW(newname,strchrW(filename,'|')+1);\r
- strcpyW(filename,newname);\r
- }\r
+ LPWSTR p = strchrW(filename,'|');\r
+ if (p)\r
+ memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR));\r
}\r
\r
inline static char *strdupWtoA( const WCHAR *str )\r
return ret;\r
}\r
\r
+static LPWSTR dupstrW(LPCWSTR src)\r
+{\r
+ LPWSTR dest;\r
+ if (!src) return NULL;\r
+ dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR));\r
+ strcpyW(dest, src);\r
+ return dest;\r
+}\r
+\r
inline static WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index)\r
{\r
UINT rc;\r
LPWSTR ret;\r
\r
sz = 0; \r
- rc = MSI_RecordGetStringW(row,index,NULL,&sz);\r
- if (sz <= 0)\r
+ if (MSI_RecordIsNull(row,index))\r
return NULL;\r
\r
+ rc = MSI_RecordGetStringW(row,index,NULL,&sz);\r
+\r
+ /* having an empty string is different than NULL */\r
+ if (sz == 0)\r
+ {\r
+ ret = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR));\r
+ ret[0] = 0;\r
+ return ret;\r
+ }\r
+\r
sz ++;\r
ret = HeapAlloc(GetProcessHeap(),0,sz * sizeof (WCHAR));\r
rc = MSI_RecordGetStringW(row,index,ret,&sz);\r
+ if (rc!=ERROR_SUCCESS)\r
+ {\r
+ ERR("Unable to load dynamic string\n");\r
+ HeapFree(GetProcessHeap(), 0, ret);\r
+ ret = NULL;\r
+ }\r
return ret;\r
}\r
\r
+inline static LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop,\r
+ UINT* rc)\r
+{\r
+ DWORD sz = 0;\r
+ LPWSTR str;\r
+ UINT r;\r
+\r
+ r = MSI_GetPropertyW(package, prop, NULL, &sz);\r
+ if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)\r
+ {\r
+ if (rc)\r
+ *rc = r;\r
+ return NULL;\r
+ }\r
+ sz++;\r
+ str = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));\r
+ r = MSI_GetPropertyW(package, prop, str, &sz);\r
+ if (r != ERROR_SUCCESS)\r
+ {\r
+ HeapFree(GetProcessHeap(),0,str);\r
+ str = NULL;\r
+ }\r
+ if (rc)\r
+ *rc = r;\r
+ return str;\r
+}\r
+\r
inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )\r
{\r
int rc = -1;\r
return rc;\r
}\r
\r
+\r
static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path)\r
{\r
DWORD i;\r
\r
memset(&package->files[index],0,sizeof(MSIFILE));\r
\r
- strcpyW(package->files[index].File,name);\r
- strcpyW(package->files[index].TargetPath,path);\r
+ package->files[index].File = dupstrW(name);\r
+ package->files[index].TargetPath = dupstrW(path);\r
package->files[index].Temporary = TRUE;\r
\r
TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File)); \r
for (i = 0; i < package->loaded_files; i++)\r
{\r
if (package->files[i].Temporary)\r
+ {\r
+ TRACE("Cleaning up %s\n",debugstr_w(package->files[i].TargetPath));\r
DeleteFileW(package->files[i].TargetPath);\r
+ }\r
\r
}\r
}\r
\r
+/* Called when the package is being closed */\r
+extern void ACTION_free_package_structures( MSIPACKAGE* package)\r
+{\r
+ INT i;\r
+ \r
+ TRACE("Freeing package action data\n");\r
+\r
+ /* No dynamic buffers in features */\r
+ if (package->features && package->loaded_features > 0)\r
+ HeapFree(GetProcessHeap(),0,package->features);\r
+\r
+ for (i = 0; i < package->loaded_folders; i++)\r
+ {\r
+ HeapFree(GetProcessHeap(),0,package->folders[i].Directory);\r
+ HeapFree(GetProcessHeap(),0,package->folders[i].TargetDefault);\r
+ HeapFree(GetProcessHeap(),0,package->folders[i].SourceDefault);\r
+ HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);\r
+ HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedSource);\r
+ HeapFree(GetProcessHeap(),0,package->folders[i].Property);\r
+ }\r
+ if (package->folders && package->loaded_folders > 0)\r
+ HeapFree(GetProcessHeap(),0,package->folders);\r
+\r
+ /* no dynamic buffers in components */ \r
+ if (package->components && package->loaded_components > 0)\r
+ HeapFree(GetProcessHeap(),0,package->components);\r
+\r
+ for (i = 0; i < package->loaded_files; i++)\r
+ {\r
+ HeapFree(GetProcessHeap(),0,package->files[i].File);\r
+ HeapFree(GetProcessHeap(),0,package->files[i].FileName);\r
+ HeapFree(GetProcessHeap(),0,package->files[i].Version);\r
+ HeapFree(GetProcessHeap(),0,package->files[i].Language);\r
+ HeapFree(GetProcessHeap(),0,package->files[i].SourcePath);\r
+ HeapFree(GetProcessHeap(),0,package->files[i].TargetPath);\r
+ }\r
+\r
+ if (package->files && package->loaded_files > 0)\r
+ HeapFree(GetProcessHeap(),0,package->files);\r
+}\r
+\r
+static UINT ACTION_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... )\r
+{\r
+ LPWSTR szQuery;\r
+ LPCWSTR p;\r
+ UINT sz, rc;\r
+ va_list va;\r
+\r
+ /* figure out how much space we need to allocate */\r
+ va_start(va, fmt);\r
+ sz = strlenW(fmt) + 1;\r
+ p = fmt;\r
+ while (*p)\r
+ {\r
+ p = strchrW(p, '%');\r
+ if (!p)\r
+ break;\r
+ p++;\r
+ switch (*p)\r
+ {\r
+ case 's': /* a string */\r
+ sz += strlenW(va_arg(va,LPCWSTR));\r
+ break;\r
+ case 'd':\r
+ case 'i': /* an integer -2147483648 seems to be longest */\r
+ sz += 3*sizeof(int);\r
+ (void)va_arg(va,int);\r
+ break;\r
+ case '%': /* a single % - leave it alone */\r
+ break;\r
+ default:\r
+ FIXME("Unhandled character type %c\n",*p);\r
+ }\r
+ p++;\r
+ }\r
+ va_end(va);\r
+\r
+ /* construct the string */\r
+ szQuery = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));\r
+ va_start(va, fmt);\r
+ vsnprintfW(szQuery, sz, fmt, va);\r
+ va_end(va);\r
+\r
+ /* perform the query */\r
+ rc = MSI_DatabaseOpenViewW(db, szQuery, view);\r
+ HeapFree(GetProcessHeap(), 0, szQuery);\r
+ return rc;\r
+}\r
+\r
static void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d )\r
{\r
MSIRECORD * row;\r
UINT rc;\r
MSIQUERY * view;\r
MSIRECORD * row = 0;\r
- static WCHAR *ActionFormat=NULL;\r
- static WCHAR LastAction[0x100] = {0};\r
- WCHAR Query[1024];\r
LPWSTR ptr;\r
\r
- if (strcmpW(LastAction,action)!=0)\r
+ if (!package->LastAction || strcmpW(package->LastAction,action))\r
{\r
- sprintfW(Query,Query_t,action);\r
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);\r
+ rc = ACTION_OpenQuery(package->db, &view, Query_t, action);\r
if (rc != ERROR_SUCCESS)\r
return;\r
+\r
rc = MSI_ViewExecute(view, 0);\r
if (rc != ERROR_SUCCESS)\r
{\r
return;\r
}\r
\r
- if (ActionFormat)\r
- HeapFree(GetProcessHeap(),0,ActionFormat);\r
+ /* update the cached actionformat */\r
+ if (package->ActionFormat)\r
+ HeapFree(GetProcessHeap(),0,package->ActionFormat);\r
+ package->ActionFormat = load_dynamic_stringW(row,3);\r
+\r
+ if (package->LastAction)\r
+ HeapFree(GetProcessHeap(),0,package->LastAction);\r
+ package->LastAction = dupstrW(action);\r
\r
- ActionFormat = load_dynamic_stringW(row,3);\r
- strcpyW(LastAction,action);\r
msiobj_release(&row->hdr);\r
MSI_ViewClose(view);\r
msiobj_release(&view->hdr);\r
}\r
\r
message[0]=0;\r
- ptr = ActionFormat;\r
+ ptr = package->ActionFormat;\r
while (*ptr)\r
{\r
LPWSTR ptr2;\r
MSIQUERY * view;\r
MSIRECORD * row = 0;\r
WCHAR *ActionText=NULL;\r
- WCHAR Query[1024];\r
\r
GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);\r
\r
- sprintfW(Query,Query_t,action);\r
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);\r
+ rc = ACTION_OpenQuery(package->db, &view, Query_t, action);\r
if (rc != ERROR_SUCCESS)\r
return;\r
rc = MSI_ViewExecute(view, 0);\r
msiobj_release(&row->hdr);\r
}\r
\r
+/*\r
+ * build_directory_name()\r
+ *\r
+ * This function is to save messing round with directory names\r
+ * It handles adding backslashes between path segments, \r
+ * and can add \ at the end of the directory name if told to.\r
+ *\r
+ * It takes a variable number of arguments.\r
+ * It always allocates a new string for the result, so make sure\r
+ * to free the return value when finished with it.\r
+ *\r
+ * The first arg is the number of path segments that follow.\r
+ * The arguments following count are a list of path segments.\r
+ * A path segment may be NULL.\r
+ *\r
+ * Path segments will be added with a \ separating them.\r
+ * A \ will not be added after the last segment, however if the\r
+ * last segment is NULL, then the last character will be a \\r
+ * \r
+ */\r
+static LPWSTR build_directory_name(DWORD count, ...)\r
+{\r
+ DWORD sz = 1, i;\r
+ LPWSTR dir;\r
+ va_list va;\r
+\r
+ va_start(va,count);\r
+ for(i=0; i<count; i++)\r
+ {\r
+ LPCWSTR str = va_arg(va,LPCWSTR);\r
+ if (str)\r
+ sz += strlenW(str) + 1;\r
+ }\r
+ va_end(va);\r
+\r
+ dir = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));\r
+ dir[0]=0;\r
+\r
+ va_start(va,count);\r
+ for(i=0; i<count; i++)\r
+ {\r
+ LPCWSTR str = va_arg(va,LPCWSTR);\r
+ if (!str)\r
+ continue;\r
+ strcatW(dir, str);\r
+ if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')\r
+ strcatW(dir, cszbs);\r
+ }\r
+ return dir;\r
+}\r
+\r
+\r
/****************************************************\r
* TOP level entry points \r
*****************************************************/\r
\r
if (szPackagePath) \r
{\r
- LPWSTR p;\r
- WCHAR check[MAX_PATH];\r
- WCHAR pth[MAX_PATH];\r
- DWORD size;\r
+ LPWSTR p, check, path;\r
\r
- strcpyW(pth,szPackagePath);\r
- p = strrchrW(pth,'\\'); \r
+ path = dupstrW(szPackagePath);\r
+ p = strrchrW(path,'\\'); \r
if (p)\r
{\r
p++;\r
*p=0;\r
}\r
\r
- size = MAX_PATH;\r
- if (MSI_GetPropertyW(package,cszSourceDir,check,&size) \r
- != ERROR_SUCCESS )\r
- MSI_SetPropertyW(package, cszSourceDir, pth);\r
+ check = load_dynamic_property(package, cszSourceDir,NULL);\r
+ if (!check)\r
+ MSI_SetPropertyW(package, cszSourceDir, path);\r
+ else\r
+ HeapFree(GetProcessHeap(), 0, check);\r
+\r
+ HeapFree(GetProcessHeap(), 0, path);\r
}\r
\r
if (szCommandLine)\r
\r
while (*ptr)\r
{\r
- WCHAR prop[0x100];\r
- WCHAR val[0x100];\r
+ WCHAR *prop = NULL;\r
+ WCHAR *val = NULL;\r
\r
TRACE("Looking at %s\n",debugstr_w(ptr));\r
\r
DWORD len = 0;\r
\r
while (*ptr == ' ') ptr++;\r
- strncpyW(prop,ptr,ptr2-ptr);\r
- prop[ptr2-ptr]=0;\r
+ len = ptr2-ptr;\r
+ prop = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));\r
+ strncpyW(prop,ptr,len);\r
+ prop[len]=0;\r
ptr2++;\r
- \r
+ \r
+ len = 0; \r
ptr = ptr2; \r
while (*ptr && (quote || (!quote && *ptr!=' ')))\r
{\r
ptr2++;\r
len -= 2;\r
}\r
+ val = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));\r
strncpyW(val,ptr2,len);\r
- val[len]=0;\r
+ val[len] = 0;\r
\r
if (strlenW(prop) > 0)\r
{\r
- TRACE("Found commandline property (%s) = (%s)\n", debugstr_w(prop), debugstr_w(val));\r
+ TRACE("Found commandline property (%s) = (%s)\n", \r
+ debugstr_w(prop), debugstr_w(val));\r
MSI_SetPropertyW(package,prop,val);\r
}\r
+ HeapFree(GetProcessHeap(),0,val);\r
+ HeapFree(GetProcessHeap(),0,prop);\r
}\r
ptr++;\r
}\r
else\r
rc = ACTION_ProcessExecSequence(package,FALSE);\r
\r
+ /* process the ending type action */\r
+ if (rc == ERROR_SUCCESS)\r
+ rc = ACTION_PerformActionSequence(package,-1);\r
+ else if (rc == ERROR_FUNCTION_FAILED) \r
+ rc = ACTION_PerformActionSequence(package,-3);\r
+ \r
return rc;\r
}\r
\r
+static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq)\r
+{\r
+ MSIQUERY * view;\r
+ UINT rc;\r
+ WCHAR buffer[0x100];\r
+ DWORD sz = 0x100;\r
+ MSIRECORD * row = 0;\r
+ static const WCHAR ExecSeqQuery[] = {\r
+ 's','e','l','e','c','t',' ','*',' ',\r
+ 'f','r','o','m',' ',\r
+ 'I','n','s','t','a','l','l','E','x','e','c','u','t','e',\r
+ 'S','e','q','u','e','n','c','e',' ',\r
+ 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',\r
+ '=',' ','%','i',0};\r
+\r
+ rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq);\r
+\r
+ if (rc == ERROR_SUCCESS)\r
+ {\r
+ rc = MSI_ViewExecute(view, 0);\r
+\r
+ if (rc != ERROR_SUCCESS)\r
+ {\r
+ MSI_ViewClose(view);\r
+ msiobj_release(&view->hdr);\r
+ goto end;\r
+ }\r
+ \r
+ TRACE("Running the actions\n"); \r
+\r
+ rc = MSI_ViewFetch(view,&row);\r
+ if (rc != ERROR_SUCCESS)\r
+ {\r
+ rc = ERROR_SUCCESS;\r
+ goto end;\r
+ }\r
+\r
+ /* check conditions */\r
+ if (!MSI_RecordIsNull(row,2))\r
+ {\r
+ LPWSTR cond = NULL;\r
+ cond = load_dynamic_stringW(row,2);\r
+\r
+ if (cond)\r
+ {\r
+ /* this is a hack to skip errors in the condition code */\r
+ if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)\r
+ {\r
+ HeapFree(GetProcessHeap(),0,cond);\r
+ msiobj_release(&row->hdr);\r
+ goto end;\r
+ }\r
+ else\r
+ HeapFree(GetProcessHeap(),0,cond);\r
+ }\r
+ }\r
+\r
+ sz=0x100;\r
+ rc = MSI_RecordGetStringW(row,1,buffer,&sz);\r
+ if (rc != ERROR_SUCCESS)\r
+ {\r
+ ERR("Error is %x\n",rc);\r
+ msiobj_release(&row->hdr);\r
+ goto end;\r
+ }\r
+\r
+ rc = ACTION_PerformAction(package,buffer);\r
+ msiobj_release(&row->hdr);\r
+end:\r
+ MSI_ViewClose(view);\r
+ msiobj_release(&view->hdr);\r
+ }\r
+ else\r
+ rc = ERROR_SUCCESS;\r
+\r
+ return rc;\r
+}\r
\r
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)\r
{\r
'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',\r
'>',' ','%','i',' ','o','r','d','e','r',' ',\r
'b','y',' ','S','e','q','u','e','n','c','e',0 };\r
- WCHAR Query[1024];\r
MSIRECORD * row = 0;\r
static const WCHAR IVQuery[] = {\r
's','e','l','e','c','t',' ','S','e','q','u','e','n','c','e',' ',\r
'w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',' ',\r
'`','I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`',\r
0};\r
+ INT seq = 0;\r
\r
+ /* get the sequence number */\r
if (UIran)\r
{\r
- INT seq = 0;\r
- \r
rc = MSI_DatabaseOpenViewW(package->db, IVQuery, &view);\r
if (rc != ERROR_SUCCESS)\r
return rc;\r
msiobj_release(&row->hdr);\r
MSI_ViewClose(view);\r
msiobj_release(&view->hdr);\r
- sprintfW(Query,ExecSeqQuery,seq);\r
}\r
- else\r
- sprintfW(Query,ExecSeqQuery,0);\r
- \r
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);\r
+\r
+ rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq);\r
if (rc == ERROR_SUCCESS)\r
{\r
rc = MSI_ViewExecute(view, 0);\r
goto end;\r
}\r
\r
- TRACE("Running the actions \n"); \r
+ TRACE("Running the actions\n"); \r
\r
while (1)\r
{\r
TRACE("Performing action (%s)\n",debugstr_w(action));\r
ui_actioninfo(package, action, TRUE, 0);\r
ui_actionstart(package, action);\r
- ui_progress(package,2,1,0,0);\r
\r
/* pre install, setup and configuration block */\r
if (strcmpW(action,szLaunchConditions)==0)\r
UINT rc = ERROR_SUCCESS;\r
MSIQUERY * view;\r
MSIRECORD * row = 0;\r
- WCHAR ExecSeqQuery[1024] = \r
+ static const WCHAR ExecSeqQuery[] =\r
{'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','C','u','s','t','o'\r
-,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i'\r
-,'o','n','`',' ','=',' ','`',0};\r
- static const WCHAR end[]={'`',0};\r
+ ,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i'\r
+ ,'o','n','`',' ','=',' ','`','%','s','`',0};\r
UINT type;\r
LPWSTR source;\r
LPWSTR target;\r
WCHAR *deformated=NULL;\r
\r
- strcatW(ExecSeqQuery,action);\r
- strcatW(ExecSeqQuery,end);\r
-\r
- rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);\r
-\r
+ rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, action);\r
if (rc != ERROR_SUCCESS)\r
return rc;\r
\r
rc = HANDLE_CustomType34(package,source,target,type);\r
break;\r
case 35: /* Directory set with formatted text. */\r
+ deformat_string(package,target,&deformated);\r
+ MSI_SetTargetPathW(package, source, deformated);\r
+ HeapFree(GetProcessHeap(),0,deformated);\r
+ break;\r
case 51: /* Property set with formatted text. */\r
deformat_string(package,target,&deformated);\r
rc = MSI_SetPropertyW(package,source,deformated);\r
UINT rc;\r
MSIQUERY * view;\r
MSIRECORD * row = 0;\r
- WCHAR Query[1024] =\r
+ static const WCHAR fmt[] =\r
{'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','B','i'\r
-,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`',0};\r
- static const WCHAR end[]={'`',0};\r
+,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`','%','s','`',0};\r
HANDLE the_file;\r
CHAR buffer[1024];\r
\r
if (the_file == INVALID_HANDLE_VALUE)\r
return ERROR_FUNCTION_FAILED;\r
\r
- strcatW(Query,source);\r
- strcatW(Query,end);\r
-\r
- rc = MSI_DatabaseOpenViewW( package->db, Query, &view);\r
+ rc = ACTION_OpenQuery(package->db, &view, fmt, source);\r
if (rc != ERROR_SUCCESS)\r
return rc;\r
\r
return ERROR_SUCCESS;\r
}\r
\r
-\r
typedef UINT __stdcall CustomEntry(MSIHANDLE);\r
typedef struct \r
{\r
MSIPACKAGE *package;\r
- WCHAR target[MAX_PATH];\r
- WCHAR source[MAX_PATH];\r
+ WCHAR *target;\r
+ WCHAR *source;\r
} thread_struct;\r
\r
-#if 0\r
-static DWORD WINAPI DllThread(LPVOID info)\r
+static DWORD WINAPI ACTION_CallDllFunction(thread_struct *stuff)\r
{\r
- HANDLE DLL;\r
+ HANDLE hModule;\r
LPSTR proc;\r
- thread_struct *stuff;\r
CustomEntry *fn;\r
- \r
- stuff = (thread_struct*)info;\r
\r
- TRACE("Asynchronous start (%s, %s) \n", debugstr_w(stuff->source),\r
+ TRACE("calling function (%s, %s) \n", debugstr_w(stuff->source),\r
debugstr_w(stuff->target));\r
\r
- DLL = LoadLibraryW(stuff->source);\r
- if (DLL)\r
+ hModule = LoadLibraryW(stuff->source);\r
+ if (hModule)\r
{\r
proc = strdupWtoA( stuff->target );\r
- fn = (CustomEntry*)GetProcAddress(DLL,proc);\r
+ fn = (CustomEntry*)GetProcAddress(hModule,proc);\r
if (fn)\r
{\r
MSIHANDLE hPackage;\r
MSIPACKAGE *package = stuff->package;\r
\r
- TRACE("Calling function\n");\r
+ TRACE("Calling function %s\n", proc);\r
hPackage = msiobj_findhandle( &package->hdr );\r
- if( !hPackage )\r
+ if (hPackage )\r
+ {\r
+ fn(hPackage);\r
+ msiobj_release( &package->hdr );\r
+ }\r
+ else\r
ERR("Handle for object %p not found\n", package );\r
- fn(hPackage);\r
- msiobj_release( &package->hdr );\r
}\r
else\r
ERR("Cannot load functon\n");\r
\r
HeapFree(GetProcessHeap(),0,proc);\r
- FreeLibrary(DLL);\r
+ FreeLibrary(hModule);\r
}\r
else\r
ERR("Unable to load library\n");\r
msiobj_release( &stuff->package->hdr );\r
- HeapFree( GetProcessHeap(), 0, info );\r
+ HeapFree(GetProcessHeap(),0,stuff->source);\r
+ HeapFree(GetProcessHeap(),0,stuff->target);\r
+ HeapFree(GetProcessHeap(), 0, stuff);\r
return 0;\r
}\r
-#endif\r
+\r
+static DWORD WINAPI DllThread(LPVOID info)\r
+{\r
+ thread_struct *stuff;\r
+ DWORD rc = 0;\r
+ \r
+ TRACE("MSI Thread (0x%lx) started for custom action\n",\r
+ GetCurrentThreadId());\r
+ \r
+ stuff = (thread_struct*)info;\r
+ rc = ACTION_CallDllFunction(stuff);\r
+\r
+ TRACE("MSI Thread (0x%lx) finished\n",GetCurrentThreadId());\r
+ /* clse all handles for this thread */\r
+ MsiCloseAllHandles();\r
+ return rc;\r
+}\r
\r
static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, \r
const LPWSTR target, const INT type)\r
{\r
WCHAR tmp_file[MAX_PATH];\r
- CustomEntry *fn;\r
- HANDLE DLL;\r
- LPSTR proc;\r
+ thread_struct *info;\r
+ DWORD ThreadId;\r
+ HANDLE ThreadHandle;\r
\r
store_binary_to_temp(package, source, tmp_file);\r
\r
strcatW(tmp_file,dot);\r
} \r
\r
- if (type & 0xc0)\r
- {\r
- /* DWORD ThreadId; */\r
- thread_struct *info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );\r
-\r
- /* msiobj_addref( &package->hdr ); */\r
- info->package = package;\r
- strcpyW(info->target,target);\r
- strcpyW(info->source,tmp_file);\r
- TRACE("Start Asynchronous execution\n");\r
- FIXME("DATABASE NOT THREADSAFE... not starting\n");\r
- /* CreateThread(NULL,0,DllThread,(LPVOID)&info,0,&ThreadId); */\r
- /* FIXME: release the package if the CreateThread fails */\r
- HeapFree( GetProcessHeap(), 0, info );\r
- return ERROR_SUCCESS;\r
- }\r
- \r
- DLL = LoadLibraryW(tmp_file);\r
- if (DLL)\r
- {\r
- proc = strdupWtoA( target );\r
- fn = (CustomEntry*)GetProcAddress(DLL,proc);\r
- if (fn)\r
- {\r
- MSIHANDLE hPackage;\r
+ info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );\r
+ msiobj_addref( &package->hdr );\r
+ info->package = package;\r
+ info->target = dupstrW(target);\r
+ info->source = dupstrW(tmp_file);\r
\r
- TRACE("Calling function\n");\r
- hPackage = msiobj_findhandle( &package->hdr );\r
- if( !hPackage )\r
- ERR("Handle for object %p not found\n", package );\r
- fn(hPackage);\r
- msiobj_release( &package->hdr );\r
- }\r
- else\r
- ERR("Cannot load functon\n");\r
+ ThreadHandle = CreateThread(NULL,0,DllThread,(LPVOID)info,0,&ThreadId);\r
\r
- HeapFree(GetProcessHeap(),0,proc);\r
- FreeLibrary(DLL);\r
- }\r
- else\r
- ERR("Unable to load library\n");\r
+ if (!(type & 0xc0))\r
+ WaitForSingleObject(ThreadHandle,INFINITE);\r
\r
+ CloseHandle(ThreadHandle);\r
+ \r
return ERROR_SUCCESS;\r
}\r
\r
static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, \r
const LPWSTR target, const INT type)\r
{\r
- WCHAR tmp_file[MAX_PATH*2];\r
+ WCHAR tmp_file[MAX_PATH];\r
STARTUPINFOW si;\r
PROCESS_INFORMATION info;\r
BOOL rc;\r
+ INT len;\r
WCHAR *deformated;\r
+ WCHAR *cmd;\r
static const WCHAR spc[] = {' ',0};\r
\r
memset(&si,0,sizeof(STARTUPINFOW));\r
\r
store_binary_to_temp(package, source, tmp_file);\r
\r
- strcatW(tmp_file,spc);\r
deformat_string(package,target,&deformated);\r
- strcatW(tmp_file,deformated);\r
+\r
+ len = strlenW(tmp_file) + strlenW(deformated) + 2;\r
+ \r
+ cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len);\r
+\r
+ strcpyW(cmd,tmp_file);\r
+ strcatW(cmd,spc);\r
+ strcatW(cmd,deformated);\r
\r
HeapFree(GetProcessHeap(),0,deformated);\r
\r
- TRACE("executing exe %s \n",debugstr_w(tmp_file));\r
+ TRACE("executing exe %s \n",debugstr_w(cmd));\r
\r
- rc = CreateProcessW(NULL, tmp_file, NULL, NULL, FALSE, 0, NULL,\r
+ rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,\r
c_collen, &si, &info);\r
\r
+ HeapFree(GetProcessHeap(),0,cmd);\r
+\r
if ( !rc )\r
{\r
ERR("Unable to execute command\n");\r
return ERROR_SUCCESS;\r
}\r
\r
-static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, \r
+static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source,\r
const LPWSTR target, const INT type)\r
{\r
- WCHAR filename[MAX_PATH*2];\r
STARTUPINFOW si;\r
PROCESS_INFORMATION info;\r
BOOL rc;\r
WCHAR *deformated;\r
+ WCHAR *cmd;\r
+ INT len;\r
static const WCHAR spc[] = {' ',0};\r
int index;\r
\r
memset(&si,0,sizeof(STARTUPINFOW));\r
\r
index = get_loaded_file(package,source);\r
- strcpyW(filename,package->files[index].TargetPath);\r
\r
- strcatW(filename,spc);\r
+ len = strlenW(package->files[index].TargetPath);\r
+\r
deformat_string(package,target,&deformated);\r
- strcatW(filename,deformated);\r
+ len += strlenW(deformated);\r
+ len += 2;\r
+\r
+ cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR));\r
+\r
+ strcpyW(cmd, package->files[index].TargetPath);\r
+ strcatW(cmd, spc);\r
+ strcatW(cmd, deformated);\r
\r
HeapFree(GetProcessHeap(),0,deformated);\r
\r
- TRACE("executing exe %s \n",debugstr_w(filename));\r
+ TRACE("executing exe %s \n",debugstr_w(cmd));\r
\r
- rc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL,\r
+ rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,\r
c_collen, &si, &info);\r
\r
+ HeapFree(GetProcessHeap(),0,cmd);\r
+ \r
if ( !rc )\r
{\r
ERR("Unable to execute command\n");\r
return ERROR_SUCCESS;\r
}\r
\r
-static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, \r
+static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source,\r
const LPWSTR target, const INT type)\r
{\r
- WCHAR filename[MAX_PATH*2];\r
STARTUPINFOW si;\r
PROCESS_INFORMATION info;\r
+ WCHAR *prop;\r
BOOL rc;\r
WCHAR *deformated;\r
+ WCHAR *cmd;\r
+ INT len;\r
+ UINT prc;\r
static const WCHAR spc[] = {' ',0};\r
- DWORD sz;\r
\r
memset(&si,0,sizeof(STARTUPINFOW));\r
+ memset(&info,0,sizeof(PROCESS_INFORMATION));\r
\r
- sz = MAX_PATH*2;\r
- if (MSI_GetPropertyW(package,source,filename,&sz) != ERROR_SUCCESS)\r
- return ERROR_FUNCTION_FAILED;\r
+ prop = load_dynamic_property(package,source,&prc);\r
+ if (!prop)\r
+ return prc;\r
\r
- strcatW(filename,spc);\r
deformat_string(package,target,&deformated);\r
- strcatW(filename,deformated);\r
+ len = strlenW(prop) + strlenW(deformated) + 2;\r
+ cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len);\r
+\r
+ strcpyW(cmd,prop);\r
+ strcatW(cmd,spc);\r
+ strcatW(cmd,deformated);\r
\r
HeapFree(GetProcessHeap(),0,deformated);\r
\r
- TRACE("executing exe %s \n",debugstr_w(filename));\r
+ TRACE("executing exe %s \n",debugstr_w(cmd));\r
\r
- rc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL,\r
+ rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,\r
c_collen, &si, &info);\r
\r
+ HeapFree(GetProcessHeap(),0,cmd);\r
+ \r
if ( !rc )\r
{\r
ERR("Unable to execute command\n");\r
return ERROR_SUCCESS;\r
}\r
\r
-static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, \r
+static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source,\r
const LPWSTR target, const INT type)\r
{\r
- WCHAR filename[MAX_PATH*2];\r
+ LPWSTR filename, deformated;\r
STARTUPINFOW si;\r
PROCESS_INFORMATION info;\r
BOOL rc;\r
- WCHAR *deformated;\r
\r
memset(&si,0,sizeof(STARTUPINFOW));\r
\r
- rc = resolve_folder(package, source, filename, FALSE, FALSE, NULL);\r
- if (rc != ERROR_SUCCESS)\r
- return rc;\r
+ filename = resolve_folder(package, source, FALSE, FALSE, NULL);\r
+\r
+ if (!filename)\r
+ return ERROR_FUNCTION_FAILED;\r
\r
SetCurrentDirectoryW(filename);\r
+ HeapFree(GetProcessHeap(),0,filename);\r
\r
deformat_string(package,target,&deformated);\r
- strcpyW(filename,deformated);\r
-\r
- HeapFree(GetProcessHeap(),0,deformated);\r
\r
- TRACE("executing exe %s \n",debugstr_w(filename));\r
+ TRACE("executing exe %s \n",debugstr_w(deformated));\r
\r
- rc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL,\r
+ rc = CreateProcessW(NULL, deformated, NULL, NULL, FALSE, 0, NULL,\r
c_collen, &si, &info);\r
+ HeapFree(GetProcessHeap(),0,deformated);\r
\r
if ( !rc )\r
{\r
WCHAR *new_path;\r
\r
new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) *\r
-sizeof(WCHAR));\r
+ sizeof(WCHAR));\r
+\r
strcpyW(new_path, path);\r
\r
while((len = strlenW(new_path)) && new_path[len - 1] == '\\')\r
\r
while(!CreateDirectoryW(new_path, NULL))\r
{\r
- WCHAR *slash;\r
- DWORD last_error = GetLastError();\r
- if(last_error == ERROR_ALREADY_EXISTS)\r
- break;\r
+ WCHAR *slash;\r
+ DWORD last_error = GetLastError();\r
+ if(last_error == ERROR_ALREADY_EXISTS)\r
+ break;\r
\r
- if(last_error != ERROR_PATH_NOT_FOUND)\r
- {\r
- ret = FALSE;\r
- break;\r
- }\r
+ if(last_error != ERROR_PATH_NOT_FOUND)\r
+ {\r
+ ret = FALSE;\r
+ break;\r
+ }\r
\r
- if(!(slash = strrchrW(new_path, '\\')))\r
- {\r
- ret = FALSE;\r
- break;\r
- }\r
+ if(!(slash = strrchrW(new_path, '\\')))\r
+ {\r
+ ret = FALSE;\r
+ break;\r
+ }\r
\r
- len = slash - new_path;\r
- new_path[len] = 0;\r
- if(!create_full_pathW(new_path))\r
- {\r
- ret = FALSE;\r
- break;\r
- }\r
- new_path[len] = '\\';\r
+ len = slash - new_path;\r
+ new_path[len] = 0;\r
+ if(!create_full_pathW(new_path))\r
+ {\r
+ ret = FALSE;\r
+ break;\r
+ }\r
+ new_path[len] = '\\';\r
}\r
\r
HeapFree(GetProcessHeap(), 0, new_path);\r
while (1)\r
{\r
WCHAR dir[0x100];\r
- WCHAR full_path[MAX_PATH];\r
+ LPWSTR full_path;\r
DWORD sz;\r
MSIRECORD *row = NULL, *uirow;\r
\r
}\r
\r
sz = MAX_PATH;\r
- rc = resolve_folder(package,dir,full_path,FALSE,FALSE,&folder);\r
-\r
- if (rc != ERROR_SUCCESS)\r
+ full_path = resolve_folder(package,dir,FALSE,FALSE,&folder);\r
+ if (!full_path)\r
{\r
ERR("Unable to resolve folder id %s\n",debugstr_w(dir));\r
msiobj_release(&row->hdr);\r
folder->State = 3;\r
\r
msiobj_release(&row->hdr);\r
+ HeapFree(GetProcessHeap(),0,full_path);\r
}\r
MSI_ViewClose(view);\r
msiobj_release(&view->hdr);\r
sz = 96; \r
MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz);\r
\r
- package->components[index].State = INSTALLSTATE_UNKNOWN;\r
+ package->components[index].Installed = INSTALLSTATE_ABSENT;\r
+ package->components[index].Action = INSTALLSTATE_UNKNOWN;\r
+ package->components[index].ActionRequest = INSTALLSTATE_UNKNOWN;\r
+\r
package->components[index].Enabled = TRUE;\r
- package->components[index].FeatureState= FALSE;\r
\r
return index;\r
}\r
int index = package->loaded_features;\r
DWORD sz;\r
static const WCHAR Query1[] = {'S','E','L','E','C','T',' ','C','o','m','p',\r
-'o','n','e','n','t','_',' ','F','R','O','M',' ','F','e','a','t','u','r','e',\r
-'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ','F','e',\r
-'a','t','u','r','e','_','=','\'','%','s','\'',0};\r
+ 'o','n','e','n','t','_',' ','F','R','O','M',' ','F','e','a','t','u','r','e',\r
+ 'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ','F','e',\r
+ 'a','t','u','r','e','_','=','\'','%','s','\'',0};\r
static const WCHAR Query2[] = {'S','E','L','E','C','T',' ','*',' ','F','R',\r
-'O','M',' ','C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ','C',\r
-'o','m','p','o','n','e','n','t','=','\'','%','s','\'',0};\r
- WCHAR Query[1024];\r
+ 'O','M',' ','C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ','C',\r
+ 'o','m','p','o','n','e','n','t','=','\'','%','s','\'',0};\r
MSIQUERY * view;\r
MSIQUERY * view2;\r
MSIRECORD * row2;\r
MSI_RecordGetStringW(row,7,package->features[index].Directory,&sz);\r
\r
package->features[index].Attributes= MSI_RecordGetInteger(row,8);\r
- package->features[index].State = INSTALLSTATE_UNKNOWN;\r
+\r
+ package->features[index].Installed = INSTALLSTATE_ABSENT;\r
+ package->features[index].Action = INSTALLSTATE_UNKNOWN;\r
+ package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN;\r
\r
/* load feature components */\r
\r
- sprintfW(Query,Query1,package->features[index].Feature);\r
- rc = MSI_DatabaseOpenViewW(package->db,Query,&view);\r
+ rc = ACTION_OpenQuery(package->db, &view, Query1, package->features[index].Feature);\r
if (rc != ERROR_SUCCESS)\r
return;\r
rc = MSI_ViewExecute(view,0);\r
c_indx);\r
package->features[index].Components[cnt] = c_indx;\r
package->features[index].ComponentCount ++;\r
+ continue;\r
}\r
\r
- sprintfW(Query,Query2,buffer);\r
- \r
- rc = MSI_DatabaseOpenViewW(package->db,Query,&view2);\r
+ rc = ACTION_OpenQuery(package->db, &view2, Query2, buffer);\r
if (rc != ERROR_SUCCESS)\r
{\r
msiobj_release( &row2->hdr );\r
\r
package->features[index].Components[cnt] = c_indx;\r
package->features[index].ComponentCount ++;\r
+ TRACE("Loaded new component to index %i\n",c_indx);\r
}\r
MSI_ViewClose(view2);\r
msiobj_release( &view2->hdr );\r
{\r
MSIQUERY * view;\r
MSIRECORD * row;\r
- DWORD sz;\r
UINT rc;\r
static const WCHAR Query_all[] = {\r
'S','E','L','E','C','T',' ','*',' ',\r
MSI_SetPropertyW(package, szCosting, szZero);\r
MSI_SetPropertyW(package, cszRootDrive , c_collen);\r
\r
- sz = 0x100;\r
rc = MSI_DatabaseOpenViewW(package->db,Query_all,&view);\r
if (rc != ERROR_SUCCESS)\r
return rc;\r
{\r
DWORD index = package->loaded_files;\r
DWORD i;\r
- WCHAR buffer[0x100];\r
- DWORD sz;\r
+ LPWSTR buffer;\r
\r
/* fill in the data */\r
\r
package->files , package->loaded_files * sizeof(MSIFILE));\r
\r
memset(&package->files[index],0,sizeof(MSIFILE));\r
-\r
- sz = 72; \r
- MSI_RecordGetStringW(row,1,package->files[index].File,&sz);\r
-\r
- sz = 0x100; \r
- MSI_RecordGetStringW(row,2,buffer,&sz);\r
+ \r
+ package->files[index].File = load_dynamic_stringW(row, 1);\r
+ buffer = load_dynamic_stringW(row, 2);\r
\r
package->files[index].ComponentIndex = -1;\r
for (i = 0; i < package->loaded_components; i++)\r
}\r
if (package->files[index].ComponentIndex == -1)\r
ERR("Unfound Component %s\n",debugstr_w(buffer));\r
+ HeapFree(GetProcessHeap(), 0, buffer);\r
\r
- sz = MAX_PATH; \r
- MSI_RecordGetStringW(row,3,package->files[index].FileName,&sz);\r
+ package->files[index].FileName = load_dynamic_stringW(row,3);\r
\r
reduce_to_longfilename(package->files[index].FileName);\r
\r
package->files[index].FileSize = MSI_RecordGetInteger(row,4);\r
-\r
- sz = 72; \r
- if (!MSI_RecordIsNull(row,5))\r
- MSI_RecordGetStringW(row,5,package->files[index].Version,&sz);\r
-\r
- sz = 20; \r
- if (!MSI_RecordIsNull(row,6))\r
- MSI_RecordGetStringW(row,6,package->files[index].Language,&sz);\r
-\r
- if (!MSI_RecordIsNull(row,7))\r
- package->files[index].Attributes= MSI_RecordGetInteger(row,7);\r
-\r
+ package->files[index].Version = load_dynamic_stringW(row, 5);\r
+ package->files[index].Language = load_dynamic_stringW(row, 6);\r
+ package->files[index].Attributes= MSI_RecordGetInteger(row,7);\r
package->files[index].Sequence= MSI_RecordGetInteger(row,8);\r
\r
package->files[index].Temporary = FALSE;\r
static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)\r
\r
{\r
- WCHAR Query[1024] = \r
-{'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','D','i','r','e','c',\r
-'t','o','r','y',' ','w','h','e','r','e',' ','`','D','i','r','e','c','t',\r
-'o','r','y','`',' ','=',' ','`',0};\r
- static const WCHAR end[]={'`',0};\r
+ static const WCHAR Query[] =\r
+ {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','D','i','r','e','c',\r
+ 't','o','r','y',' ','w','h','e','r','e',' ','`','D','i','r','e','c','t',\r
+ 'o','r','y','`',' ','=',' ','`','%','s','`',0};\r
UINT rc;\r
MSIQUERY * view;\r
- WCHAR targetbuffer[0x100];\r
- WCHAR *srcdir = NULL;\r
- WCHAR *targetdir = NULL;\r
- WCHAR parent[0x100];\r
- DWORD sz=0x100;\r
+ LPWSTR targetdir, parent, srcdir;\r
MSIRECORD * row = 0;\r
INT index = -1;\r
DWORD i;\r
\r
TRACE("Working to load %s\n",debugstr_w(dir));\r
\r
- index = package->loaded_folders; \r
-\r
- package->loaded_folders++;\r
- if (package->loaded_folders== 1)\r
+ index = package->loaded_folders++;\r
+ if (package->loaded_folders==1)\r
package->folders = HeapAlloc(GetProcessHeap(),0,\r
sizeof(MSIFOLDER));\r
else\r
\r
memset(&package->folders[index],0,sizeof(MSIFOLDER));\r
\r
- strcpyW(package->folders[index].Directory,dir);\r
-\r
- strcatW(Query,dir);\r
- strcatW(Query,end);\r
-\r
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);\r
+ package->folders[index].Directory = dupstrW(dir);\r
\r
+ rc = ACTION_OpenQuery(package->db, &view, Query, dir);\r
if (rc != ERROR_SUCCESS)\r
return -1;\r
\r
return -1;\r
}\r
\r
- sz=0x100;\r
- MSI_RecordGetStringW(row,3,targetbuffer,&sz);\r
- targetdir=targetbuffer;\r
+ targetdir = load_dynamic_stringW(row,3);\r
\r
/* split src and target dir */\r
if (strchrW(targetdir,':'))\r
if (srcdir && srcdir[0] == '.' && srcdir[1] == 0)\r
srcdir = NULL;\r
\r
- if (targetdir)\r
- strcpyW(package->folders[index].TargetDefault,targetdir);\r
-\r
- if (srcdir)\r
- strcpyW(package->folders[index].SourceDefault,srcdir);\r
- else if (targetdir)\r
- strcpyW(package->folders[index].SourceDefault,targetdir);\r
-\r
- if (MSI_RecordIsNull(row,2))\r
- parent[0]=0;\r
- else\r
+ if (targetdir)\r
{\r
- sz=0x100;\r
- MSI_RecordGetStringW(row,2,parent,&sz);\r
+ TRACE(" TargetDefault = %s\n",debugstr_w(targetdir));\r
+ if (package->folders[index].TargetDefault)\r
+ HeapFree(GetProcessHeap(),0, package->folders[index].TargetDefault);\r
+ package->folders[index].TargetDefault = dupstrW(targetdir);\r
}\r
\r
- if (parent[0]) \r
+ if (srcdir)\r
+ package->folders[index].SourceDefault = dupstrW(srcdir);\r
+ else if (targetdir)\r
+ package->folders[index].SourceDefault = dupstrW(targetdir);\r
+ HeapFree(GetProcessHeap(), 0, targetdir);\r
+\r
+ parent = load_dynamic_stringW(row,2);\r
+ if (parent) \r
{\r
i = load_folder(package,parent);\r
package->folders[index].ParentIndex = i;\r
TRACE("Parent is index %i... %s %s\n",\r
package->folders[index].ParentIndex,\r
- debugstr_w(package->folders[package->folders[index].ParentIndex].Directory),\r
+ debugstr_w(package->folders[package->folders[index].ParentIndex].Directory),\r
debugstr_w(parent));\r
}\r
else\r
package->folders[index].ParentIndex = -2;\r
+ HeapFree(GetProcessHeap(), 0, parent);\r
\r
- sz = MAX_PATH;\r
- rc = MSI_GetPropertyW(package, dir, package->folders[index].Property, &sz);\r
- if (rc != ERROR_SUCCESS)\r
- package->folders[index].Property[0]=0;\r
+ package->folders[index].Property = load_dynamic_property(package, dir,NULL);\r
\r
msiobj_release(&row->hdr);\r
MSI_ViewClose(view);\r
return index;\r
}\r
\r
-static UINT resolve_folder(MSIPACKAGE *package, LPCWSTR name, LPWSTR path, \r
+\r
+static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name,\r
BOOL source, BOOL set_prop, MSIFOLDER **folder)\r
{\r
DWORD i;\r
- UINT rc = ERROR_SUCCESS;\r
- DWORD sz;\r
+ LPWSTR p, path = NULL;\r
\r
TRACE("Working to resolve %s\n",debugstr_w(name));\r
\r
- if (!path)\r
- return rc;\r
-\r
/* special resolving for Target and Source root dir */\r
if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)\r
{\r
if (!source)\r
{\r
- sz = MAX_PATH;\r
- rc = MSI_GetPropertyW(package,cszTargetDir,path,&sz);\r
- if (rc != ERROR_SUCCESS)\r
+ path = load_dynamic_property(package,cszTargetDir,NULL);\r
+ if (!path)\r
{\r
- sz = MAX_PATH;\r
- rc = MSI_GetPropertyW(package,cszRootDrive,path,&sz);\r
+ path = load_dynamic_property(package,cszRootDrive,NULL);\r
if (set_prop)\r
MSI_SetPropertyW(package,cszTargetDir,path);\r
}\r
if (folder)\r
- *folder = &(package->folders[0]);\r
- return rc;\r
+ {\r
+ for (i = 0; i < package->loaded_folders; i++)\r
+ {\r
+ if (strcmpW(package->folders[i].Directory,name)==0)\r
+ break;\r
+ }\r
+ *folder = &(package->folders[i]);\r
+ }\r
+ return path;\r
}\r
else\r
{\r
- sz = MAX_PATH;\r
- rc = MSI_GetPropertyW(package,cszSourceDir,path,&sz);\r
- if (rc != ERROR_SUCCESS)\r
+ path = load_dynamic_property(package,cszSourceDir,NULL);\r
+ if (!path)\r
{\r
- sz = MAX_PATH;\r
- rc = MSI_GetPropertyW(package,cszDatabase,path,&sz);\r
- if (rc == ERROR_SUCCESS)\r
+ path = load_dynamic_property(package,cszDatabase,NULL);\r
+ if (path)\r
{\r
- LPWSTR ptr = strrchrW(path,'\\');\r
- if (ptr)\r
- {\r
- ptr++;\r
- *ptr = 0;\r
- }\r
+ p = strrchrW(path,'\\');\r
+ if (p)\r
+ *(p+1) = 0;\r
}\r
}\r
if (folder)\r
- *folder = &(package->folders[0]);\r
- return rc;\r
+ {\r
+ for (i = 0; i < package->loaded_folders; i++)\r
+ {\r
+ if (strcmpW(package->folders[i].Directory,name)==0)\r
+ break;\r
+ }\r
+ *folder = &(package->folders[i]);\r
+ }\r
+ return path;\r
}\r
}\r
\r
}\r
\r
if (i >= package->loaded_folders)\r
- return ERROR_FUNCTION_FAILED;\r
+ return NULL;\r
\r
if (folder)\r
*folder = &(package->folders[i]);\r
\r
- if (!source && package->folders[i].ResolvedTarget[0])\r
+ if (!source && package->folders[i].ResolvedTarget)\r
{\r
- strcpyW(path,package->folders[i].ResolvedTarget);\r
+ path = dupstrW(package->folders[i].ResolvedTarget);\r
TRACE(" already resolved to %s\n",debugstr_w(path));\r
- return ERROR_SUCCESS;\r
+ return path;\r
}\r
- else if (source && package->folders[i].ResolvedSource[0])\r
+ else if (source && package->folders[i].ResolvedSource)\r
{\r
- strcpyW(path,package->folders[i].ResolvedSource);\r
- return ERROR_SUCCESS;\r
+ path = dupstrW(package->folders[i].ResolvedSource);\r
+ return path;\r
}\r
- else if (!source && package->folders[i].Property[0])\r
+ else if (!source && package->folders[i].Property)\r
{\r
- strcpyW(path,package->folders[i].Property);\r
+ path = dupstrW(package->folders[i].Property);\r
TRACE(" internally set to %s\n",debugstr_w(path));\r
if (set_prop)\r
MSI_SetPropertyW(package,name,path);\r
- return ERROR_SUCCESS;\r
+ return path;\r
+ }\r
+\r
+ if (package->folders[i].ParentIndex >= 0)\r
+ {\r
+ LPWSTR parent = package->folders[package->folders[i].ParentIndex].Directory;\r
+\r
+ TRACE(" ! Parent is %s\n", debugstr_w(parent));\r
+\r
+ p = resolve_folder(package, parent, source, set_prop, NULL);\r
+ if (!source)\r
+ {\r
+ TRACE(" TargetDefault = %s\n",debugstr_w(package->folders[i].TargetDefault));\r
+ path = build_directory_name(3, p, package->folders[i].TargetDefault, NULL);\r
+ package->folders[i].ResolvedTarget = dupstrW(path);\r
+ TRACE(" resolved into %s\n",debugstr_w(path));\r
+ if (set_prop)\r
+ MSI_SetPropertyW(package,name,path);\r
+ }\r
+ else \r
+ {\r
+ path = build_directory_name(3, p, package->folders[i].SourceDefault, NULL);\r
+ package->folders[i].ResolvedSource = dupstrW(path);\r
+ }\r
+ HeapFree(GetProcessHeap(),0,p);\r
+ }\r
+ return path;\r
+}\r
+\r
+static UINT SetFeatureStates(MSIPACKAGE *package)\r
+{\r
+ LPWSTR level;\r
+ INT install_level;\r
+ DWORD i;\r
+ INT j;\r
+ LPWSTR override = NULL;\r
+ static const WCHAR all[]={'A','L','L',0};\r
+ static const WCHAR szlevel[] = {\r
+ 'I','N','S','T','A','L','L','L','E','V','E','L',0};\r
+ static const WCHAR szAddLocal[] = {\r
+ 'A','D','D','L','O','C','A','L',0};\r
+\r
+ /* I do not know if this is where it should happen.. but */\r
+\r
+ TRACE("Checking Install Level\n");\r
+\r
+ level = load_dynamic_property(package,szlevel,NULL);\r
+ if (level)\r
+ {\r
+ install_level = atoiW(level);\r
+ HeapFree(GetProcessHeap(), 0, level);\r
+ }\r
+ else\r
+ install_level = 1;\r
+\r
+ /* ok hereis the rub\r
+ * ADDLOCAL and its friend OVERRIDE INSTALLLEVLE\r
+ * I have confirmed this if ADDLOCALis stated then the INSTALLLEVEL is\r
+ * itnored for all the features. seems strange, epsecially since it is not\r
+ * documented anywhere, but it is how it works. \r
+ */\r
+ \r
+ override = load_dynamic_property(package,szAddLocal,NULL);\r
+ \r
+ if (override)\r
+ {\r
+ for(i = 0; i < package->loaded_features; i++)\r
+ {\r
+ if (strcmpiW(override,all)==0)\r
+ {\r
+ package->features[i].ActionRequest= INSTALLSTATE_LOCAL;\r
+ package->features[i].Action = INSTALLSTATE_LOCAL;\r
+ }\r
+ else\r
+ {\r
+ LPWSTR ptr = override;\r
+ LPWSTR ptr2 = strchrW(override,',');\r
+\r
+ while (ptr)\r
+ {\r
+ if ((ptr2 && \r
+ strncmpW(ptr,package->features[i].Feature, ptr2-ptr)==0)\r
+ || (!ptr2 &&\r
+ strcmpW(ptr,package->features[i].Feature)==0))\r
+ {\r
+ package->features[i].ActionRequest= INSTALLSTATE_LOCAL;\r
+ package->features[i].Action = INSTALLSTATE_LOCAL;\r
+ break;\r
+ }\r
+ if (ptr2)\r
+ {\r
+ ptr=ptr2+1;\r
+ ptr2 = strchrW(ptr,',');\r
+ }\r
+ else\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ HeapFree(GetProcessHeap(),0,override);\r
+ } \r
+ else\r
+ {\r
+ for(i = 0; i < package->loaded_features; i++)\r
+ {\r
+ BOOL feature_state= ((package->features[i].Level > 0) &&\r
+ (package->features[i].Level <= install_level));\r
+\r
+ if (feature_state)\r
+ {\r
+ package->features[i].ActionRequest= INSTALLSTATE_LOCAL;\r
+ package->features[i].Action = INSTALLSTATE_LOCAL;\r
+ }\r
+ }\r
}\r
\r
- if (package->folders[i].ParentIndex >= 0)\r
- {\r
- int len;\r
- TRACE(" ! Parent is %s\n", debugstr_w(package->folders[\r
- package->folders[i].ParentIndex].Directory));\r
- resolve_folder(package, package->folders[\r
- package->folders[i].ParentIndex].Directory, path,source,\r
- set_prop, NULL);\r
+ /*\r
+ * now we want to enable or disable components base on feature \r
+ */\r
\r
- len = strlenW(path);\r
- if (len && path[len-1] != '\\')\r
- strcatW(path, cszbs);\r
+ for(i = 0; i < package->loaded_features; i++)\r
+ {\r
+ MSIFEATURE* feature = &package->features[i];\r
+ TRACE("Examining Feature %s (Installed %i, Action %i, Request %i)\n",\r
+ debugstr_w(feature->Feature), feature->Installed, feature->Action,\r
+ feature->ActionRequest);\r
\r
- if (!source)\r
+ for( j = 0; j < feature->ComponentCount; j++)\r
{\r
- if (package->folders[i].TargetDefault[0])\r
+ MSICOMPONENT* component = &package->components[\r
+ feature->Components[j]];\r
+\r
+ if (!component->Enabled)\r
{\r
- strcatW(path,package->folders[i].TargetDefault);\r
- strcatW(path,cszbs);\r
+ component->Action = INSTALLSTATE_ABSENT;\r
+ component->ActionRequest = INSTALLSTATE_ABSENT;\r
}\r
- strcpyW(package->folders[i].ResolvedTarget,path);\r
- TRACE(" resolved into %s\n",debugstr_w(path));\r
- if (set_prop)\r
- MSI_SetPropertyW(package,name,path);\r
- }\r
- else \r
- {\r
- if (package->folders[i].SourceDefault[0])\r
+ else\r
{\r
- strcatW(path,package->folders[i].SourceDefault);\r
- strcatW(path,cszbs);\r
+ if (feature->Action == INSTALLSTATE_LOCAL)\r
+ component->Action = INSTALLSTATE_LOCAL;\r
+ if (feature->ActionRequest == INSTALLSTATE_LOCAL)\r
+ component->ActionRequest = INSTALLSTATE_LOCAL;\r
}\r
- strcpyW(package->folders[i].ResolvedSource,path);\r
}\r
+ } \r
+\r
+ for(i = 0; i < package->loaded_components; i++)\r
+ {\r
+ MSICOMPONENT* component= &package->components[i];\r
+\r
+ TRACE("Result: Component %s (Installed %i, Action %i, Request %i)\n",\r
+ debugstr_w(component->Component), component->Installed, \r
+ component->Action, component->ActionRequest);\r
}\r
- return rc;\r
+\r
+\r
+ return ERROR_SUCCESS;\r
}\r
\r
/* \r
'C','o','n','d','i','t','i','o','n',0};\r
static const WCHAR szCosting[] = {\r
'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };\r
+ static const WCHAR szlevel[] = {\r
+ 'I','N','S','T','A','L','L','L','E','V','E','L',0};\r
static const WCHAR szOne[] = { '1', 0 };\r
UINT rc;\r
MSIQUERY * view;\r
DWORD i;\r
+ LPWSTR level;\r
\r
TRACE("Building Directory properties\n");\r
\r
while (1)\r
{\r
WCHAR name[0x100];\r
- WCHAR path[MAX_PATH];\r
+ LPWSTR path;\r
MSIRECORD * row = 0;\r
DWORD sz;\r
\r
/* This helper function now does ALL the work */\r
TRACE("Dir %s ...\n",debugstr_w(name));\r
load_folder(package,name);\r
- resolve_folder(package,name,path,FALSE,TRUE,NULL);\r
+ path = resolve_folder(package,name,FALSE,TRUE,NULL);\r
TRACE("resolves to %s\n",debugstr_w(path));\r
+ HeapFree( GetProcessHeap(), 0, path);\r
\r
msiobj_release(&row->hdr);\r
}\r
if (file->ComponentIndex >= 0)\r
comp = &package->components[file->ComponentIndex];\r
\r
+ if (file->Temporary == TRUE)\r
+ continue;\r
+\r
if (comp)\r
{\r
- int len;\r
+ LPWSTR p;\r
+\r
/* calculate target */\r
- resolve_folder(package, comp->Directory, file->TargetPath, FALSE,\r
- FALSE, NULL);\r
- /* make sure that the path ends in a \ */\r
- len = strlenW(file->TargetPath);\r
- if (len && file->TargetPath[len-1] != '\\')\r
- strcatW(file->TargetPath, cszbs);\r
- strcatW(file->TargetPath,file->FileName);\r
+ p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);\r
+\r
+ if (file->TargetPath)\r
+ HeapFree(GetProcessHeap(),0,file->TargetPath);\r
+\r
+ TRACE("file %s is named %s\n",\r
+ debugstr_w(file->File),debugstr_w(file->FileName)); \r
+\r
+ file->TargetPath = build_directory_name(2, p, file->FileName);\r
+\r
+ HeapFree(GetProcessHeap(),0,p);\r
\r
TRACE("file %s resolves to %s\n",\r
debugstr_w(file->File),debugstr_w(file->TargetPath)); \r
- \r
+\r
if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)\r
{\r
file->State = 1;\r
}\r
else\r
{\r
- if (file->Version[0])\r
+ if (file->Version)\r
{\r
DWORD handle;\r
DWORD versize;\r
rc = MSI_DatabaseOpenViewW(package->db, ConditionQuery, &view);\r
if (rc == ERROR_SUCCESS)\r
{\r
- rc = MSI_ViewExecute(view, 0);\r
- if (rc != ERROR_SUCCESS)\r
- {\r
- MSI_ViewClose(view);\r
- msiobj_release(&view->hdr);\r
- return rc;\r
- }\r
- \r
- while (1)\r
- {\r
- WCHAR Feature[0x100];\r
- MSIRECORD * row = 0;\r
- DWORD sz;\r
- int feature_index;\r
-\r
- rc = MSI_ViewFetch(view,&row);\r
-\r
+ rc = MSI_ViewExecute(view, 0);\r
if (rc != ERROR_SUCCESS)\r
{\r
- rc = ERROR_SUCCESS;\r
- break;\r
+ MSI_ViewClose(view);\r
+ msiobj_release(&view->hdr);\r
+ return rc;\r
}\r
+ \r
+ while (1)\r
+ {\r
+ WCHAR Feature[0x100];\r
+ MSIRECORD * row = 0;\r
+ DWORD sz;\r
+ int feature_index;\r
\r
- sz = 0x100;\r
- MSI_RecordGetStringW(row,1,Feature,&sz);\r
+ rc = MSI_ViewFetch(view,&row);\r
\r
- feature_index = get_loaded_feature(package,Feature);\r
- if (feature_index < 0)\r
- ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature));\r
- else\r
- {\r
- LPWSTR Condition;\r
- Condition = load_dynamic_stringW(row,3);\r
+ if (rc != ERROR_SUCCESS)\r
+ {\r
+ rc = ERROR_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ sz = 0x100;\r
+ MSI_RecordGetStringW(row,1,Feature,&sz);\r
+\r
+ feature_index = get_loaded_feature(package,Feature);\r
+ if (feature_index < 0)\r
+ ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature));\r
+ else\r
+ {\r
+ LPWSTR Condition;\r
+ Condition = load_dynamic_stringW(row,3);\r
\r
if (MSI_EvaluateConditionW(package,Condition) == \r
MSICONDITION_TRUE)\r
- {\r
- int level = MSI_RecordGetInteger(row,2);\r
+ {\r
+ int level = MSI_RecordGetInteger(row,2);\r
TRACE("Reseting feature %s to level %i\n",\r
debugstr_w(Feature), level);\r
- package->features[feature_index].Level = level;\r
+ package->features[feature_index].Level = level;\r
+ }\r
+ HeapFree(GetProcessHeap(),0,Condition);\r
}\r
- HeapFree(GetProcessHeap(),0,Condition);\r
- }\r
\r
- msiobj_release(&row->hdr);\r
- }\r
- MSI_ViewClose(view);\r
- msiobj_release(&view->hdr);\r
+ msiobj_release(&row->hdr);\r
+ }\r
+ MSI_ViewClose(view);\r
+ msiobj_release(&view->hdr);\r
}\r
\r
TRACE("Enabling or Disabling Components\n");\r
}\r
\r
MSI_SetPropertyW(package,szCosting,szOne);\r
- return ERROR_SUCCESS;\r
+ /* set default run level if not set */\r
+ level = load_dynamic_property(package,szlevel,NULL);\r
+ if (!level)\r
+ MSI_SetPropertyW(package,szlevel, szOne);\r
+ else\r
+ HeapFree(GetProcessHeap(),0,level);\r
+\r
+ return SetFeatureStates(package);\r
+\r
}\r
\r
/*\r
\r
\r
/* Support functions for FDI functions */\r
+typedef struct\r
+{\r
+ MSIPACKAGE* package;\r
+ LPCSTR cab_path;\r
+ LPCSTR file_name;\r
+} CabData;\r
\r
static void * cabinet_alloc(ULONG cb)\r
{\r
{\r
case fdintCOPY_FILE:\r
{\r
- ULONG len = strlen((char*)pfdin->pv) + strlen(pfdin->psz1);\r
- char *file = cabinet_alloc((len+1)*sizeof(char));\r
+ CabData *data = (CabData*) pfdin->pv;\r
+ ULONG len = strlen(data->cab_path) + strlen(pfdin->psz1);\r
+ char *file;\r
\r
- strcpy(file, (char*)pfdin->pv);\r
+ LPWSTR trackname;\r
+ LPWSTR trackpath;\r
+ LPWSTR tracknametmp;\r
+ static const WCHAR tmpprefix[] = {'C','A','B','T','M','P','_',0};\r
+ \r
+ if (data->file_name && strcmp(data->file_name,pfdin->psz1))\r
+ return 0;\r
+ \r
+ file = cabinet_alloc((len+1)*sizeof(char));\r
+ strcpy(file, data->cab_path);\r
strcat(file, pfdin->psz1);\r
\r
TRACE("file: %s\n", debugstr_a(file));\r
\r
+ /* track this file so it can be deleted if not installed */\r
+ trackpath=strdupAtoW(file);\r
+ tracknametmp=strdupAtoW(strrchr(file,'\\')+1);\r
+ trackname = HeapAlloc(GetProcessHeap(),0,(strlenW(tracknametmp) + \r
+ strlenW(tmpprefix)+1) * sizeof(WCHAR));\r
+\r
+ strcpyW(trackname,tmpprefix);\r
+ strcatW(trackname,tracknametmp);\r
+\r
+ track_tempfile(data->package, trackname, trackpath);\r
+\r
+ HeapFree(GetProcessHeap(),0,trackpath);\r
+ HeapFree(GetProcessHeap(),0,trackname);\r
+ HeapFree(GetProcessHeap(),0,tracknametmp);\r
+\r
return cabinet_open(file, _O_WRONLY | _O_CREAT, 0);\r
}\r
case fdintCLOSE_FILE_INFO:\r
*\r
* Extract files from a cab file.\r
*/\r
-static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path)\r
+static BOOL extract_a_cabinet_file(MSIPACKAGE* package, const WCHAR* source, \r
+ const WCHAR* path, const WCHAR* file)\r
{\r
HFDI hfdi;\r
ERF erf;\r
BOOL ret;\r
char *cabinet;\r
char *cab_path;\r
+ char *file_name;\r
+ CabData data;\r
\r
- TRACE("Extracting %s to %s\n",debugstr_w(source), debugstr_w(path));\r
+ TRACE("Extracting %s (%s) to %s\n",debugstr_w(source), \r
+ debugstr_w(file), debugstr_w(path));\r
\r
hfdi = FDICreate(cabinet_alloc,\r
cabinet_free,\r
return FALSE;\r
}\r
\r
- ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, cab_path);\r
+ data.package = package;\r
+ data.cab_path = cab_path;\r
+ file_name = strdupWtoA(file);\r
+ data.file_name = file_name;\r
+\r
+ ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, &data);\r
\r
if (!ret)\r
ERR("FDICopy failed\n");\r
\r
HeapFree(GetProcessHeap(), 0, cabinet);\r
HeapFree(GetProcessHeap(), 0, cab_path);\r
+ HeapFree(GetProcessHeap(), 0, file_name);\r
\r
return ret;\r
}\r
\r
static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence, \r
- WCHAR* path)\r
+ WCHAR* path, WCHAR* file)\r
{\r
UINT rc;\r
MSIQUERY * view;\r
MSIRECORD * row = 0;\r
- WCHAR source[MAX_PATH];\r
+ static WCHAR source[MAX_PATH];\r
static const WCHAR ExecSeqQuery[] = {\r
's','e','l','e','c','t',' ','*',' ',\r
'f','r','o','m',' ','M','e','d','i','a',' ',\r
if (sequence <= last_sequence)\r
{\r
TRACE("Media already ready (%u, %u)\n",sequence,last_sequence);\r
+ extract_a_cabinet_file(package, source,path,file);\r
return ERROR_SUCCESS;\r
}\r
\r
GetTempPathW(MAX_PATH,path);\r
}\r
}\r
- rc = !extract_cabinet_file(source,path);\r
+ rc = !extract_a_cabinet_file(package, source,path,file);\r
}\r
msiobj_release(&row->hdr);\r
MSI_ViewClose(view);\r
{\r
UINT rc;\r
MSIFOLDER *folder;\r
- WCHAR install_path[MAX_PATH];\r
+ LPWSTR install_path;\r
\r
- rc = resolve_folder(package, package->components[component].Directory,\r
- install_path, FALSE, FALSE, &folder);\r
-\r
- if (rc != ERROR_SUCCESS)\r
- return rc; \r
+ install_path = resolve_folder(package, package->components[component].Directory,\r
+ FALSE, FALSE, &folder);\r
+ if (!install_path)\r
+ return ERROR_FUNCTION_FAILED; \r
\r
/* create the path */\r
if (folder->State == 0)\r
create_full_pathW(install_path);\r
folder->State = 2;\r
}\r
+ HeapFree(GetProcessHeap(), 0, install_path);\r
\r
return rc;\r
}\r
return ERROR_INVALID_HANDLE;\r
\r
/* increment progress bar each time action data is sent */\r
- ui_progress(package,1,1,1,0);\r
+ ui_progress(package,1,1,0,0);\r
\r
for (index = 0; index < package->loaded_files; index++)\r
{\r
if (file->Temporary)\r
continue;\r
\r
- if (!package->components[file->ComponentIndex].Enabled ||\r
- !package->components[file->ComponentIndex].FeatureState)\r
+ if (package->components[file->ComponentIndex].ActionRequest != \r
+ INSTALLSTATE_LOCAL)\r
{\r
+ ui_progress(package,2,file->FileSize,0,0);\r
TRACE("File %s is not scheduled for install\n",\r
debugstr_w(file->File));\r
+\r
continue;\r
}\r
\r
if ((file->State == 1) || (file->State == 2))\r
{\r
+ LPWSTR p;\r
+ INT len;\r
+ MSICOMPONENT* comp = NULL;\r
+\r
TRACE("Installing %s\n",debugstr_w(file->File));\r
- rc = ready_media_for_file(package,file->Sequence,path_to_source);\r
+ rc = ready_media_for_file(package,file->Sequence,path_to_source,\r
+ file->File);\r
/* \r
* WARNING!\r
* our file table could change here because a new temp file\r
\r
create_component_directory( package, file->ComponentIndex);\r
\r
+ /* recalculate file paths because things may have changed */\r
+\r
+ if (file->ComponentIndex >= 0)\r
+ comp = &package->components[file->ComponentIndex];\r
+\r
+ p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);\r
+ if (file->TargetPath)\r
+ HeapFree(GetProcessHeap(),0,file->TargetPath);\r
+\r
+ file->TargetPath = build_directory_name(2, p, file->FileName);\r
+\r
+ len = strlenW(path_to_source) + strlenW(file->File) + 2;\r
+ file->SourcePath = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));\r
strcpyW(file->SourcePath, path_to_source);\r
strcatW(file->SourcePath, file->File);\r
\r
MSI_RecordSetInteger(uirow,6,file->FileSize);\r
ui_actiondata(package,szInstallFiles,uirow);\r
msiobj_release( &uirow->hdr );\r
+ ui_progress(package,2,file->FileSize,0,0);\r
\r
if (!MoveFileW(file->SourcePath,file->TargetPath))\r
{\r
DeleteFileW(file->SourcePath);\r
rc = 0;\r
}\r
+ else if (rc == ERROR_FILE_NOT_FOUND)\r
+ {\r
+ ERR("Source File Not Found! Continueing\n");\r
+ rc = 0;\r
+ }\r
else\r
- break;\r
+ {\r
+ ERR("Ignoring Error and continuing...\n");\r
+ rc = 0;\r
+ }\r
}\r
else\r
file->State = 4;\r
-\r
- ui_progress(package,2,0,0,0);\r
}\r
}\r
\r
}\r
\r
inline static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key, \r
- LPWSTR file_source)\r
+ LPWSTR* file_source)\r
{\r
DWORD index;\r
\r
{\r
if (package->files[index].State >= 3)\r
{\r
- strcpyW(file_source,package->files[index].TargetPath);\r
+ *file_source = dupstrW(package->files[index].TargetPath);\r
return ERROR_SUCCESS;\r
}\r
else\r
while (1)\r
{\r
WCHAR file_key[0x100];\r
- WCHAR file_source[MAX_PATH];\r
+ WCHAR *file_source = NULL;\r
WCHAR dest_name[0x100];\r
- WCHAR dest_path[MAX_PATH];\r
+ LPWSTR dest_path, dest;\r
WCHAR component[0x100];\r
INT component_index;\r
\r
}\r
\r
component_index = get_loaded_component(package,component);\r
- if (!package->components[component_index].Enabled ||\r
- !package->components[component_index].FeatureState)\r
+ if (package->components[component_index].ActionRequest != \r
+ INSTALLSTATE_LOCAL)\r
{\r
TRACE("Skipping copy due to disabled component\n");\r
msiobj_release(&row->hdr);\r
break;\r
}\r
\r
- rc = get_file_target(package,file_key,file_source);\r
+ rc = get_file_target(package,file_key,&file_source);\r
\r
if (rc != ERROR_SUCCESS)\r
{\r
ERR("Original file unknown %s\n",debugstr_w(file_key));\r
msiobj_release(&row->hdr);\r
+ if (file_source)\r
+ HeapFree(GetProcessHeap(),0,file_source);\r
break;\r
}\r
\r
\r
if (MSI_RecordIsNull(row,5))\r
{\r
- strcpyW(dest_path,file_source);\r
- *strrchrW(dest_path,'\\')=0;\r
+ LPWSTR p;\r
+ dest_path = dupstrW(file_source);\r
+ p = strrchrW(dest_path,'\\');\r
+ if (p)\r
+ *p=0;\r
}\r
else\r
{\r
sz=0x100;\r
MSI_RecordGetStringW(row,5,destkey,&sz);\r
sz = 0x100;\r
- rc = resolve_folder(package, destkey, dest_path,FALSE,FALSE,NULL);\r
- if (rc != ERROR_SUCCESS)\r
+ dest_path = resolve_folder(package, destkey, FALSE,FALSE,NULL);\r
+ if (!dest_path)\r
{\r
ERR("Unable to get destination folder\n");\r
msiobj_release(&row->hdr);\r
+ if (file_source)\r
+ HeapFree(GetProcessHeap(),0,file_source);\r
break;\r
}\r
}\r
\r
- strcatW(dest_path,dest_name);\r
+ dest = build_directory_name(2, dest_path, dest_name);\r
+ HeapFree(GetProcessHeap(), 0, dest_path);\r
\r
TRACE("Duplicating file %s to %s\n",debugstr_w(file_source),\r
- debugstr_w(dest_path)); \r
+ debugstr_w(dest)); \r
\r
- if (strcmpW(file_source,dest_path))\r
- rc = !CopyFileW(file_source,dest_path,TRUE);\r
+ if (strcmpW(file_source,dest))\r
+ rc = !CopyFileW(file_source,dest,TRUE);\r
else\r
rc = ERROR_SUCCESS;\r
\r
FIXME("We should track these duplicate files as well\n"); \r
\r
msiobj_release(&row->hdr);\r
+ HeapFree(GetProcessHeap(),0,dest);\r
+ HeapFree(GetProcessHeap(),0,file_source);\r
}\r
MSI_ViewClose(view);\r
msiobj_release(&view->hdr);\r
return rc;\r
-\r
}\r
\r
\r
}\r
\r
/* increment progress bar each time action data is sent */\r
- ui_progress(package,1,1,1,0);\r
+ ui_progress(package,1,REG_PROGRESS_VALUE,1,0);\r
\r
while (1)\r
{\r
static const WCHAR szHU[] =\r
{'H','K','E','Y','_','U','S','E','R','S','\\',0};\r
\r
- WCHAR key[0x100];\r
- WCHAR name[0x100];\r
- LPWSTR value;\r
LPSTR value_data = NULL;\r
HKEY root_key, hkey;\r
DWORD type,size;\r
- WCHAR component[0x100];\r
+ LPWSTR value, key, name, component, deformated;\r
+ LPCWSTR szRoot;\r
INT component_index;\r
MSIRECORD * uirow;\r
- WCHAR uikey[0x110];\r
-\r
+ LPWSTR uikey;\r
INT root;\r
- DWORD sz=0x100;\r
\r
rc = MSI_ViewFetch(view,&row);\r
if (rc != ERROR_SUCCESS)\r
rc = ERROR_SUCCESS;\r
break;\r
}\r
+ ui_progress(package,2,0,0,0);\r
+\r
+ value = NULL;\r
+ key = NULL;\r
+ uikey = NULL;\r
+ name = NULL;\r
\r
- sz= 0x100;\r
- MSI_RecordGetStringW(row,6,component,&sz);\r
+ component = load_dynamic_stringW(row, 6);\r
component_index = get_loaded_component(package,component);\r
\r
- if (!package->components[component_index].Enabled ||\r
- !package->components[component_index].FeatureState)\r
+ if (package->components[component_index].ActionRequest != \r
+ INSTALLSTATE_LOCAL)\r
{\r
TRACE("Skipping write due to disabled component\n");\r
msiobj_release(&row->hdr);\r
- continue;\r
+ goto next;\r
}\r
\r
/* null values have special meanings during uninstalls and such */\r
if(MSI_RecordIsNull(row,5))\r
{\r
msiobj_release(&row->hdr);\r
- continue;\r
+ goto next;\r
}\r
\r
root = MSI_RecordGetInteger(row,2);\r
- sz = 0x100;\r
- MSI_RecordGetStringW(row,3,key,&sz);\r
+ key = load_dynamic_stringW(row, 3);\r
\r
- sz = 0x100; \r
- if (MSI_RecordIsNull(row,4))\r
- name[0]=0;\r
- else\r
- MSI_RecordGetStringW(row,4,name,&sz);\r
+ name = load_dynamic_stringW(row, 4);\r
\r
/* get the root key */\r
switch (root)\r
{\r
case 0: root_key = HKEY_CLASSES_ROOT; \r
- strcpyW(uikey,szHCR); break;\r
+ szRoot = szHCR;\r
+ break;\r
case 1: root_key = HKEY_CURRENT_USER;\r
- strcpyW(uikey,szHCU); break;\r
+ szRoot = szHCU;\r
+ break;\r
case 2: root_key = HKEY_LOCAL_MACHINE;\r
- strcpyW(uikey,szHLM); break;\r
+ szRoot = szHLM;\r
+ break;\r
case 3: root_key = HKEY_USERS; \r
- strcpyW(uikey,szHU); break;\r
+ szRoot = szHU;\r
+ break;\r
default:\r
ERR("Unknown root %i\n",root);\r
root_key=NULL;\r
+ szRoot = NULL;\r
break;\r
}\r
if (!root_key)\r
{\r
msiobj_release(&row->hdr);\r
- continue;\r
+ goto next;\r
}\r
\r
- strcatW(uikey,key);\r
- if (RegCreateKeyW( root_key, key, &hkey))\r
+ deformat_string(package, key , &deformated);\r
+ size = strlenW(deformated) + strlenW(szRoot) + 1;\r
+ uikey = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));\r
+ strcpyW(uikey,szRoot);\r
+ strcatW(uikey,deformated);\r
+\r
+ if (RegCreateKeyW( root_key, deformated, &hkey))\r
{\r
- ERR("Could not create key %s\n",debugstr_w(key));\r
+ ERR("Could not create key %s\n",debugstr_w(deformated));\r
msiobj_release(&row->hdr);\r
- continue;\r
+ HeapFree(GetProcessHeap(),0,deformated);\r
+ goto next;\r
}\r
+ HeapFree(GetProcessHeap(),0,deformated);\r
\r
value = load_dynamic_stringW(row,5);\r
value_data = parse_value(package, value, &type, &size); \r
\r
+ deformat_string(package, name, &deformated);\r
+\r
if (value_data)\r
{\r
- TRACE("Setting value %s\n",debugstr_w(name));\r
- RegSetValueExW(hkey, name, 0, type, value_data, size);\r
+ TRACE("Setting value %s\n",debugstr_w(deformated));\r
+ RegSetValueExW(hkey, deformated, 0, type, value_data, size);\r
\r
uirow = MSI_CreateRecord(3);\r
- MSI_RecordSetStringW(uirow,2,name);\r
+ MSI_RecordSetStringW(uirow,2,deformated);\r
MSI_RecordSetStringW(uirow,1,uikey);\r
\r
if (type == REG_SZ)\r
MSI_RecordSetStringW(uirow,3,value);\r
\r
ui_actiondata(package,szWriteRegistryValues,uirow);\r
- ui_progress(package,2,0,0,0);\r
msiobj_release( &uirow->hdr );\r
\r
HeapFree(GetProcessHeap(),0,value_data);\r
}\r
HeapFree(GetProcessHeap(),0,value);\r
+ HeapFree(GetProcessHeap(),0,deformated);\r
\r
msiobj_release(&row->hdr);\r
RegCloseKey(hkey);\r
+next:\r
+ if (uikey)\r
+ HeapFree(GetProcessHeap(),0,uikey);\r
+ if (key)\r
+ HeapFree(GetProcessHeap(),0,key);\r
+ if (name)\r
+ HeapFree(GetProcessHeap(),0,name);\r
+ if (component)\r
+ HeapFree(GetProcessHeap(),0,component);\r
}\r
MSI_ViewClose(view);\r
msiobj_release(&view->hdr);\r
DWORD sz;\r
UINT rc;\r
\r
+ if (ptr==NULL)\r
+ {\r
+ TRACE("Deformatting NULL string\n");\r
+ *data = NULL;\r
+ return 0;\r
+ }\r
/* scan for special characters */\r
if (!strchrW(ptr,'[') || (strchrW(ptr,'[') && !strchrW(ptr,']')))\r
{\r
\r
static UINT ACTION_InstallInitialize(MSIPACKAGE *package)\r
{\r
- WCHAR level[10000];\r
- INT install_level;\r
- DWORD sz;\r
- DWORD i;\r
- INT j;\r
- DWORD rc;\r
- LPWSTR override = NULL;\r
- static const WCHAR addlocal[]={'A','D','D','L','O','C','A','L',0};\r
- static const WCHAR all[]={'A','L','L',0};\r
- static const WCHAR szlevel[] = {\r
- 'I','N','S','T','A','L','L','L','E','V','E','L',0};\r
- static const WCHAR szAddLocal[] = {\r
- 'A','D','D','L','O','C','A','L',0};\r
-\r
- /* I do not know if this is where it should happen.. but */\r
-\r
- TRACE("Checking Install Level\n");\r
-\r
- sz = 10000;\r
- if (MSI_GetPropertyW(package,szlevel,level,&sz)==ERROR_SUCCESS)\r
- install_level = atoiW(level);\r
- else\r
- install_level = 1;\r
-\r
- sz = 0;\r
- rc = MSI_GetPropertyW(package,szAddLocal,NULL,&sz);\r
- if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA)\r
- {\r
- sz++;\r
- override = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));\r
- MSI_GetPropertyW(package, addlocal,override,&sz);\r
- }\r
- \r
- /*\r
- * Components FeatureState defaults to FALSE. The idea is we want to \r
- * enable the component is ANY feature that uses it is enabled to install\r
- */\r
- for(i = 0; i < package->loaded_features; i++)\r
- {\r
- BOOL feature_state= ((package->features[i].Level > 0) &&\r
- (package->features[i].Level <= install_level));\r
-\r
- if (override && (strcmpiW(override,all)==0 || \r
- strstrW(override,package->features[i].Feature)))\r
- {\r
- TRACE("Override of install level found\n");\r
- feature_state = TRUE;\r
- package->features[i].Enabled = feature_state;\r
- }\r
-\r
- TRACE("Feature %s has a state of %i\n",\r
- debugstr_w(package->features[i].Feature), feature_state);\r
- for( j = 0; j < package->features[i].ComponentCount; j++)\r
- {\r
- package->components[package->features[i].Components[j]].FeatureState\r
- |= feature_state;\r
- }\r
- } \r
- if (override != NULL)\r
- HeapFree(GetProcessHeap(),0,override);\r
- /* \r
- * So basically we ONLY want to install a component if its Enabled AND\r
- * FeatureState are both TRUE \r
- */\r
return ERROR_SUCCESS;\r
}\r
\r
+\r
static UINT ACTION_InstallValidate(MSIPACKAGE *package)\r
{\r
DWORD progress = 0;\r
+ DWORD total = 0;\r
static const WCHAR q1[]={\r
'S','E','L','E','C','T',' ','*',' ',\r
'F','R','O','M',' ','R','e','g','i','s','t','r','y',0};\r
UINT rc;\r
MSIQUERY * view;\r
MSIRECORD * row = 0;\r
+ int i;\r
\r
TRACE(" InstallValidate \n");\r
\r
MSI_ViewClose(view);\r
msiobj_release(&view->hdr);\r
\r
- ui_progress(package,0,progress+package->loaded_files,0,0);\r
+ total = total + progress * REG_PROGRESS_VALUE;\r
+ total = total + package->loaded_components * COMPONENT_PROGRESS_VALUE;\r
+ for (i=0; i < package->loaded_files; i++)\r
+ total += package->files[i].FileSize;\r
+ ui_progress(package,0,total,0,0);\r
\r
return ERROR_SUCCESS;\r
}\r
return rc;\r
}\r
\r
-static void resolve_keypath( MSIPACKAGE* package, INT\r
- component_index, WCHAR *keypath)\r
+static LPWSTR resolve_keypath( MSIPACKAGE* package, INT\r
+ component_index)\r
{\r
MSICOMPONENT* cmp = &package->components[component_index];\r
\r
if (cmp->KeyPath[0]==0)\r
{\r
- resolve_folder(package,cmp->Directory,keypath,FALSE,FALSE,NULL);\r
- return;\r
+ LPWSTR p = resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL);\r
+ return p;\r
}\r
if ((cmp->Attributes & 0x4) || (cmp->Attributes & 0x20))\r
{\r
FIXME("UNIMPLEMENTED keypath as Registry or ODBC Source\n");\r
- keypath[0]=0;\r
+ return NULL;\r
}\r
else\r
{\r
j = get_loaded_file(package,cmp->KeyPath);\r
\r
if (j>=0)\r
- strcpyW(keypath,package->files[j].TargetPath);\r
+ {\r
+ LPWSTR p = dupstrW(package->files[j].TargetPath);\r
+ return p;\r
+ }\r
}\r
+ return NULL;\r
}\r
\r
/*\r
*/\r
static UINT ACTION_ProcessComponents(MSIPACKAGE *package)\r
{\r
- WCHAR productcode[0x100];\r
+ LPWSTR productcode;\r
WCHAR squished_pc[0x100];\r
WCHAR squished_cc[0x100];\r
- DWORD sz;\r
UINT rc;\r
DWORD i;\r
HKEY hkey=0,hkey2=0,hkey3=0;\r
static const WCHAR szProductCode[]=\r
-{'P','r','o','d','u','c','t','C','o','d','e',0};\r
+ {'P','r','o','d','u','c','t','C','o','d','e',0};\r
static const WCHAR szInstaller[] = {\r
-'S','o','f','t','w','a','r','e','\\',\r
-'M','i','c','r','o','s','o','f','t','\\',\r
-'W','i','n','d','o','w','s','\\',\r
-'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',\r
-'I','n','s','t','a','l','l','e','r',0 };\r
+ 'S','o','f','t','w','a','r','e','\\',\r
+ 'M','i','c','r','o','s','o','f','t','\\',\r
+ 'W','i','n','d','o','w','s','\\',\r
+ 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',\r
+ 'I','n','s','t','a','l','l','e','r',0 };\r
static const WCHAR szFeatures[] = {\r
-'F','e','a','t','u','r','e','s',0 };\r
+ 'F','e','a','t','u','r','e','s',0 };\r
static const WCHAR szComponents[] = {\r
-'C','o','m','p','o','n','e','n','t','s',0 };\r
+ 'C','o','m','p','o','n','e','n','t','s',0 };\r
\r
if (!package)\r
return ERROR_INVALID_HANDLE;\r
\r
/* writes the Component and Features values to the registry */\r
- sz = 0x100;\r
- rc = MSI_GetPropertyW(package,szProductCode,productcode,&sz);\r
- if (rc != ERROR_SUCCESS)\r
- return ERROR_SUCCESS;\r
+ productcode = load_dynamic_property(package,szProductCode,&rc);\r
+ if (!productcode)\r
+ return rc;\r
\r
squash_guid(productcode,squished_pc);\r
rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller,&hkey);\r
rc = RegCreateKeyW(hkey,szComponents,&hkey2);\r
if (rc != ERROR_SUCCESS)\r
goto end;\r
- \r
+ \r
+ ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0);\r
for (i = 0; i < package->loaded_components; i++)\r
{\r
+ ui_progress(package,2,0,0,0);\r
if (package->components[i].ComponentId[0]!=0)\r
{\r
- WCHAR keypath[0x1000];\r
+ WCHAR *keypath = NULL;\r
MSIRECORD * uirow;\r
\r
squash_guid(package->components[i].ComponentId,squished_cc);\r
if (rc != ERROR_SUCCESS)\r
continue;\r
\r
- resolve_keypath(package,i,keypath);\r
-\r
- RegSetValueExW(hkey3,squished_pc,0,REG_SZ,(LPVOID)keypath,\r
+ keypath = resolve_keypath(package,i);\r
+ if (keypath)\r
+ {\r
+ RegSetValueExW(hkey3,squished_pc,0,REG_SZ,(LPVOID)keypath,\r
(strlenW(keypath)+1)*sizeof(WCHAR));\r
- RegCloseKey(hkey3);\r
+ RegCloseKey(hkey3);\r
\r
- /* UI stuff */\r
- uirow = MSI_CreateRecord(3);\r
- MSI_RecordSetStringW(uirow,1,productcode);\r
- MSI_RecordSetStringW(uirow,2,package->components[i].ComponentId);\r
- MSI_RecordSetStringW(uirow,3,keypath);\r
- ui_actiondata(package,szProcessComponents,uirow);\r
- msiobj_release( &uirow->hdr );\r
+ /* UI stuff */\r
+ uirow = MSI_CreateRecord(3);\r
+ MSI_RecordSetStringW(uirow,1,productcode);\r
+ MSI_RecordSetStringW(uirow,2,package->components[i].\r
+ ComponentId);\r
+ MSI_RecordSetStringW(uirow,3,keypath);\r
+ ui_actiondata(package,szProcessComponents,uirow);\r
+ msiobj_release( &uirow->hdr );\r
+ HeapFree(GetProcessHeap(),0,keypath);\r
+ }\r
}\r
} \r
end:\r
+ HeapFree(GetProcessHeap(), 0, productcode);\r
RegCloseKey(hkey2);\r
RegCloseKey(hkey);\r
return rc;\r
continue;\r
}\r
\r
- if (!package->components[index].Enabled ||\r
- !package->components[index].FeatureState)\r
+ if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)\r
{\r
TRACE("Skipping typelib reg due to disabled component\n");\r
msiobj_release(&row->hdr);\r
res = LoadTypeLib(package->files[index].TargetPath,&ptLib);\r
if (SUCCEEDED(res))\r
{\r
- WCHAR help[MAX_PATH];\r
+ LPWSTR help;\r
WCHAR helpid[0x100];\r
\r
sz = 0x100;\r
MSI_RecordGetStringW(row,6,helpid,&sz);\r
\r
- resolve_folder(package,helpid,help,FALSE,FALSE,NULL);\r
-\r
+ help = resolve_folder(package,helpid,FALSE,FALSE,NULL);\r
res = RegisterTypeLib(ptLib,package->files[index].TargetPath,help);\r
+ HeapFree(GetProcessHeap(),0,help);\r
+\r
if (!SUCCEEDED(res))\r
ERR("Failed to register type library %s\n",\r
debugstr_w(package->files[index].TargetPath));\r
MSIQUERY * view;\r
MSIRECORD * row = 0;\r
static const WCHAR ExecSeqQuery[] = \r
-{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','p','p','I'\r
-,'d',' ','w','h','e','r','e',' ','A','p','p','I','d','=','`','%','s','`',0};\r
- WCHAR Query[0x1000];\r
+ {'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','p','p','I'\r
+ ,'d',' ','w','h','e','r','e',' ','A','p','p','I','d','=','`','%','s','`',0};\r
HKEY hkey2,hkey3;\r
LPWSTR buffer=0;\r
\r
if (!package)\r
return ERROR_INVALID_HANDLE;\r
\r
- sprintfW(Query,ExecSeqQuery,clsid);\r
-\r
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);\r
+ rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, clsid);\r
if (rc != ERROR_SUCCESS)\r
return rc;\r
\r
LPWSTR deformated=0;\r
UINT size; \r
static const WCHAR szRemoteServerName[] =\r
-{'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0};\r
+ {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0};\r
buffer = load_dynamic_stringW(row,2);\r
size = deformat_string(package,buffer,&deformated);\r
RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,(LPVOID)deformated,\r
if (!MSI_RecordIsNull(row,3)) \r
{\r
static const WCHAR szLocalService[] =\r
-{'L','o','c','a','l','S','e','r','v','i','c','e',0};\r
+ {'L','o','c','a','l','S','e','r','v','i','c','e',0};\r
UINT size;\r
buffer = load_dynamic_stringW(row,3);\r
size = (strlenW(buffer)+1) * sizeof(WCHAR);\r
if (!MSI_RecordIsNull(row,4)) \r
{\r
static const WCHAR szService[] =\r
-{'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0};\r
+ {'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0};\r
UINT size;\r
buffer = load_dynamic_stringW(row,4);\r
size = (strlenW(buffer)+1) * sizeof(WCHAR);\r
if (!MSI_RecordIsNull(row,5)) \r
{\r
static const WCHAR szDLL[] =\r
-{'D','l','l','S','u','r','r','o','g','a','t','e',0};\r
+ {'D','l','l','S','u','r','r','o','g','a','t','e',0};\r
UINT size;\r
buffer = load_dynamic_stringW(row,5);\r
size = (strlenW(buffer)+1) * sizeof(WCHAR);\r
if (!MSI_RecordIsNull(row,6)) \r
{\r
static const WCHAR szActivate[] =\r
-{'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0};\r
+ {'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0};\r
static const WCHAR szY[] = {'Y',0};\r
\r
if (MSI_RecordGetInteger(row,6))\r
{\r
static const WCHAR szRunAs[] = {'R','u','n','A','s',0};\r
static const WCHAR szUser[] = \r
-{'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0};\r
+ {'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0};\r
\r
if (MSI_RecordGetInteger(row,7))\r
RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,34);\r
continue;\r
}\r
\r
- if (!package->components[index].Enabled ||\r
- !package->components[index].FeatureState)\r
+ if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)\r
{\r
TRACE("Skipping class reg due to disabled component\n");\r
msiobj_release(&row->hdr);\r
MSIQUERY * view;\r
MSIRECORD * row = 0;\r
static const WCHAR Query_t[] = \r
-{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','r','o','g'\r
-,'I','d',' ','w','h','e','r','e',' ','P','r','o','g','I','d',' ','=',' ','`'\r
-,'%','s','`',0};\r
- WCHAR Query[0x1000];\r
+ {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','r','o','g'\r
+ ,'I','d',' ','w','h','e','r','e',' ','P','r','o','g','I','d',' ','=',' ','`'\r
+ ,'%','s','`',0};\r
\r
if (!package)\r
return ERROR_INVALID_HANDLE;\r
\r
- sprintfW(Query,Query_t,parent);\r
-\r
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);\r
+ rc = ACTION_OpenQuery(package->db, &view, Query_t, parent);\r
if (rc != ERROR_SUCCESS)\r
return rc;\r
\r
}\r
\r
static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, \r
- LPWSTR FilePath)\r
+ LPWSTR *FilePath)\r
{\r
- WCHAR ProductCode[0x100];\r
- WCHAR SystemFolder[MAX_PATH];\r
- DWORD sz;\r
+ LPWSTR ProductCode;\r
+ LPWSTR SystemFolder;\r
+ LPWSTR dest;\r
+ UINT rc;\r
\r
static const WCHAR szInstaller[] = \r
-{'I','n','s','t','a','l','l','e','r','\\',0};\r
+ {'I','n','s','t','a','l','l','e','r','\\',0};\r
static const WCHAR szProductCode[] =\r
-{'P','r','o','d','u','c','t','C','o','d','e',0};\r
+ {'P','r','o','d','u','c','t','C','o','d','e',0};\r
static const WCHAR szFolder[] =\r
-{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};\r
+ {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};\r
\r
- sz = 0x100;\r
- MSI_GetPropertyW(package,szProductCode,ProductCode,&sz);\r
- if (strlenW(ProductCode)==0)\r
- return ERROR_FUNCTION_FAILED;\r
+ ProductCode = load_dynamic_property(package,szProductCode,&rc);\r
+ if (!ProductCode)\r
+ return rc;\r
\r
- sz = MAX_PATH;\r
- MSI_GetPropertyW(package,szFolder,SystemFolder,&sz);\r
- strcatW(SystemFolder,szInstaller); \r
- strcatW(SystemFolder,ProductCode);\r
- create_full_pathW(SystemFolder);\r
+ SystemFolder = load_dynamic_property(package,szFolder,NULL);\r
\r
- strcpyW(FilePath,SystemFolder);\r
- strcatW(FilePath,cszbs);\r
- strcatW(FilePath,icon_name);\r
+ dest = build_directory_name(3, SystemFolder, szInstaller, ProductCode);\r
+\r
+ create_full_pathW(dest);\r
+\r
+ *FilePath = build_directory_name(2, dest, icon_name);\r
+\r
+ HeapFree(GetProcessHeap(),0,SystemFolder);\r
+ HeapFree(GetProcessHeap(),0,ProductCode);\r
+ HeapFree(GetProcessHeap(),0,dest);\r
return ERROR_SUCCESS;\r
}\r
\r
\r
while (1)\r
{\r
- WCHAR target_file[MAX_PATH];\r
+ LPWSTR target_file, target_folder;\r
WCHAR buffer[0x100];\r
DWORD sz;\r
DWORD index;\r
continue;\r
}\r
\r
- if (!package->components[index].Enabled ||\r
- !package->components[index].FeatureState)\r
+ if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)\r
{\r
TRACE("Skipping shortcut creation due to disabled component\n");\r
msiobj_release(&row->hdr);\r
\r
sz = 0x100;\r
MSI_RecordGetStringW(row,2,buffer,&sz);\r
- resolve_folder(package, buffer,target_file,FALSE,FALSE,NULL);\r
+ target_folder = resolve_folder(package, buffer,FALSE,FALSE,NULL);\r
+\r
+ /* may be needed because of a bug somehwere else */\r
+ create_full_pathW(target_folder);\r
\r
sz = 0x100;\r
MSI_RecordGetStringW(row,3,buffer,&sz);\r
reduce_to_longfilename(buffer);\r
- strcatW(target_file,buffer);\r
- if (!strchrW(target_file,'.'))\r
- strcatW(target_file,szlnk);\r
+ if (!strchrW(buffer,'.') || strcmpiW(strchrW(buffer,'.'),szlnk))\r
+ strcatW(buffer,szlnk);\r
+ target_file = build_directory_name(2, target_folder, buffer);\r
+ HeapFree(GetProcessHeap(),0,target_folder);\r
\r
sz = 0x100;\r
MSI_RecordGetStringW(row,5,buffer,&sz);\r
\r
if (!MSI_RecordIsNull(row,9))\r
{\r
- WCHAR Path[MAX_PATH];\r
+ WCHAR *Path = NULL;\r
INT index; \r
\r
sz = 0x100;\r
MSI_RecordGetStringW(row,9,buffer,&sz);\r
\r
- build_icon_path(package,buffer,Path);\r
+ build_icon_path(package,buffer,&Path);\r
index = MSI_RecordGetInteger(row,10);\r
\r
IShellLinkW_SetIconLocation(sl,Path,index);\r
+ HeapFree(GetProcessHeap(),0,Path);\r
}\r
\r
if (!MSI_RecordIsNull(row,11))\r
\r
if (!MSI_RecordIsNull(row,12))\r
{\r
- WCHAR Path[MAX_PATH];\r
-\r
+ LPWSTR Path;\r
sz = 0x100;\r
MSI_RecordGetStringW(row,12,buffer,&sz);\r
- resolve_folder(package, buffer, Path, FALSE, FALSE, NULL);\r
+ Path = resolve_folder(package, buffer, FALSE, FALSE, NULL);\r
IShellLinkW_SetWorkingDirectory(sl,Path);\r
+ HeapFree(GetProcessHeap(), 0, Path);\r
}\r
\r
TRACE("Writing shortcut to %s\n",debugstr_w(target_file));\r
IPersistFile_Save(pf,target_file,FALSE);\r
- \r
+ \r
+ HeapFree(GetProcessHeap(),0,target_file); \r
+\r
IPersistFile_Release( pf );\r
IShellLinkW_Release( sl );\r
\r
while (1)\r
{\r
HANDLE the_file;\r
- WCHAR FilePath[MAX_PATH];\r
- WCHAR FileName[MAX_PATH];\r
+ WCHAR *FilePath=NULL;\r
+ WCHAR *FileName=NULL;\r
CHAR buffer[1024];\r
\r
rc = MSI_ViewFetch(view,&row);\r
break;\r
}\r
\r
- sz = MAX_PATH;\r
- MSI_RecordGetStringW(row,1,FileName,&sz);\r
- if (sz == 0)\r
+ FileName = load_dynamic_stringW(row,1);\r
+ if (!FileName)\r
{\r
ERR("Unable to get FileName\n");\r
msiobj_release(&row->hdr);\r
continue;\r
}\r
\r
- build_icon_path(package,FileName,FilePath);\r
+ build_icon_path(package,FileName,&FilePath);\r
+\r
+ HeapFree(GetProcessHeap(),0,FileName);\r
\r
TRACE("Creating icon file at %s\n",debugstr_w(FilePath));\r
\r
{\r
ERR("Unable to create file %s\n",debugstr_w(FilePath));\r
msiobj_release(&row->hdr);\r
+ HeapFree(GetProcessHeap(),0,FilePath);\r
continue;\r
}\r
\r
WriteFile(the_file,buffer,sz,&write,NULL);\r
} while (sz == 1024);\r
\r
+ HeapFree(GetProcessHeap(),0,FilePath);\r
+\r
CloseHandle(the_file);\r
msiobj_release(&row->hdr);\r
}\r
UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR\r
szPathBuf, DWORD* pcchPathBuf) \r
{\r
- WCHAR path[MAX_PATH];\r
- UINT rc;\r
+ LPWSTR path;\r
+ UINT rc = ERROR_FUNCTION_FAILED;\r
MSIPACKAGE *package;\r
\r
TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);\r
\r
package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);\r
- if( !package )\r
+ if (!package)\r
return ERROR_INVALID_HANDLE;\r
- rc = resolve_folder(package, szFolder, path, FALSE, FALSE, NULL);\r
+ path = resolve_folder(package, szFolder, FALSE, FALSE, NULL);\r
msiobj_release( &package->hdr );\r
\r
- if (rc == ERROR_SUCCESS && strlenW(path) > *pcchPathBuf)\r
+ if (path && (strlenW(path) > *pcchPathBuf))\r
{\r
*pcchPathBuf = strlenW(path)+1;\r
- return ERROR_MORE_DATA;\r
+ rc = ERROR_MORE_DATA;\r
}\r
- else if (rc == ERROR_SUCCESS)\r
+ else if (path)\r
{\r
*pcchPathBuf = strlenW(path)+1;\r
strcpyW(szPathBuf,path);\r
TRACE("Returning Path %s\n",debugstr_w(path));\r
+ rc = ERROR_SUCCESS;\r
}\r
+ HeapFree(GetProcessHeap(),0,path);\r
\r
return rc;\r
}\r
UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR\r
szPathBuf, DWORD* pcchPathBuf) \r
{\r
- WCHAR path[MAX_PATH];\r
- UINT rc;\r
+ LPWSTR path;\r
+ UINT rc = ERROR_FUNCTION_FAILED;\r
MSIPACKAGE *package;\r
\r
TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);\r
package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);\r
if( !package )\r
return ERROR_INVALID_HANDLE;\r
- rc = resolve_folder(package, szFolder, path, TRUE, FALSE, NULL);\r
+ path = resolve_folder(package, szFolder, TRUE, FALSE, NULL);\r
msiobj_release( &package->hdr );\r
\r
- if (rc == ERROR_SUCCESS && strlenW(path) > *pcchPathBuf)\r
+ if (path && strlenW(path) > *pcchPathBuf)\r
{\r
*pcchPathBuf = strlenW(path)+1;\r
- return ERROR_MORE_DATA;\r
+ rc = ERROR_MORE_DATA;\r
}\r
- else if (rc == ERROR_SUCCESS)\r
+ else if (path)\r
{\r
*pcchPathBuf = strlenW(path)+1;\r
strcpyW(szPathBuf,path);\r
TRACE("Returning Path %s\n",debugstr_w(path));\r
+ rc = ERROR_SUCCESS;\r
}\r
+ HeapFree(GetProcessHeap(),0,path);\r
\r
return rc;\r
}\r
LPCWSTR szFolderPath)\r
{\r
DWORD i;\r
- WCHAR path[MAX_PATH];\r
+ LPWSTR path = NULL;\r
+ LPWSTR path2 = NULL;\r
+ INT len;\r
MSIFOLDER *folder;\r
\r
TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));\r
if (GetFileAttributesW(szFolderPath) == INVALID_FILE_ATTRIBUTES)\r
return ERROR_FUNCTION_FAILED;\r
\r
- resolve_folder(package,szFolder,path,FALSE,FALSE,&folder);\r
+ path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);\r
\r
- if (!folder)\r
+ if (!path)\r
return ERROR_INVALID_PARAMETER;\r
\r
- strcpyW(folder->Property,szFolderPath);\r
+ if (folder->Property)\r
+ HeapFree(GetProcessHeap(),0,folder->Property);\r
\r
- for (i = 0; i < package->loaded_folders; i++)\r
- package->folders[i].ResolvedTarget[0]=0;\r
+ len = strlenW(szFolderPath);\r
\r
- for (i = 0; i < package->loaded_folders; i++)\r
- resolve_folder(package, package->folders[i].Directory, path, FALSE,\r
+ if (szFolderPath[len-1]!='\\')\r
+ {\r
+ len +=2;\r
+ folder->Property = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));\r
+ strcpyW(folder->Property,szFolderPath);\r
+ strcatW(folder->Property,cszbs);\r
+ }\r
+ else\r
+ folder->Property = dupstrW(szFolderPath);\r
+\r
+ if (strcmpiW(path, szFolderPath) == 0)\r
+ {\r
+ /*\r
+ * Resolved Target has not really changed, so just \r
+ * set this folder and do not recalculate everything.\r
+ */\r
+ HeapFree(GetProcessHeap(),0,folder->ResolvedTarget);\r
+ folder->ResolvedTarget = NULL;\r
+ path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL);\r
+ HeapFree(GetProcessHeap(),0,path2);\r
+ }\r
+ else\r
+ {\r
+ for (i = 0; i < package->loaded_folders; i++)\r
+ {\r
+ if (package->folders[i].ResolvedTarget)\r
+ HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);\r
+ package->folders[i].ResolvedTarget=NULL;\r
+ }\r
+\r
+ for (i = 0; i < package->loaded_folders; i++)\r
+ {\r
+ path2=resolve_folder(package, package->folders[i].Directory, FALSE,\r
TRUE, NULL);\r
+ HeapFree(GetProcessHeap(),0,path2);\r
+ }\r
+ }\r
+ HeapFree(GetProcessHeap(),0,path);\r
\r
return ERROR_SUCCESS;\r
}\r
return ret;\r
}\r
\r
-BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, DWORD iRunMode)\r
+/***********************************************************************\r
+ * MsiGetMode (MSI.@)\r
+ *\r
+ * Returns an internal installer state (if it is running in a mode iRunMode)\r
+ *\r
+ * PARAMS\r
+ * hInstall [I] Handle to the installation\r
+ * hRunMode [I] Checking run mode\r
+ * MSIRUNMODE_ADMIN Administrative mode\r
+ * MSIRUNMODE_ADVERTISE Advertisement mode\r
+ * MSIRUNMODE_MAINTENANCE Maintenance mode\r
+ * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled\r
+ * MSIRUNMODE_LOGENABLED Log file is writing\r
+ * MSIRUNMODE_OPERATIONS Operations in progress??\r
+ * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed\r
+ * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation\r
+ * MSIRUNMODE_CABINET Files from cabinet are installed\r
+ * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is supressed\r
+ * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is supressed\r
+ * MSIRUNMODE_RESERVED11 Reserved\r
+ * MSIRUNMODE_WINDOWS9X Running under Windows95/98\r
+ * MSIRUNMODE_ZAWENABLED Demand installation is supported\r
+ * MSIRUNMODE_RESERVED14 Reserved\r
+ * MSIRUNMODE_RESERVED15 Reserved\r
+ * MSIRUNMODE_SCHEDULED called from install script\r
+ * MSIRUNMODE_ROLLBACK called from rollback script\r
+ * MSIRUNMODE_COMMIT called from commit script\r
+ *\r
+ * RETURNS\r
+ * In the state: TRUE\r
+ * Not in the state: FALSE\r
+ *\r
+ */\r
+\r
+BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)\r
{\r
- FIXME("STUB (%li)\n",iRunMode);\r
- return FALSE;\r
+ FIXME("STUB (iRunMode=%i)\n",iRunMode);\r
+ return TRUE;\r
}\r
\r
/*\r
if (index < 0)\r
return ERROR_UNKNOWN_FEATURE;\r
\r
- package->features[index].State = iState;\r
+ package->features[index].ActionRequest= iState;\r
\r
return ERROR_SUCCESS;\r
}\r
return ERROR_UNKNOWN_FEATURE;\r
\r
if (piInstalled)\r
- *piInstalled = package->features[index].State;\r
+ *piInstalled = package->features[index].Installed;\r
\r
if (piAction)\r
- {\r
- if (package->features[index].Enabled)\r
- *piAction = INSTALLSTATE_LOCAL;\r
- else\r
- *piAction = INSTALLSTATE_UNKNOWN;\r
- }\r
+ *piAction = package->features[index].Action;\r
+\r
+ TRACE("returning %i %i\n",*piInstalled,*piAction);\r
\r
return ERROR_SUCCESS;\r
}\r
return ERROR_UNKNOWN_COMPONENT;\r
\r
if (piInstalled)\r
- *piInstalled = package->components[index].State;\r
+ *piInstalled = package->components[index].Installed;\r
\r
if (piAction)\r
- {\r
- if (package->components[index].Enabled &&\r
- package->components[index].FeatureState)\r
- *piAction = INSTALLSTATE_LOCAL;\r
- else\r
- *piAction = INSTALLSTATE_UNKNOWN;\r
- }\r
+ *piInstalled = package->components[index].Action;\r
\r
return ERROR_SUCCESS;\r
}\r
-/* A Bison parser, made from ./sql.y\r
- by GNU bison 1.35. */\r
-\r
-#define YYBISON 1 /* Identify Bison output. */\r
-\r
-#define yyparse SQL_parse\r
-#define yylex SQL_lex\r
-#define yyerror SQL_error\r
-#define yylval SQL_lval\r
-#define yychar SQL_char\r
-#define yydebug SQL_debug\r
-#define yynerrs SQL_nerrs\r
-# define TK_ABORT 257\r
-# define TK_AFTER 258\r
-# define TK_AGG_FUNCTION 259\r
-# define TK_ALL 260\r
-# define TK_AND 261\r
-# define TK_AS 262\r
-# define TK_ASC 263\r
-# define TK_BEFORE 264\r
-# define TK_BEGIN 265\r
-# define TK_BETWEEN 266\r
-# define TK_BITAND 267\r
-# define TK_BITNOT 268\r
-# define TK_BITOR 269\r
-# define TK_BY 270\r
-# define TK_CASCADE 271\r
-# define TK_CASE 272\r
-# define TK_CHAR 273\r
-# define TK_CHECK 274\r
-# define TK_CLUSTER 275\r
-# define TK_COLLATE 276\r
-# define TK_COLUMN 277\r
-# define TK_COMMA 278\r
-# define TK_COMMENT 279\r
-# define TK_COMMIT 280\r
-# define TK_CONCAT 281\r
-# define TK_CONFLICT 282\r
-# define TK_CONSTRAINT 283\r
-# define TK_COPY 284\r
-# define TK_CREATE 285\r
-# define TK_DEFAULT 286\r
-# define TK_DEFERRABLE 287\r
-# define TK_DEFERRED 288\r
-# define TK_DELETE 289\r
-# define TK_DELIMITERS 290\r
-# define TK_DESC 291\r
-# define TK_DISTINCT 292\r
-# define TK_DOT 293\r
-# define TK_DROP 294\r
-# define TK_EACH 295\r
-# define TK_ELSE 296\r
-# define TK_END 297\r
-# define TK_END_OF_FILE 298\r
-# define TK_EQ 299\r
-# define TK_EXCEPT 300\r
-# define TK_EXPLAIN 301\r
-# define TK_FAIL 302\r
-# define TK_FLOAT 303\r
-# define TK_FOR 304\r
-# define TK_FOREIGN 305\r
-# define TK_FROM 306\r
-# define TK_FUNCTION 307\r
-# define TK_GE 308\r
-# define TK_GLOB 309\r
-# define TK_GROUP 310\r
-# define TK_GT 311\r
-# define TK_HAVING 312\r
-# define TK_HOLD 313\r
-# define TK_IGNORE 314\r
-# define TK_ILLEGAL 315\r
-# define TK_IMMEDIATE 316\r
-# define TK_IN 317\r
-# define TK_INDEX 318\r
-# define TK_INITIALLY 319\r
-# define TK_ID 320\r
-# define TK_INSERT 321\r
-# define TK_INSTEAD 322\r
-# define TK_INT 323\r
-# define TK_INTEGER 324\r
-# define TK_INTERSECT 325\r
-# define TK_INTO 326\r
-# define TK_IS 327\r
-# define TK_ISNULL 328\r
-# define TK_JOIN 329\r
-# define TK_JOIN_KW 330\r
-# define TK_KEY 331\r
-# define TK_LE 332\r
-# define TK_LIKE 333\r
-# define TK_LIMIT 334\r
-# define TK_LONG 335\r
-# define TK_LONGCHAR 336\r
-# define TK_LP 337\r
-# define TK_LSHIFT 338\r
-# define TK_LT 339\r
-# define TK_LOCALIZABLE 340\r
-# define TK_MATCH 341\r
-# define TK_MINUS 342\r
-# define TK_NE 343\r
-# define TK_NOT 344\r
-# define TK_NOTNULL 345\r
-# define TK_NULL 346\r
-# define TK_OBJECT 347\r
-# define TK_OF 348\r
-# define TK_OFFSET 349\r
-# define TK_ON 350\r
-# define TK_OR 351\r
-# define TK_ORACLE_OUTER_JOIN 352\r
-# define TK_ORDER 353\r
-# define TK_PLUS 354\r
-# define TK_PRAGMA 355\r
-# define TK_PRIMARY 356\r
-# define TK_RAISE 357\r
-# define TK_REFERENCES 358\r
-# define TK_REM 359\r
-# define TK_REPLACE 360\r
-# define TK_RESTRICT 361\r
-# define TK_ROLLBACK 362\r
-# define TK_ROW 363\r
-# define TK_RP 364\r
-# define TK_RSHIFT 365\r
-# define TK_SELECT 366\r
-# define TK_SEMI 367\r
-# define TK_SET 368\r
-# define TK_SHORT 369\r
-# define TK_SLASH 370\r
-# define TK_SPACE 371\r
-# define TK_STAR 372\r
-# define TK_STATEMENT 373\r
-# define TK_STRING 374\r
-# define TK_TABLE 375\r
-# define TK_TEMP 376\r
-# define TK_THEN 377\r
-# define TK_TRANSACTION 378\r
-# define TK_TRIGGER 379\r
-# define TK_UMINUS 380\r
-# define TK_UNCLOSED_STRING 381\r
-# define TK_UNION 382\r
-# define TK_UNIQUE 383\r
-# define TK_UPDATE 384\r
-# define TK_UPLUS 385\r
-# define TK_USING 386\r
-# define TK_VACUUM 387\r
-# define TK_VALUES 388\r
-# define TK_VIEW 389\r
-# define TK_WHEN 390\r
-# define TK_WHERE 391\r
-# define TK_WILDCARD 392\r
-# define END_OF_FILE 393\r
-# define ILLEGAL 394\r
-# define SPACE 395\r
-# define UNCLOSED_STRING 396\r
-# define COMMENT 397\r
-# define FUNCTION 398\r
-# define COLUMN 399\r
-\r
-#line 1 "./sql.y"\r
-\r
-\r
-/*\r
- * Implementation of the Microsoft Installer (msi.dll)\r
- *\r
- * Copyright 2002-2004 Mike McCormack for CodeWeavers\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- */\r
-\r
-\r
-#include "config.h"\r
-\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "query.h"\r
-#include "wine/debug.h"\r
-#include "wine/unicode.h"\r
-\r
-#define YYLEX_PARAM info\r
-#define YYPARSE_PARAM info\r
-\r
-extern int SQL_error(const char *str);\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(msi);\r
-\r
-typedef struct tag_SQL_input\r
-{\r
- MSIDATABASE *db;\r
- LPCWSTR command;\r
- DWORD n, len;\r
- MSIVIEW **view; /* view structure for the resulting query */\r
-} SQL_input;\r
-\r
-static LPWSTR SQL_getstring( struct sql_str *str );\r
-static INT SQL_getint( SQL_input *sql );\r
-static int SQL_lex( void *SQL_lval, SQL_input *info);\r
-\r
-static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, \r
- string_list *columns );\r
-static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, \r
- string_list *columns );\r
-\r
-static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,\r
- string_list *keys);\r
-\r
-static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r );\r
-static struct expr * EXPR_column( LPWSTR );\r
-static struct expr * EXPR_ival( struct sql_str *);\r
-static struct expr * EXPR_sval( struct sql_str *);\r
-static struct expr * EXPR_wildcard(void);\r
-\r
-\r
-#line 73 "./sql.y"\r
-#ifndef YYSTYPE\r
-typedef union\r
-{\r
- struct sql_str str;\r
- LPWSTR string;\r
- string_list *column_list;\r
- value_list *val_list;\r
- MSIVIEW *query;\r
- struct expr *expr;\r
- USHORT column_type;\r
- create_col_info *column_info;\r
- column_assignment update_col_info;\r
-} yystype;\r
-# define YYSTYPE yystype\r
-# define YYSTYPE_IS_TRIVIAL 1\r
-#endif\r
-#ifndef YYDEBUG\r
-# define YYDEBUG 0\r
-#endif\r
-\r
-\r
-\r
-#define YYFINAL 121\r
-#define YYFLAG -32768\r
-#define YYNTBASE 147\r
-\r
-/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */\r
-#define YYTRANSLATE(x) ((unsigned)(x) <= 400 ? yytranslate[x] : 171)\r
-\r
-/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */\r
-static const short yytranslate[] =\r
-{\r
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r
- 2, 2, 2, 2, 2, 2, 1, 3, 4, 5,\r
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\r
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\r
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,\r
- 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,\r
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,\r
- 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,\r
- 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,\r
- 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,\r
- 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\r
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,\r
- 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,\r
- 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,\r
- 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,\r
- 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,\r
- 146\r
-};\r
-\r
-#if YYDEBUG\r
-static const short yyprhs[] =\r
-{\r
- 0, 0, 2, 4, 6, 8, 19, 31, 38, 46,\r
- 53, 58, 63, 66, 68, 71, 73, 77, 79, 84,\r
- 86, 88, 90, 92, 94, 96, 101, 103, 107, 112,\r
- 114, 118, 120, 123, 128, 132, 136, 140, 144, 148,\r
- 152, 156, 160, 164, 168, 172, 177, 179, 181, 183,\r
- 187, 189, 193, 197, 199, 201, 203, 205, 209, 211,\r
- 213, 215\r
-};\r
-static const short yyrhs[] =\r
-{\r
- 157, 0, 149, 0, 148, 0, 150, 0, 67, 72,\r
- 169, 83, 159, 110, 134, 83, 163, 110, 0, 67,\r
- 72, 169, 83, 159, 110, 134, 83, 163, 110, 122,\r
- 0, 31, 121, 169, 83, 151, 110, 0, 31, 121,\r
- 169, 83, 151, 110, 59, 0, 130, 169, 114, 164,\r
- 137, 161, 0, 152, 102, 77, 159, 0, 152, 24,\r
- 168, 153, 0, 168, 153, 0, 154, 0, 154, 86,\r
- 0, 155, 0, 155, 90, 92, 0, 19, 0, 19,\r
- 83, 156, 110, 0, 82, 0, 115, 0, 69, 0,\r
- 81, 0, 93, 0, 70, 0, 158, 99, 16, 159,\r
- 0, 158, 0, 112, 159, 160, 0, 112, 38, 159,\r
- 160, 0, 168, 0, 168, 24, 159, 0, 118, 0,\r
- 52, 169, 0, 52, 169, 137, 161, 0, 83, 161,\r
- 110, 0, 167, 45, 167, 0, 161, 7, 161, 0,\r
- 161, 97, 161, 0, 167, 45, 162, 0, 167, 57,\r
- 162, 0, 167, 85, 162, 0, 167, 78, 162, 0,\r
- 167, 54, 162, 0, 167, 89, 162, 0, 167, 73,\r
- 92, 0, 167, 73, 90, 92, 0, 167, 0, 166,\r
- 0, 166, 0, 163, 24, 166, 0, 165, 0, 165,\r
- 24, 164, 0, 168, 45, 166, 0, 70, 0, 120,\r
- 0, 138, 0, 168, 0, 169, 39, 170, 0, 170,\r
- 0, 170, 0, 66, 0, 120, 0\r
-};\r
-\r
-#endif\r
-\r
-#if YYDEBUG\r
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */\r
-static const short yyrline[] =\r
-{\r
- 0, 141, 147, 152, 157, 164, 173, 183, 194, 206,\r
- 217, 227, 247, 258, 263, 270, 275, 281, 286, 290,\r
- 294, 298, 302, 306, 312, 323, 335, 338, 353, 370,\r
- 384, 397, 403, 415, 433, 438, 442, 446, 450, 454,\r
- 458, 462, 466, 470, 474, 478, 484, 486, 489, 502,\r
- 517, 519, 527, 543, 548, 552, 558, 565, 570, 576,\r
- 583, 588\r
-};\r
-#endif\r
-\r
-\r
-#if (YYDEBUG) || defined YYERROR_VERBOSE\r
-\r
-/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */\r
-static const char *const yytname[] =\r
-{\r
- "$", "error", "$undefined.", "TK_ABORT", "TK_AFTER", "TK_AGG_FUNCTION", \r
- "TK_ALL", "TK_AND", "TK_AS", "TK_ASC", "TK_BEFORE", "TK_BEGIN", \r
- "TK_BETWEEN", "TK_BITAND", "TK_BITNOT", "TK_BITOR", "TK_BY", \r
- "TK_CASCADE", "TK_CASE", "TK_CHAR", "TK_CHECK", "TK_CLUSTER", \r
- "TK_COLLATE", "TK_COLUMN", "TK_COMMA", "TK_COMMENT", "TK_COMMIT", \r
- "TK_CONCAT", "TK_CONFLICT", "TK_CONSTRAINT", "TK_COPY", "TK_CREATE", \r
- "TK_DEFAULT", "TK_DEFERRABLE", "TK_DEFERRED", "TK_DELETE", \r
- "TK_DELIMITERS", "TK_DESC", "TK_DISTINCT", "TK_DOT", "TK_DROP", \r
- "TK_EACH", "TK_ELSE", "TK_END", "TK_END_OF_FILE", "TK_EQ", "TK_EXCEPT", \r
- "TK_EXPLAIN", "TK_FAIL", "TK_FLOAT", "TK_FOR", "TK_FOREIGN", "TK_FROM", \r
- "TK_FUNCTION", "TK_GE", "TK_GLOB", "TK_GROUP", "TK_GT", "TK_HAVING", \r
- "TK_HOLD", "TK_IGNORE", "TK_ILLEGAL", "TK_IMMEDIATE", "TK_IN", \r
- "TK_INDEX", "TK_INITIALLY", "TK_ID", "TK_INSERT", "TK_INSTEAD", \r
- "TK_INT", "TK_INTEGER", "TK_INTERSECT", "TK_INTO", "TK_IS", "TK_ISNULL", \r
- "TK_JOIN", "TK_JOIN_KW", "TK_KEY", "TK_LE", "TK_LIKE", "TK_LIMIT", \r
- "TK_LONG", "TK_LONGCHAR", "TK_LP", "TK_LSHIFT", "TK_LT", \r
- "TK_LOCALIZABLE", "TK_MATCH", "TK_MINUS", "TK_NE", "TK_NOT", \r
- "TK_NOTNULL", "TK_NULL", "TK_OBJECT", "TK_OF", "TK_OFFSET", "TK_ON", \r
- "TK_OR", "TK_ORACLE_OUTER_JOIN", "TK_ORDER", "TK_PLUS", "TK_PRAGMA", \r
- "TK_PRIMARY", "TK_RAISE", "TK_REFERENCES", "TK_REM", "TK_REPLACE", \r
- "TK_RESTRICT", "TK_ROLLBACK", "TK_ROW", "TK_RP", "TK_RSHIFT", \r
- "TK_SELECT", "TK_SEMI", "TK_SET", "TK_SHORT", "TK_SLASH", "TK_SPACE", \r
- "TK_STAR", "TK_STATEMENT", "TK_STRING", "TK_TABLE", "TK_TEMP", \r
- "TK_THEN", "TK_TRANSACTION", "TK_TRIGGER", "TK_UMINUS", \r
- "TK_UNCLOSED_STRING", "TK_UNION", "TK_UNIQUE", "TK_UPDATE", "TK_UPLUS", \r
- "TK_USING", "TK_VACUUM", "TK_VALUES", "TK_VIEW", "TK_WHEN", "TK_WHERE", \r
- "TK_WILDCARD", "END_OF_FILE", "ILLEGAL", "SPACE", "UNCLOSED_STRING", \r
- "COMMENT", "FUNCTION", "COLUMN", "AGG_FUNCTION.", "onequery", \r
- "oneinsert", "onecreate", "oneupdate", "table_def", "column_def", \r
- "column_type", "data_type_l", "data_type", "data_count", "oneselect", \r
- "unorderedsel", "selcollist", "from", "expr", "val", "constlist", \r
- "update_assign_list", "column_assignment", "const_val", "column_val", \r
- "column", "table", "string_or_id", 0\r
-};\r
-#endif\r
-\r
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */\r
-static const short yyr1[] =\r
-{\r
- 0, 147, 147, 147, 147, 148, 148, 149, 149, 150,\r
- 151, 152, 152, 153, 153, 154, 154, 155, 155, 155,\r
- 155, 155, 155, 155, 156, 157, 157, 158, 158, 159,\r
- 159, 159, 160, 160, 161, 161, 161, 161, 161, 161,\r
- 161, 161, 161, 161, 161, 161, 162, 162, 163, 163,\r
- 164, 164, 165, 166, 166, 166, 167, 168, 168, 169,\r
- 170, 170\r
-};\r
-\r
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */\r
-static const short yyr2[] =\r
-{\r
- 0, 1, 1, 1, 1, 10, 11, 6, 7, 6,\r
- 4, 4, 2, 1, 2, 1, 3, 1, 4, 1,\r
- 1, 1, 1, 1, 1, 4, 1, 3, 4, 1,\r
- 3, 1, 2, 4, 3, 3, 3, 3, 3, 3,\r
- 3, 3, 3, 3, 3, 4, 1, 1, 1, 3,\r
- 1, 3, 3, 1, 1, 1, 1, 3, 1, 1,\r
- 1, 1\r
-};\r
-\r
-/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE\r
- doesn't specify something else to do. Zero means the default is an\r
- error. */\r
-static const short yydefact[] =\r
-{\r
- 0, 0, 0, 0, 0, 3, 2, 4, 1, 26,\r
- 0, 0, 0, 60, 31, 61, 0, 29, 0, 58,\r
- 0, 59, 0, 0, 0, 0, 0, 27, 0, 0,\r
- 0, 0, 0, 0, 28, 32, 30, 57, 0, 50,\r
- 0, 25, 0, 0, 0, 0, 0, 0, 0, 0,\r
- 7, 0, 0, 17, 21, 22, 19, 23, 20, 12,\r
- 13, 15, 0, 0, 33, 0, 56, 9, 51, 53,\r
- 54, 55, 52, 8, 0, 0, 0, 14, 0, 0,\r
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
- 11, 10, 24, 0, 16, 0, 34, 36, 37, 54,\r
- 38, 47, 35, 42, 46, 39, 0, 44, 41, 40,\r
- 43, 18, 0, 48, 45, 0, 5, 49, 6, 0,\r
- 0, 0\r
-};\r
-\r
-static const short yydefgoto[] =\r
-{\r
- 119, 5, 6, 7, 42, 43, 59, 60, 61, 93,\r
- 8, 9, 16, 27, 64, 100, 112, 38, 39, 101,\r
- 65, 66, 18, 19\r
-};\r
-\r
-static const short yypact[] =\r
-{\r
- -30, -113, -49, -34, -50,-32768,-32768,-32768,-32768, -79,\r
- -50, -50, -52,-32768,-32768,-32768, -25, 4, -10, 0,\r
- -72,-32768, 30, -36, -35, -25, -50,-32768, -52, -50,\r
- -50, -52, -50, -52,-32768, -87,-32768,-32768, -84, 33,\r
- 13,-32768, -51, -15, -17, -41, -53, -53, -50, -58,\r
- 1, -50, -5, -8,-32768,-32768,-32768,-32768,-32768,-32768,\r
- -13, -9, -57, -53, -4, 47,-32768, -4,-32768,-32768,\r
- -32768,-32768,-32768,-32768, -17, -52, 18,-32768, -3, 11,\r
- -7, -53, -53, -59, -59, -59, -71, -59, -59, -59,\r
- -32768,-32768,-32768, -14,-32768, -58,-32768, -4, -4, 56,\r
- -32768,-32768,-32768,-32768,-32768,-32768, 5,-32768,-32768,-32768,\r
- -32768,-32768, -19,-32768,-32768, -58, -23,-32768,-32768, 102,\r
- 108,-32768\r
-};\r
-\r
-static const short yypgoto[] =\r
-{\r
- -32768,-32768,-32768,-32768,-32768,-32768, 40,-32768,-32768,-32768,\r
- -32768,-32768, 10, 93, -37, 28,-32768, 71,-32768, -32,\r
- 22, 3, 14, 45\r
-};\r
-\r
-\r
-#define YYLAST 136\r
-\r
-\r
-static const short yytable[] =\r
-{\r
- 81, 1, 53, 81, 12, 115, 17, 13, 10, 51,\r
- 67, 69, 69, 13, 13, 17, 13, 72, 20, 106,\r
- 22, 107, 25, 11, 23, 24, 80, 26, 28, 29,\r
- 63, 17, 13, 40, 17, 44, 17, 2, 36, -59,\r
- 35, 41, 30, 45, 97, 98, 31, 32, 33, 21,\r
- 46, 40, 54, 47, 74, 21, 21, 48, 49, 50,\r
- 73, 99, 70, 113, 55, 56, 14, 15, 15, 62,\r
- 15, 21, 75, 77, 37, 76, 57, 79, 17, 71,\r
- 71, 78, 3, 117, 14, 91, 15, 52, 92, 94,\r
- 82, 116, 83, 82, 95, -61, 111, 114, 58, 118,\r
- 4, 84, 120, 96, 85, 102, 104, 104, 121, 104,\r
- 104, 104, 103, 105, 90, 108, 109, 110, 34, 68,\r
- 86, 0, 0, 0, 0, 87, 0, 0, 0, 0,\r
- 0, 0, 88, 0, 0, 0, 89\r
-};\r
-\r
-static const short yycheck[] =\r
-{\r
- 7, 31, 19, 7, 38, 24, 3, 66, 121, 24,\r
- 47, 70, 70, 66, 66, 12, 66, 49, 4, 90,\r
- 99, 92, 12, 72, 10, 11, 63, 52, 24, 39,\r
- 83, 28, 66, 30, 31, 32, 33, 67, 28, 39,\r
- 26, 31, 114, 33, 81, 82, 16, 83, 83, 4,\r
- 137, 48, 69, 137, 51, 10, 11, 24, 45, 110,\r
- 59, 120, 120, 95, 81, 82, 118, 120, 120, 110,\r
- 120, 26, 77, 86, 29, 83, 93, 134, 75, 138,\r
- 138, 90, 112, 115, 118, 75, 120, 102, 70, 92,\r
- 97, 110, 45, 97, 83, 39, 110, 92, 115, 122,\r
- 130, 54, 0, 110, 57, 83, 84, 85, 0, 87,\r
- 88, 89, 84, 85, 74, 87, 88, 89, 25, 48,\r
- 73, -1, -1, -1, -1, 78, -1, -1, -1, -1,\r
- -1, -1, 85, -1, -1, -1, 89\r
-};\r
-#define YYPURE 1\r
-\r
-/* -*-C-*- Note some compilers choke on comments on `#line' lines. */\r
-#line 3 "/usr/share/bison/bison.simple"\r
-\r
-/* Skeleton output parser for bison,\r
-\r
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software\r
- Foundation, Inc.\r
-\r
- This program is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2, or (at your option)\r
- any later version.\r
-\r
- This program is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with this program; if not, write to the Free Software\r
- Foundation, Inc., 59 Temple Place - Suite 330,\r
- Boston, MA 02111-1307, USA. */\r
-\r
-/* As a special exception, when this file is copied by Bison into a\r
- Bison output file, you may use that output file without restriction.\r
- This special exception was added by the Free Software Foundation\r
- in version 1.24 of Bison. */\r
-\r
-/* This is the parser code that is written into each bison parser when\r
- the %semantic_parser declaration is not specified in the grammar.\r
- It was written by Richard Stallman by simplifying the hairy parser\r
- used when %semantic_parser is specified. */\r
-\r
-/* All symbols defined below should begin with yy or YY, to avoid\r
- infringing on user name space. This should be done even for local\r
- variables, as they might otherwise be expanded by user macros.\r
- There are some unavoidable exceptions within include files to\r
- define necessary library symbols; they are noted "INFRINGES ON\r
- USER NAME SPACE" below. */\r
-\r
-#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE)\r
-\r
-/* The parser invokes alloca or malloc; define the necessary symbols. */\r
-\r
-# if YYSTACK_USE_ALLOCA\r
-# define YYSTACK_ALLOC alloca\r
-# else\r
-# ifndef YYSTACK_USE_ALLOCA\r
-# if defined (alloca) || defined (_ALLOCA_H)\r
-# define YYSTACK_ALLOC alloca\r
-# else\r
-# ifdef __GNUC__\r
-# define YYSTACK_ALLOC __builtin_alloca\r
-# endif\r
-# endif\r
-# endif\r
-# endif\r
-\r
-# ifdef YYSTACK_ALLOC\r
- /* Pacify GCC's `empty if-body' warning. */\r
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)\r
-# else\r
-# if defined (__STDC__) || defined (__cplusplus)\r
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */\r
-# define YYSIZE_T size_t\r
-# endif\r
-# define YYSTACK_ALLOC malloc\r
-# define YYSTACK_FREE free\r
-# endif\r
-#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */\r
-\r
-\r
-#if (! defined (yyoverflow) \\r
- && (! defined (__cplusplus) \\r
- || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))\r
-\r
-/* A type that is properly aligned for any stack member. */\r
-union yyalloc\r
-{\r
- short yyss;\r
- YYSTYPE yyvs;\r
-# if YYLSP_NEEDED\r
- YYLTYPE yyls;\r
-# endif\r
-};\r
-\r
-/* The size of the maximum gap between one aligned stack and the next. */\r
-# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)\r
-\r
-/* The size of an array large to enough to hold all stacks, each with\r
- N elements. */\r
-# if YYLSP_NEEDED\r
-# define YYSTACK_BYTES(N) \\r
- ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \\r
- + 2 * YYSTACK_GAP_MAX)\r
-# else\r
-# define YYSTACK_BYTES(N) \\r
- ((N) * (sizeof (short) + sizeof (YYSTYPE)) \\r
- + YYSTACK_GAP_MAX)\r
-# endif\r
-\r
-/* Copy COUNT objects from FROM to TO. The source and destination do\r
- not overlap. */\r
-# ifndef YYCOPY\r
-# if 1 < __GNUC__\r
-# define YYCOPY(To, From, Count) \\r
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))\r
-# else\r
-# define YYCOPY(To, From, Count) \\r
- do \\r
- { \\r
- register YYSIZE_T yyi; \\r
- for (yyi = 0; yyi < (Count); yyi++) \\r
- (To)[yyi] = (From)[yyi]; \\r
- } \\r
- while (0)\r
-# endif\r
-# endif\r
-\r
-/* Relocate STACK from its old location to the new one. The\r
- local variables YYSIZE and YYSTACKSIZE give the old and new number of\r
- elements in the stack, and YYPTR gives the new location of the\r
- stack. Advance YYPTR to a properly aligned location for the next\r
- stack. */\r
-# define YYSTACK_RELOCATE(Stack) \\r
- do \\r
- { \\r
- YYSIZE_T yynewbytes; \\r
- YYCOPY (&yyptr->Stack, Stack, yysize); \\r
- Stack = &yyptr->Stack; \\r
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \\r
- yyptr += yynewbytes / sizeof (*yyptr); \\r
- } \\r
- while (0)\r
-\r
-#endif\r
-\r
-\r
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)\r
-# define YYSIZE_T __SIZE_TYPE__\r
-#endif\r
-#if ! defined (YYSIZE_T) && defined (size_t)\r
-# define YYSIZE_T size_t\r
-#endif\r
-#if ! defined (YYSIZE_T)\r
-# if defined (__STDC__) || defined (__cplusplus)\r
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */\r
-# define YYSIZE_T size_t\r
-# endif\r
-#endif\r
-#if ! defined (YYSIZE_T)\r
-# define YYSIZE_T unsigned int\r
-#endif\r
-\r
-#define yyerrok (yyerrstatus = 0)\r
-#define yyclearin (yychar = YYEMPTY)\r
-#define YYEMPTY -2\r
-#define YYEOF 0\r
-#define YYACCEPT goto yyacceptlab\r
-#define YYABORT goto yyabortlab\r
-#define YYERROR goto yyerrlab1\r
-/* Like YYERROR except do call yyerror. This remains here temporarily\r
- to ease the transition to the new meaning of YYERROR, for GCC.\r
- Once GCC version 2 has supplanted version 1, this can go. */\r
-#define YYFAIL goto yyerrlab\r
-#define YYRECOVERING() (!!yyerrstatus)\r
-#define YYBACKUP(Token, Value) \\r
-do \\r
- if (yychar == YYEMPTY && yylen == 1) \\r
- { \\r
- yychar = (Token); \\r
- yylval = (Value); \\r
- yychar1 = YYTRANSLATE (yychar); \\r
- YYPOPSTACK; \\r
- goto yybackup; \\r
- } \\r
- else \\r
- { \\r
- yyerror ("syntax error: cannot back up"); \\r
- YYERROR; \\r
- } \\r
-while (0)\r
-\r
-#define YYTERROR 1\r
-#define YYERRCODE 256\r
-\r
-\r
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions\r
- are run).\r
-\r
- When YYLLOC_DEFAULT is run, CURRENT is set the location of the\r
- first token. By default, to implement support for ranges, extend\r
- its range to the last symbol. */\r
-\r
-#ifndef YYLLOC_DEFAULT\r
-# define YYLLOC_DEFAULT(Current, Rhs, N) \\r
- Current.last_line = Rhs[N].last_line; \\r
- Current.last_column = Rhs[N].last_column;\r
-#endif\r
-\r
-\r
-/* YYLEX -- calling `yylex' with the right arguments. */\r
-\r
-#if YYPURE\r
-# if YYLSP_NEEDED\r
-# ifdef YYLEX_PARAM\r
-# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)\r
-# else\r
-# define YYLEX yylex (&yylval, &yylloc)\r
-# endif\r
-# else /* !YYLSP_NEEDED */\r
-# ifdef YYLEX_PARAM\r
-# define YYLEX yylex (&yylval, YYLEX_PARAM)\r
-# else\r
-# define YYLEX yylex (&yylval)\r
-# endif\r
-# endif /* !YYLSP_NEEDED */\r
-#else /* !YYPURE */\r
-# define YYLEX yylex ()\r
-#endif /* !YYPURE */\r
-\r
-\r
-/* Enable debugging if requested. */\r
-#if YYDEBUG\r
-\r
-# ifndef YYFPRINTF\r
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */\r
-# define YYFPRINTF fprintf\r
-# endif\r
-\r
-# define YYDPRINTF(Args) \\r
-do { \\r
- if (yydebug) \\r
- YYFPRINTF Args; \\r
-} while (0)\r
-/* Nonzero means print parse trace. It is left uninitialized so that\r
- multiple parsers can coexist. */\r
-int yydebug;\r
-#else /* !YYDEBUG */\r
-# define YYDPRINTF(Args)\r
-#endif /* !YYDEBUG */\r
-\r
-/* YYINITDEPTH -- initial size of the parser's stacks. */\r
-#ifndef YYINITDEPTH\r
-# define YYINITDEPTH 200\r
-#endif\r
-\r
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only\r
- if the built-in stack extension method is used).\r
-\r
- Do not make this value too large; the results are undefined if\r
- SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)\r
- evaluated with infinite-precision integer arithmetic. */\r
-\r
-#if YYMAXDEPTH == 0\r
-# undef YYMAXDEPTH\r
-#endif\r
-\r
-#ifndef YYMAXDEPTH\r
-# define YYMAXDEPTH 10000\r
-#endif\r
-\f\r
-#ifdef YYERROR_VERBOSE\r
-\r
-# ifndef yystrlen\r
-# if defined (__GLIBC__) && defined (_STRING_H)\r
-# define yystrlen strlen\r
-# else\r
-/* Return the length of YYSTR. */\r
-static YYSIZE_T\r
-# if defined (__STDC__) || defined (__cplusplus)\r
-yystrlen (const char *yystr)\r
-# else\r
-yystrlen (yystr)\r
- const char *yystr;\r
-# endif\r
-{\r
- register const char *yys = yystr;\r
-\r
- while (*yys++ != '\0')\r
- continue;\r
-\r
- return yys - yystr - 1;\r
-}\r
-# endif\r
-# endif\r
-\r
-# ifndef yystpcpy\r
-# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)\r
-# define yystpcpy stpcpy\r
-# else\r
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in\r
- YYDEST. */\r
-static char *\r
-# if defined (__STDC__) || defined (__cplusplus)\r
-yystpcpy (char *yydest, const char *yysrc)\r
-# else\r
-yystpcpy (yydest, yysrc)\r
- char *yydest;\r
- const char *yysrc;\r
-# endif\r
-{\r
- register char *yyd = yydest;\r
- register const char *yys = yysrc;\r
-\r
- while ((*yyd++ = *yys++) != '\0')\r
- continue;\r
-\r
- return yyd - 1;\r
-}\r
-# endif\r
-# endif\r
-#endif\r
-\f\r
-#line 315 "/usr/share/bison/bison.simple"\r
-\r
-\r
-/* The user can define YYPARSE_PARAM as the name of an argument to be passed\r
- into yyparse. The argument should have type void *.\r
- It should actually point to an object.\r
- Grammar actions can access the variable by casting it\r
- to the proper pointer type. */\r
-\r
-#ifdef YYPARSE_PARAM\r
-# if defined (__STDC__) || defined (__cplusplus)\r
-# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM\r
-# define YYPARSE_PARAM_DECL\r
-# else\r
-# define YYPARSE_PARAM_ARG YYPARSE_PARAM\r
-# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;\r
-# endif\r
-#else /* !YYPARSE_PARAM */\r
-# define YYPARSE_PARAM_ARG\r
-# define YYPARSE_PARAM_DECL\r
-#endif /* !YYPARSE_PARAM */\r
-\r
-/* Prevent warning if -Wstrict-prototypes. */\r
-#ifdef __GNUC__\r
-# ifdef YYPARSE_PARAM\r
-int yyparse (void *);\r
-# else\r
-int yyparse (void);\r
-# endif\r
-#endif\r
-\r
-/* YY_DECL_VARIABLES -- depending whether we use a pure parser,\r
- variables are global, or local to YYPARSE. */\r
-\r
-#define YY_DECL_NON_LSP_VARIABLES \\r
-/* The lookahead symbol. */ \\r
-int yychar; \\r
- \\r
-/* The semantic value of the lookahead symbol. */ \\r
-YYSTYPE yylval; \\r
- \\r
-/* Number of parse errors so far. */ \\r
-int yynerrs;\r
-\r
-#if YYLSP_NEEDED\r
-# define YY_DECL_VARIABLES \\r
-YY_DECL_NON_LSP_VARIABLES \\r
- \\r
-/* Location data for the lookahead symbol. */ \\r
-YYLTYPE yylloc;\r
-#else\r
-# define YY_DECL_VARIABLES \\r
-YY_DECL_NON_LSP_VARIABLES\r
-#endif\r
-\r
-\r
-/* If nonreentrant, generate the variables here. */\r
-\r
-#if !YYPURE\r
-YY_DECL_VARIABLES\r
-#endif /* !YYPURE */\r
-\r
-int\r
-yyparse (YYPARSE_PARAM_ARG)\r
- YYPARSE_PARAM_DECL\r
-{\r
- /* If reentrant, generate the variables here. */\r
-#if YYPURE\r
- YY_DECL_VARIABLES\r
-#endif /* !YYPURE */\r
-\r
- register int yystate;\r
- register int yyn;\r
- int yyresult;\r
- /* Number of tokens to shift before error messages enabled. */\r
- int yyerrstatus;\r
- /* Lookahead token as an internal (translated) token number. */\r
- int yychar1 = 0;\r
-\r
- /* Three stacks and their tools:\r
- `yyss': related to states,\r
- `yyvs': related to semantic values,\r
- `yyls': related to locations.\r
-\r
- Refer to the stacks thru separate pointers, to allow yyoverflow\r
- to reallocate them elsewhere. */\r
-\r
- /* The state stack. */\r
- short yyssa[YYINITDEPTH];\r
- short *yyss = yyssa;\r
- register short *yyssp;\r
-\r
- /* The semantic value stack. */\r
- YYSTYPE yyvsa[YYINITDEPTH];\r
- YYSTYPE *yyvs = yyvsa;\r
- register YYSTYPE *yyvsp;\r
-\r
-#if YYLSP_NEEDED\r
- /* The location stack. */\r
- YYLTYPE yylsa[YYINITDEPTH];\r
- YYLTYPE *yyls = yylsa;\r
- YYLTYPE *yylsp;\r
-#endif\r
-\r
-#if YYLSP_NEEDED\r
-# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)\r
-#else\r
-# define YYPOPSTACK (yyvsp--, yyssp--)\r
-#endif\r
-\r
- YYSIZE_T yystacksize = YYINITDEPTH;\r
-\r
-\r
- /* The variables used to return semantic value and location from the\r
- action routines. */\r
- YYSTYPE yyval;\r
-#if YYLSP_NEEDED\r
- YYLTYPE yyloc;\r
-#endif\r
-\r
- /* When reducing, the number of symbols on the RHS of the reduced\r
- rule. */\r
- int yylen;\r
-\r
- YYDPRINTF ((stderr, "Starting parse\n"));\r
-\r
- yystate = 0;\r
- yyerrstatus = 0;\r
- yynerrs = 0;\r
- yychar = YYEMPTY; /* Cause a token to be read. */\r
-\r
- /* Initialize stack pointers.\r
- Waste one element of value and location stack\r
- so that they stay on the same level as the state stack.\r
- The wasted elements are never initialized. */\r
-\r
- yyssp = yyss;\r
- yyvsp = yyvs;\r
-#if YYLSP_NEEDED\r
- yylsp = yyls;\r
-#endif\r
- goto yysetstate;\r
-\r
-/*------------------------------------------------------------.\r
-| yynewstate -- Push a new state, which is found in yystate. |\r
-`------------------------------------------------------------*/\r
- yynewstate:\r
- /* In all cases, when you get here, the value and location stacks\r
- have just been pushed. so pushing a state here evens the stacks.\r
- */\r
- yyssp++;\r
-\r
- yysetstate:\r
- *yyssp = yystate;\r
-\r
- if (yyssp >= yyss + yystacksize - 1)\r
- {\r
- /* Get the current used size of the three stacks, in elements. */\r
- YYSIZE_T yysize = yyssp - yyss + 1;\r
-\r
-#ifdef yyoverflow\r
- {\r
- /* Give user a chance to reallocate the stack. Use copies of\r
- these so that the &'s don't force the real ones into\r
- memory. */\r
- YYSTYPE *yyvs1 = yyvs;\r
- short *yyss1 = yyss;\r
-\r
- /* Each stack pointer address is followed by the size of the\r
- data in use in that stack, in bytes. */\r
-# if YYLSP_NEEDED\r
- YYLTYPE *yyls1 = yyls;\r
- /* This used to be a conditional around just the two extra args,\r
- but that might be undefined if yyoverflow is a macro. */\r
- yyoverflow ("parser stack overflow",\r
- &yyss1, yysize * sizeof (*yyssp),\r
- &yyvs1, yysize * sizeof (*yyvsp),\r
- &yyls1, yysize * sizeof (*yylsp),\r
- &yystacksize);\r
- yyls = yyls1;\r
-# else\r
- yyoverflow ("parser stack overflow",\r
- &yyss1, yysize * sizeof (*yyssp),\r
- &yyvs1, yysize * sizeof (*yyvsp),\r
- &yystacksize);\r
-# endif\r
- yyss = yyss1;\r
- yyvs = yyvs1;\r
- }\r
-#else /* no yyoverflow */\r
-# ifndef YYSTACK_RELOCATE\r
- goto yyoverflowlab;\r
-# else\r
- /* Extend the stack our own way. */\r
- if (yystacksize >= YYMAXDEPTH)\r
- goto yyoverflowlab;\r
- yystacksize *= 2;\r
- if (yystacksize > YYMAXDEPTH)\r
- yystacksize = YYMAXDEPTH;\r
-\r
- {\r
- short *yyss1 = yyss;\r
- union yyalloc *yyptr =\r
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));\r
- if (! yyptr)\r
- goto yyoverflowlab;\r
- YYSTACK_RELOCATE (yyss);\r
- YYSTACK_RELOCATE (yyvs);\r
-# if YYLSP_NEEDED\r
- YYSTACK_RELOCATE (yyls);\r
-# endif\r
-# undef YYSTACK_RELOCATE\r
- if (yyss1 != yyssa)\r
- YYSTACK_FREE (yyss1);\r
- }\r
-# endif\r
-#endif /* no yyoverflow */\r
-\r
- yyssp = yyss + yysize - 1;\r
- yyvsp = yyvs + yysize - 1;\r
-#if YYLSP_NEEDED\r
- yylsp = yyls + yysize - 1;\r
-#endif\r
-\r
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",\r
- (unsigned long int) yystacksize));\r
-\r
- if (yyssp >= yyss + yystacksize - 1)\r
- YYABORT;\r
- }\r
-\r
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));\r
-\r
- goto yybackup;\r
-\r
-\r
-/*-----------.\r
-| yybackup. |\r
-`-----------*/\r
-yybackup:\r
-\r
-/* Do appropriate processing given the current state. */\r
-/* Read a lookahead token if we need one and don't already have one. */\r
-/* yyresume: */\r
-\r
- /* First try to decide what to do without reference to lookahead token. */\r
-\r
- yyn = yypact[yystate];\r
- if (yyn == YYFLAG)\r
- goto yydefault;\r
-\r
- /* Not known => get a lookahead token if don't already have one. */\r
-\r
- /* yychar is either YYEMPTY or YYEOF\r
- or a valid token in external form. */\r
-\r
- if (yychar == YYEMPTY)\r
- {\r
- YYDPRINTF ((stderr, "Reading a token: "));\r
- yychar = YYLEX;\r
- }\r
-\r
- /* Convert token to internal form (in yychar1) for indexing tables with */\r
-\r
- if (yychar <= 0) /* This means end of input. */\r
- {\r
- yychar1 = 0;\r
- yychar = YYEOF; /* Don't call YYLEX any more */\r
-\r
- YYDPRINTF ((stderr, "Now at end of input.\n"));\r
- }\r
- else\r
- {\r
- yychar1 = YYTRANSLATE (yychar);\r
-\r
-#if YYDEBUG\r
- /* We have to keep this `#if YYDEBUG', since we use variables\r
- which are defined only if `YYDEBUG' is set. */\r
- if (yydebug)\r
- {\r
- YYFPRINTF (stderr, "Next token is %d (%s",\r
- yychar, yytname[yychar1]);\r
- /* Give the individual parser a way to print the precise\r
- meaning of a token, for further debugging info. */\r
-# ifdef YYPRINT\r
- YYPRINT (stderr, yychar, yylval);\r
-# endif\r
- YYFPRINTF (stderr, ")\n");\r
- }\r
-#endif\r
- }\r
-\r
- yyn += yychar1;\r
- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)\r
- goto yydefault;\r
-\r
- yyn = yytable[yyn];\r
-\r
- /* yyn is what to do for this token type in this state.\r
- Negative => reduce, -yyn is rule number.\r
- Positive => shift, yyn is new state.\r
- New state is final state => don't bother to shift,\r
- just return success.\r
- 0, or most negative number => error. */\r
-\r
- if (yyn < 0)\r
- {\r
- if (yyn == YYFLAG)\r
- goto yyerrlab;\r
- yyn = -yyn;\r
- goto yyreduce;\r
- }\r
- else if (yyn == 0)\r
- goto yyerrlab;\r
-\r
- if (yyn == YYFINAL)\r
- YYACCEPT;\r
-\r
- /* Shift the lookahead token. */\r
- YYDPRINTF ((stderr, "Shifting token %d (%s), ",\r
- yychar, yytname[yychar1]));\r
-\r
- /* Discard the token being shifted unless it is eof. */\r
- if (yychar != YYEOF)\r
- yychar = YYEMPTY;\r
-\r
- *++yyvsp = yylval;\r
-#if YYLSP_NEEDED\r
- *++yylsp = yylloc;\r
-#endif\r
-\r
- /* Count tokens shifted since error; after three, turn off error\r
- status. */\r
- if (yyerrstatus)\r
- yyerrstatus--;\r
-\r
- yystate = yyn;\r
- goto yynewstate;\r
-\r
-\r
-/*-----------------------------------------------------------.\r
-| yydefault -- do the default action for the current state. |\r
-`-----------------------------------------------------------*/\r
-yydefault:\r
- yyn = yydefact[yystate];\r
- if (yyn == 0)\r
- goto yyerrlab;\r
- goto yyreduce;\r
-\r
-\r
-/*-----------------------------.\r
-| yyreduce -- Do a reduction. |\r
-`-----------------------------*/\r
-yyreduce:\r
- /* yyn is the number of a rule to reduce with. */\r
- yylen = yyr2[yyn];\r
-\r
- /* If YYLEN is nonzero, implement the default value of the action:\r
- `$$ = $1'.\r
-\r
- Otherwise, the following line sets YYVAL to the semantic value of\r
- the lookahead token. This behavior is undocumented and Bison\r
- users should not rely upon it. Assigning to YYVAL\r
- unconditionally makes the parser a bit smaller, and it avoids a\r
- GCC warning that YYVAL may be used uninitialized. */\r
- yyval = yyvsp[1-yylen];\r
-\r
-#if YYLSP_NEEDED\r
- /* Similarly for the default location. Let the user run additional\r
- commands if for instance locations are ranges. */\r
- yyloc = yylsp[1-yylen];\r
- YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);\r
-#endif\r
-\r
-#if YYDEBUG\r
- /* We have to keep this `#if YYDEBUG', since we use variables which\r
- are defined only if `YYDEBUG' is set. */\r
- if (yydebug)\r
- {\r
- int yyi;\r
-\r
- YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",\r
- yyn, yyrline[yyn]);\r
-\r
- /* Print the symbols being reduced, and their result. */\r
- for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++)\r
- YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);\r
- YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);\r
- }\r
-#endif\r
-\r
- switch (yyn) {\r
-\r
-case 1:\r
-#line 143 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- *sql->view = yyvsp[0].query;\r
- ;\r
- break;}\r
-case 2:\r
-#line 148 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- *sql->view = yyvsp[0].query;\r
- ;\r
- break;}\r
-case 3:\r
-#line 153 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- *sql->view = yyvsp[0].query;\r
- ;\r
- break;}\r
-case 4:\r
-#line 158 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- *sql->view = yyvsp[0].query;\r
- ;\r
- break;}\r
-case 5:\r
-#line 166 "./sql.y"\r
-{\r
- SQL_input *sql = (SQL_input*) info;\r
- MSIVIEW *insert = NULL; \r
-\r
- INSERT_CreateView( sql->db, &insert, yyvsp[-7].string, yyvsp[-5].column_list, yyvsp[-1].val_list, FALSE ); \r
- yyval.query = insert;\r
- ;\r
- break;}\r
-case 6:\r
-#line 174 "./sql.y"\r
-{\r
- SQL_input *sql = (SQL_input*) info;\r
- MSIVIEW *insert = NULL; \r
-\r
- INSERT_CreateView( sql->db, &insert, yyvsp[-8].string, yyvsp[-6].column_list, yyvsp[-2].val_list, TRUE ); \r
- yyval.query = insert;\r
- ;\r
- break;}\r
-case 7:\r
-#line 185 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- MSIVIEW *create = NULL; \r
-\r
- if( !yyvsp[-1].column_info )\r
- YYABORT;\r
- CREATE_CreateView( sql->db, &create, yyvsp[-3].string, yyvsp[-1].column_info, FALSE );\r
- yyval.query = create;\r
- ;\r
- break;}\r
-case 8:\r
-#line 195 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- MSIVIEW *create = NULL; \r
-\r
- if( !yyvsp[-2].column_info )\r
- YYABORT;\r
- CREATE_CreateView( sql->db, &create, yyvsp[-4].string, yyvsp[-2].column_info, TRUE );\r
- yyval.query = create;\r
- ;\r
- break;}\r
-case 9:\r
-#line 208 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- MSIVIEW *update = NULL; \r
-\r
- UPDATE_CreateView( sql->db, &update, yyvsp[-4].string, &yyvsp[-2].update_col_info, yyvsp[0].expr );\r
- yyval.query = update;\r
- ;\r
- break;}\r
-case 10:\r
-#line 219 "./sql.y"\r
-{\r
- if( SQL_MarkPrimaryKeys( yyvsp[-3].column_info, yyvsp[0].column_list ) )\r
- yyval.column_info = yyvsp[-3].column_info;\r
- else\r
- yyval.column_info = NULL;\r
- ;\r
- break;}\r
-case 11:\r
-#line 229 "./sql.y"\r
-{\r
- create_col_info *ci;\r
-\r
- for( ci = yyvsp[-3].column_info; ci->next; ci = ci->next )\r
- ;\r
-\r
- ci->next = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.column_info );\r
- if( !ci->next )\r
- {\r
- /* FIXME: free $1 */\r
- YYABORT;\r
- }\r
- ci->next->colname = yyvsp[-1].string;\r
- ci->next->type = yyvsp[0].column_type;\r
- ci->next->next = NULL;\r
-\r
- yyval.column_info = yyvsp[-3].column_info;\r
- ;\r
- break;}\r
-case 12:\r
-#line 248 "./sql.y"\r
-{\r
- yyval.column_info = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.column_info );\r
- if( ! yyval.column_info )\r
- YYABORT;\r
- yyval.column_info->colname = yyvsp[-1].string;\r
- yyval.column_info->type = yyvsp[0].column_type;\r
- yyval.column_info->next = NULL;\r
- ;\r
- break;}\r
-case 13:\r
-#line 260 "./sql.y"\r
-{\r
- yyval.column_type = yyvsp[0].column_type | MSITYPE_VALID;\r
- ;\r
- break;}\r
-case 14:\r
-#line 264 "./sql.y"\r
-{\r
- FIXME("LOCALIZABLE ignored\n");\r
- yyval.column_type = yyvsp[-1].column_type | MSITYPE_VALID;\r
- ;\r
- break;}\r
-case 15:\r
-#line 272 "./sql.y"\r
-{\r
- yyval.column_type |= MSITYPE_NULLABLE;\r
- ;\r
- break;}\r
-case 16:\r
-#line 276 "./sql.y"\r
-{\r
- yyval.column_type = yyvsp[-2].column_type;\r
- ;\r
- break;}\r
-case 17:\r
-#line 283 "./sql.y"\r
-{\r
- yyval.column_type = MSITYPE_STRING | 1;\r
- ;\r
- break;}\r
-case 18:\r
-#line 287 "./sql.y"\r
-{\r
- yyval.column_type = MSITYPE_STRING | 0x400 | yyvsp[-1].column_type;\r
- ;\r
- break;}\r
-case 19:\r
-#line 291 "./sql.y"\r
-{\r
- yyval.column_type = 2;\r
- ;\r
- break;}\r
-case 20:\r
-#line 295 "./sql.y"\r
-{\r
- yyval.column_type = 2;\r
- ;\r
- break;}\r
-case 21:\r
-#line 299 "./sql.y"\r
-{\r
- yyval.column_type = 2;\r
- ;\r
- break;}\r
-case 22:\r
-#line 303 "./sql.y"\r
-{\r
- yyval.column_type = 4;\r
- ;\r
- break;}\r
-case 23:\r
-#line 307 "./sql.y"\r
-{\r
- yyval.column_type = 0;\r
- ;\r
- break;}\r
-case 24:\r
-#line 314 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- int val = SQL_getint(sql);\r
- if( ( val > 255 ) || ( val < 0 ) )\r
- YYABORT;\r
- yyval.column_type = val;\r
- ;\r
- break;}\r
-case 25:\r
-#line 325 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
-\r
- if( !yyvsp[-3].query )\r
- YYABORT;\r
- if( yyvsp[0].column_list )\r
- yyval.query = do_order_by( sql->db, yyvsp[-3].query, yyvsp[0].column_list );\r
- else\r
- yyval.query = yyvsp[-3].query;\r
- ;\r
- break;}\r
-case 27:\r
-#line 340 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- if( !yyvsp[0].query )\r
- YYABORT;\r
- if( yyvsp[-1].column_list )\r
- {\r
- yyval.query = do_one_select( sql->db, yyvsp[0].query, yyvsp[-1].column_list );\r
- if( !yyval.query )\r
- YYABORT;\r
- }\r
- else\r
- yyval.query = yyvsp[0].query;\r
- ;\r
- break;}\r
-case 28:\r
-#line 354 "./sql.y"\r
-{\r
- SQL_input* sql = (SQL_input*) info;\r
- MSIVIEW *view = yyvsp[0].query;\r
-\r
- if( !view )\r
- YYABORT;\r
- if( yyvsp[-1].column_list )\r
- {\r
- view = do_one_select( sql->db, view, yyvsp[-1].column_list );\r
- if( !view )\r
- YYABORT;\r
- }\r
- DISTINCT_CreateView( sql->db, & yyval.query, view );\r
- ;\r
- break;}\r
-case 29:\r
-#line 372 "./sql.y"\r
-{ \r
- string_list *list;\r
-\r
- list = HeapAlloc( GetProcessHeap(), 0, sizeof *list );\r
- if( !list )\r
- YYABORT;\r
- list->string = yyvsp[0].string;\r
- list->next = NULL;\r
-\r
- yyval.column_list = list;\r
- TRACE("Collist %s\n",debugstr_w(yyval.column_list->string));\r
- ;\r
- break;}\r
-case 30:\r
-#line 385 "./sql.y"\r
-{ \r
- string_list *list;\r
-\r
- list = HeapAlloc( GetProcessHeap(), 0, sizeof *list );\r
- if( !list )\r
- YYABORT;\r
- list->string = yyvsp[-2].string;\r
- list->next = yyvsp[0].column_list;\r
-\r
- yyval.column_list = list;\r
- TRACE("From table: %s\n",debugstr_w(yyval.column_list->string));\r
- ;\r
- break;}\r
-case 31:\r
-#line 398 "./sql.y"\r
-{\r
- yyval.column_list = NULL;\r
- ;\r
- break;}\r
-case 32:\r
-#line 405 "./sql.y"\r
-{ \r
- SQL_input* sql = (SQL_input*) info;\r
- UINT r;\r
-\r
- yyval.query = NULL;\r
- TRACE("From table: %s\n",debugstr_w(yyvsp[0].string));\r
- r = TABLE_CreateView( sql->db, yyvsp[0].string, & yyval.query );\r
- if( r != ERROR_SUCCESS )\r
- YYABORT;\r
- ;\r
- break;}\r
-case 33:\r
-#line 416 "./sql.y"\r
-{ \r
- SQL_input* sql = (SQL_input*) info;\r
- MSIVIEW *view = NULL;\r
- UINT r;\r
-\r
- yyval.query = NULL;\r
- TRACE("From table: %s\n",debugstr_w(yyvsp[-2].string));\r
- r = TABLE_CreateView( sql->db, yyvsp[-2].string, &view );\r
- if( r != ERROR_SUCCESS )\r
- YYABORT;\r
- r = WHERE_CreateView( sql->db, &view, view, yyvsp[0].expr );\r
- if( r != ERROR_SUCCESS )\r
- YYABORT;\r
- yyval.query = view;\r
- ;\r
- break;}\r
-case 34:\r
-#line 435 "./sql.y"\r
-{\r
- yyval.expr = yyvsp[-1].expr;\r
- ;\r
- break;}\r
-case 35:\r
-#line 439 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_EQ, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 36:\r
-#line 443 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_AND, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 37:\r
-#line 447 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_OR, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 38:\r
-#line 451 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_EQ, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 39:\r
-#line 455 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_GT, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 40:\r
-#line 459 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_LT, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 41:\r
-#line 463 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_LE, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 42:\r
-#line 467 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_GE, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 43:\r
-#line 471 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_NE, yyvsp[0].expr );\r
- ;\r
- break;}\r
-case 44:\r
-#line 475 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_ISNULL, NULL );\r
- ;\r
- break;}\r
-case 45:\r
-#line 479 "./sql.y"\r
-{\r
- yyval.expr = EXPR_complex( yyvsp[-3].expr, OP_NOTNULL, NULL );\r
- ;\r
- break;}\r
-case 48:\r
-#line 491 "./sql.y"\r
-{\r
- value_list *vals;\r
-\r
- vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );\r
- if( vals )\r
- {\r
- vals->val = yyvsp[0].expr;\r
- vals->next = NULL;\r
- }\r
- yyval.val_list = vals;\r
- ;\r
- break;}\r
-case 49:\r
-#line 503 "./sql.y"\r
-{\r
- value_list *vals;\r
-\r
- vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );\r
- if( vals )\r
- {\r
- vals->val = yyvsp[0].expr;\r
- vals->next = NULL;\r
- }\r
- yyvsp[-2].val_list->next = vals;\r
- yyval.val_list = yyvsp[-2].val_list;\r
- ;\r
- break;}\r
-case 51:\r
-#line 520 "./sql.y"\r
-{\r
- yyvsp[-2].update_col_info.col_list->next = yyvsp[0].update_col_info.col_list;\r
- yyvsp[-2].update_col_info.val_list->next = yyvsp[0].update_col_info.val_list;\r
- yyval.update_col_info = yyvsp[-2].update_col_info;\r
- ;\r
- break;}\r
-case 52:\r
-#line 529 "./sql.y"\r
-{\r
- yyval.update_col_info.col_list = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.update_col_info.col_list );\r
- if( !yyval.update_col_info.col_list )\r
- YYABORT;\r
- yyval.update_col_info.col_list->string = yyvsp[-2].string;\r
- yyval.update_col_info.col_list->next = NULL;\r
- yyval.update_col_info.val_list = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.update_col_info.val_list );\r
- if( !yyval.update_col_info.val_list )\r
- YYABORT;\r
- yyval.update_col_info.val_list->val = yyvsp[0].expr;\r
- yyval.update_col_info.val_list->next = 0;\r
- ;\r
- break;}\r
-case 53:\r
-#line 545 "./sql.y"\r
-{\r
- yyval.expr = EXPR_ival( &yyvsp[0].str );\r
- ;\r
- break;}\r
-case 54:\r
-#line 549 "./sql.y"\r
-{\r
- yyval.expr = EXPR_sval( &yyvsp[0].str );\r
- ;\r
- break;}\r
-case 55:\r
-#line 553 "./sql.y"\r
-{\r
- yyval.expr = EXPR_wildcard();\r
- ;\r
- break;}\r
-case 56:\r
-#line 560 "./sql.y"\r
-{\r
- yyval.expr = EXPR_column( yyvsp[0].string );\r
- ;\r
- break;}\r
-case 57:\r
-#line 567 "./sql.y"\r
-{\r
- yyval.string = yyvsp[0].string; /* FIXME */\r
- ;\r
- break;}\r
-case 58:\r
-#line 571 "./sql.y"\r
-{\r
- yyval.string = yyvsp[0].string;\r
- ;\r
- break;}\r
-case 59:\r
-#line 578 "./sql.y"\r
-{\r
- yyval.string = yyvsp[0].string;\r
- ;\r
- break;}\r
-case 60:\r
-#line 585 "./sql.y"\r
-{\r
- yyval.string = SQL_getstring( &yyvsp[0].str );\r
- ;\r
- break;}\r
-case 61:\r
-#line 589 "./sql.y"\r
-{\r
- yyval.string = SQL_getstring( &yyvsp[0].str );\r
- ;\r
- break;}\r
-}\r
-\r
-#line 705 "/usr/share/bison/bison.simple"\r
-\r
-\f\r
- yyvsp -= yylen;\r
- yyssp -= yylen;\r
-#if YYLSP_NEEDED\r
- yylsp -= yylen;\r
-#endif\r
-\r
-#if YYDEBUG\r
- if (yydebug)\r
- {\r
- short *yyssp1 = yyss - 1;\r
- YYFPRINTF (stderr, "state stack now");\r
- while (yyssp1 != yyssp)\r
- YYFPRINTF (stderr, " %d", *++yyssp1);\r
- YYFPRINTF (stderr, "\n");\r
- }\r
-#endif\r
-\r
- *++yyvsp = yyval;\r
-#if YYLSP_NEEDED\r
- *++yylsp = yyloc;\r
-#endif\r
-\r
- /* Now `shift' the result of the reduction. Determine what state\r
- that goes to, based on the state we popped back to and the rule\r
- number reduced by. */\r
-\r
- yyn = yyr1[yyn];\r
-\r
- yystate = yypgoto[yyn - YYNTBASE] + *yyssp;\r
- if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)\r
- yystate = yytable[yystate];\r
- else\r
- yystate = yydefgoto[yyn - YYNTBASE];\r
-\r
- goto yynewstate;\r
-\r
-\r
-/*------------------------------------.\r
-| yyerrlab -- here on detecting error |\r
-`------------------------------------*/\r
-yyerrlab:\r
- /* If not already recovering from an error, report this error. */\r
- if (!yyerrstatus)\r
- {\r
- ++yynerrs;\r
-\r
-#ifdef YYERROR_VERBOSE\r
- yyn = yypact[yystate];\r
-\r
- if (yyn > YYFLAG && yyn < YYLAST)\r
- {\r
- YYSIZE_T yysize = 0;\r
- char *yymsg;\r
- int yyx, yycount;\r
-\r
- yycount = 0;\r
- /* Start YYX at -YYN if negative to avoid negative indexes in\r
- YYCHECK. */\r
- for (yyx = yyn < 0 ? -yyn : 0;\r
- yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)\r
- if (yycheck[yyx + yyn] == yyx)\r
- yysize += yystrlen (yytname[yyx]) + 15, yycount++;\r
- yysize += yystrlen ("parse error, unexpected ") + 1;\r
- yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);\r
- yymsg = (char *) YYSTACK_ALLOC (yysize);\r
- if (yymsg != 0)\r
- {\r
- char *yyp = yystpcpy (yymsg, "parse error, unexpected ");\r
- yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);\r
-\r
- if (yycount < 5)\r
- {\r
- yycount = 0;\r
- for (yyx = yyn < 0 ? -yyn : 0;\r
- yyx < (int) (sizeof (yytname) / sizeof (char *));\r
- yyx++)\r
- if (yycheck[yyx + yyn] == yyx)\r
- {\r
- const char *yyq = ! yycount ? ", expecting " : " or ";\r
- yyp = yystpcpy (yyp, yyq);\r
- yyp = yystpcpy (yyp, yytname[yyx]);\r
- yycount++;\r
- }\r
- }\r
- yyerror (yymsg);\r
- YYSTACK_FREE (yymsg);\r
- }\r
- else\r
- yyerror ("parse error; also virtual memory exhausted");\r
- }\r
- else\r
-#endif /* defined (YYERROR_VERBOSE) */\r
- yyerror ("parse error");\r
- }\r
- goto yyerrlab1;\r
-\r
-\r
-/*--------------------------------------------------.\r
-| yyerrlab1 -- error raised explicitly by an action |\r
-`--------------------------------------------------*/\r
-yyerrlab1:\r
- if (yyerrstatus == 3)\r
- {\r
- /* If just tried and failed to reuse lookahead token after an\r
- error, discard it. */\r
-\r
- /* return failure if at end of input */\r
- if (yychar == YYEOF)\r
- YYABORT;\r
- YYDPRINTF ((stderr, "Discarding token %d (%s).\n",\r
- yychar, yytname[yychar1]));\r
- yychar = YYEMPTY;\r
- }\r
-\r
- /* Else will try to reuse lookahead token after shifting the error\r
- token. */\r
-\r
- yyerrstatus = 3; /* Each real token shifted decrements this */\r
-\r
- goto yyerrhandle;\r
-\r
-\r
-/*-------------------------------------------------------------------.\r
-| yyerrdefault -- current state does not do anything special for the |\r
-| error token. |\r
-`-------------------------------------------------------------------*/\r
-yyerrdefault:\r
-#if 0\r
- /* This is wrong; only states that explicitly want error tokens\r
- should shift them. */\r
-\r
- /* If its default is to accept any token, ok. Otherwise pop it. */\r
- yyn = yydefact[yystate];\r
- if (yyn)\r
- goto yydefault;\r
-#endif\r
-\r
-\r
-/*---------------------------------------------------------------.\r
-| yyerrpop -- pop the current state because it cannot handle the |\r
-| error token |\r
-`---------------------------------------------------------------*/\r
-yyerrpop:\r
- if (yyssp == yyss)\r
- YYABORT;\r
- yyvsp--;\r
- yystate = *--yyssp;\r
-#if YYLSP_NEEDED\r
- yylsp--;\r
-#endif\r
-\r
-#if YYDEBUG\r
- if (yydebug)\r
- {\r
- short *yyssp1 = yyss - 1;\r
- YYFPRINTF (stderr, "Error: state stack now");\r
- while (yyssp1 != yyssp)\r
- YYFPRINTF (stderr, " %d", *++yyssp1);\r
- YYFPRINTF (stderr, "\n");\r
- }\r
-#endif\r
-\r
-/*--------------.\r
-| yyerrhandle. |\r
-`--------------*/\r
-yyerrhandle:\r
- yyn = yypact[yystate];\r
- if (yyn == YYFLAG)\r
- goto yyerrdefault;\r
-\r
- yyn += YYTERROR;\r
- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)\r
- goto yyerrdefault;\r
-\r
- yyn = yytable[yyn];\r
- if (yyn < 0)\r
- {\r
- if (yyn == YYFLAG)\r
- goto yyerrpop;\r
- yyn = -yyn;\r
- goto yyreduce;\r
- }\r
- else if (yyn == 0)\r
- goto yyerrpop;\r
-\r
- if (yyn == YYFINAL)\r
- YYACCEPT;\r
-\r
- YYDPRINTF ((stderr, "Shifting error token, "));\r
-\r
- *++yyvsp = yylval;\r
-#if YYLSP_NEEDED\r
- *++yylsp = yylloc;\r
-#endif\r
-\r
- yystate = yyn;\r
- goto yynewstate;\r
-\r
-\r
-/*-------------------------------------.\r
-| yyacceptlab -- YYACCEPT comes here. |\r
-`-------------------------------------*/\r
-yyacceptlab:\r
- yyresult = 0;\r
- goto yyreturn;\r
-\r
-/*-----------------------------------.\r
-| yyabortlab -- YYABORT comes here. |\r
-`-----------------------------------*/\r
-yyabortlab:\r
- yyresult = 1;\r
- goto yyreturn;\r
-\r
-/*---------------------------------------------.\r
-| yyoverflowab -- parser overflow comes here. |\r
-`---------------------------------------------*/\r
-yyoverflowlab:\r
- yyerror ("parser stack overflow");\r
- yyresult = 2;\r
- /* Fall through. */\r
-\r
-yyreturn:\r
-#ifndef yyoverflow\r
- if (yyss != yyssa)\r
- YYSTACK_FREE (yyss);\r
-#endif\r
- return yyresult;\r
-}\r
-#line 594 "./sql.y"\r
-\r
-\r
-int SQL_lex( void *SQL_lval, SQL_input *sql)\r
-{\r
- int token;\r
- struct sql_str * str = SQL_lval;\r
-\r
- do\r
- {\r
- sql->n += sql->len;\r
- if( ! sql->command[sql->n] )\r
- return 0; /* end of input */\r
-\r
- TRACE("string : %s\n", debugstr_w(&sql->command[sql->n]));\r
- sql->len = sqliteGetToken( &sql->command[sql->n], &token );\r
- if( sql->len==0 )\r
- break;\r
- str->data = &sql->command[sql->n];\r
- str->len = sql->len;\r
- }\r
- while( token == TK_SPACE );\r
-\r
- TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len));\r
- \r
- return token;\r
-}\r
-\r
-LPWSTR SQL_getstring( struct sql_str *strdata)\r
-{\r
- LPCWSTR p = strdata->data;\r
- UINT len = strdata->len;\r
- LPWSTR str;\r
-\r
- /* if there's quotes, remove them */\r
- if( ( (p[0]=='`') && (p[len-1]=='`') ) || \r
- ( (p[0]=='\'') && (p[len-1]=='\'') ) )\r
- {\r
- p++;\r
- len -= 2;\r
- }\r
- str = HeapAlloc( GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));\r
- if(!str )\r
- return str;\r
- memcpy(str, p, len*sizeof(WCHAR) );\r
- str[len]=0;\r
-\r
- return str;\r
-}\r
-\r
-INT SQL_getint( SQL_input *sql )\r
-{\r
- LPCWSTR p = &sql->command[sql->n];\r
-\r
- return atoiW( p );\r
-}\r
-\r
-int SQL_error(const char *str)\r
-{\r
- return 0;\r
-}\r
-\r
-static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, \r
- string_list *columns )\r
-{\r
- MSIVIEW *view = NULL;\r
-\r
- SELECT_CreateView( db, &view, in, columns );\r
- delete_string_list( columns );\r
- if( !view )\r
- ERR("Error creating select query\n");\r
- return view;\r
-}\r
-\r
-static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, \r
- string_list *columns )\r
-{\r
- MSIVIEW *view = NULL;\r
-\r
- ORDER_CreateView( db, &view, in );\r
- if( view )\r
- {\r
- string_list *x = columns;\r
-\r
- for( x = columns; x ; x = x->next )\r
- ORDER_AddColumn( view, x->string );\r
- }\r
- else\r
- ERR("Error creating select query\n");\r
- delete_string_list( columns );\r
- return view;\r
-}\r
-\r
-static struct expr * EXPR_wildcard()\r
-{\r
- struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
- if( e )\r
- {\r
- e->type = EXPR_WILDCARD;\r
- }\r
- return e;\r
-}\r
-\r
-static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r )\r
-{\r
- struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
- if( e )\r
- {\r
- e->type = EXPR_COMPLEX;\r
- e->u.expr.left = l;\r
- e->u.expr.op = op;\r
- e->u.expr.right = r;\r
- }\r
- return e;\r
-}\r
-\r
-static struct expr * EXPR_column( LPWSTR str )\r
-{\r
- struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
- if( e )\r
- {\r
- e->type = EXPR_COLUMN;\r
- e->u.sval = str;\r
- }\r
- return e;\r
-}\r
-\r
-static struct expr * EXPR_ival( struct sql_str *str )\r
-{\r
- struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
- if( e )\r
- {\r
- e->type = EXPR_IVAL;\r
- e->u.ival = atoiW( str->data );\r
- }\r
- return e;\r
-}\r
-\r
-static struct expr * EXPR_sval( struct sql_str *str )\r
-{\r
- struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
- if( e )\r
- {\r
- e->type = EXPR_SVAL;\r
- e->u.sval = SQL_getstring( str );\r
- }\r
- return e;\r
-}\r
-\r
-void delete_expr( struct expr *e )\r
-{\r
- if( !e )\r
- return;\r
- if( e->type == EXPR_COMPLEX )\r
- {\r
- delete_expr( e->u.expr.left );\r
- delete_expr( e->u.expr.right );\r
- }\r
- else if( e->type == EXPR_UTF8 )\r
- HeapFree( GetProcessHeap(), 0, e->u.utf8 );\r
- else if( e->type == EXPR_SVAL )\r
- HeapFree( GetProcessHeap(), 0, e->u.sval );\r
- HeapFree( GetProcessHeap(), 0, e );\r
-}\r
-\r
-void delete_string_list( string_list *sl )\r
-{\r
- while( sl )\r
- {\r
- string_list *t = sl->next;\r
- HeapFree( GetProcessHeap(), 0, sl->string );\r
- HeapFree( GetProcessHeap(), 0, sl );\r
- sl = t;\r
- }\r
-}\r
-\r
-void delete_value_list( value_list *vl )\r
-{\r
- while( vl )\r
- {\r
- value_list *t = vl->next;\r
- delete_expr( vl->val );\r
- HeapFree( GetProcessHeap(), 0, vl );\r
- vl = t;\r
- }\r
-}\r
-\r
-static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,\r
- string_list *keys )\r
-{\r
- string_list *k;\r
- BOOL found = TRUE;\r
-\r
- for( k = keys; k && found; k = k->next )\r
- {\r
- create_col_info *c;\r
-\r
- found = FALSE;\r
- for( c = cols; c && !found; c = c->next )\r
- {\r
- if( lstrcmpW( k->string, c->colname ) )\r
- continue;\r
- c->type |= MSITYPE_KEY;\r
- found = TRUE;\r
- }\r
- }\r
-\r
- return found;\r
-}\r
-\r
-UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview )\r
-{\r
- SQL_input sql;\r
- int r;\r
-\r
- *phview = NULL;\r
-\r
- sql.db = db;\r
- sql.command = command;\r
- sql.n = 0;\r
- sql.len = 0;\r
- sql.view = phview;\r
-\r
- r = SQL_parse(&sql);\r
-\r
- TRACE("Parse returned %d\n", r);\r
- if( r )\r
- {\r
- if( *sql.view )\r
- (*sql.view)->ops->delete( *sql.view );\r
- *sql.view = NULL;\r
- return ERROR_BAD_QUERY_SYNTAX;\r
- }\r
-\r
- return ERROR_SUCCESS;\r
-}\r
+/* A Bison parser, made by GNU Bison 1.875b. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* If NAME_PREFIX is specified substitute the variables and functions
+ names. */
+#define yyparse SQL_parse
+#define yylex SQL_lex
+#define yyerror SQL_error
+#define yylval SQL_lval
+#define yychar SQL_char
+#define yydebug SQL_debug
+#define yynerrs SQL_nerrs
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ TK_ABORT = 258,
+ TK_AFTER = 259,
+ TK_AGG_FUNCTION = 260,
+ TK_ALL = 261,
+ TK_AND = 262,
+ TK_AS = 263,
+ TK_ASC = 264,
+ TK_BEFORE = 265,
+ TK_BEGIN = 266,
+ TK_BETWEEN = 267,
+ TK_BITAND = 268,
+ TK_BITNOT = 269,
+ TK_BITOR = 270,
+ TK_BY = 271,
+ TK_CASCADE = 272,
+ TK_CASE = 273,
+ TK_CHAR = 274,
+ TK_CHECK = 275,
+ TK_CLUSTER = 276,
+ TK_COLLATE = 277,
+ TK_COLUMN = 278,
+ TK_COMMA = 279,
+ TK_COMMENT = 280,
+ TK_COMMIT = 281,
+ TK_CONCAT = 282,
+ TK_CONFLICT = 283,
+ TK_CONSTRAINT = 284,
+ TK_COPY = 285,
+ TK_CREATE = 286,
+ TK_DEFAULT = 287,
+ TK_DEFERRABLE = 288,
+ TK_DEFERRED = 289,
+ TK_DELETE = 290,
+ TK_DELIMITERS = 291,
+ TK_DESC = 292,
+ TK_DISTINCT = 293,
+ TK_DOT = 294,
+ TK_DROP = 295,
+ TK_EACH = 296,
+ TK_ELSE = 297,
+ TK_END = 298,
+ TK_END_OF_FILE = 299,
+ TK_EQ = 300,
+ TK_EXCEPT = 301,
+ TK_EXPLAIN = 302,
+ TK_FAIL = 303,
+ TK_FLOAT = 304,
+ TK_FOR = 305,
+ TK_FOREIGN = 306,
+ TK_FROM = 307,
+ TK_FUNCTION = 308,
+ TK_GE = 309,
+ TK_GLOB = 310,
+ TK_GROUP = 311,
+ TK_GT = 312,
+ TK_HAVING = 313,
+ TK_HOLD = 314,
+ TK_IGNORE = 315,
+ TK_ILLEGAL = 316,
+ TK_IMMEDIATE = 317,
+ TK_IN = 318,
+ TK_INDEX = 319,
+ TK_INITIALLY = 320,
+ TK_ID = 321,
+ TK_INSERT = 322,
+ TK_INSTEAD = 323,
+ TK_INT = 324,
+ TK_INTEGER = 325,
+ TK_INTERSECT = 326,
+ TK_INTO = 327,
+ TK_IS = 328,
+ TK_ISNULL = 329,
+ TK_JOIN = 330,
+ TK_JOIN_KW = 331,
+ TK_KEY = 332,
+ TK_LE = 333,
+ TK_LIKE = 334,
+ TK_LIMIT = 335,
+ TK_LONG = 336,
+ TK_LONGCHAR = 337,
+ TK_LP = 338,
+ TK_LSHIFT = 339,
+ TK_LT = 340,
+ TK_LOCALIZABLE = 341,
+ TK_MATCH = 342,
+ TK_MINUS = 343,
+ TK_NE = 344,
+ TK_NOT = 345,
+ TK_NOTNULL = 346,
+ TK_NULL = 347,
+ TK_OBJECT = 348,
+ TK_OF = 349,
+ TK_OFFSET = 350,
+ TK_ON = 351,
+ TK_OR = 352,
+ TK_ORACLE_OUTER_JOIN = 353,
+ TK_ORDER = 354,
+ TK_PLUS = 355,
+ TK_PRAGMA = 356,
+ TK_PRIMARY = 357,
+ TK_RAISE = 358,
+ TK_REFERENCES = 359,
+ TK_REM = 360,
+ TK_REPLACE = 361,
+ TK_RESTRICT = 362,
+ TK_ROLLBACK = 363,
+ TK_ROW = 364,
+ TK_RP = 365,
+ TK_RSHIFT = 366,
+ TK_SELECT = 367,
+ TK_SEMI = 368,
+ TK_SET = 369,
+ TK_SHORT = 370,
+ TK_SLASH = 371,
+ TK_SPACE = 372,
+ TK_STAR = 373,
+ TK_STATEMENT = 374,
+ TK_STRING = 375,
+ TK_TABLE = 376,
+ TK_TEMP = 377,
+ TK_THEN = 378,
+ TK_TRANSACTION = 379,
+ TK_TRIGGER = 380,
+ TK_UMINUS = 381,
+ TK_UNCLOSED_STRING = 382,
+ TK_UNION = 383,
+ TK_UNIQUE = 384,
+ TK_UPDATE = 385,
+ TK_UPLUS = 386,
+ TK_USING = 387,
+ TK_VACUUM = 388,
+ TK_VALUES = 389,
+ TK_VIEW = 390,
+ TK_WHEN = 391,
+ TK_WHERE = 392,
+ TK_WILDCARD = 393,
+ COLUMN = 395,
+ FUNCTION = 396,
+ COMMENT = 397,
+ UNCLOSED_STRING = 398,
+ SPACE = 399,
+ ILLEGAL = 400,
+ END_OF_FILE = 401
+ };
+#endif
+#define TK_ABORT 258
+#define TK_AFTER 259
+#define TK_AGG_FUNCTION 260
+#define TK_ALL 261
+#define TK_AND 262
+#define TK_AS 263
+#define TK_ASC 264
+#define TK_BEFORE 265
+#define TK_BEGIN 266
+#define TK_BETWEEN 267
+#define TK_BITAND 268
+#define TK_BITNOT 269
+#define TK_BITOR 270
+#define TK_BY 271
+#define TK_CASCADE 272
+#define TK_CASE 273
+#define TK_CHAR 274
+#define TK_CHECK 275
+#define TK_CLUSTER 276
+#define TK_COLLATE 277
+#define TK_COLUMN 278
+#define TK_COMMA 279
+#define TK_COMMENT 280
+#define TK_COMMIT 281
+#define TK_CONCAT 282
+#define TK_CONFLICT 283
+#define TK_CONSTRAINT 284
+#define TK_COPY 285
+#define TK_CREATE 286
+#define TK_DEFAULT 287
+#define TK_DEFERRABLE 288
+#define TK_DEFERRED 289
+#define TK_DELETE 290
+#define TK_DELIMITERS 291
+#define TK_DESC 292
+#define TK_DISTINCT 293
+#define TK_DOT 294
+#define TK_DROP 295
+#define TK_EACH 296
+#define TK_ELSE 297
+#define TK_END 298
+#define TK_END_OF_FILE 299
+#define TK_EQ 300
+#define TK_EXCEPT 301
+#define TK_EXPLAIN 302
+#define TK_FAIL 303
+#define TK_FLOAT 304
+#define TK_FOR 305
+#define TK_FOREIGN 306
+#define TK_FROM 307
+#define TK_FUNCTION 308
+#define TK_GE 309
+#define TK_GLOB 310
+#define TK_GROUP 311
+#define TK_GT 312
+#define TK_HAVING 313
+#define TK_HOLD 314
+#define TK_IGNORE 315
+#define TK_ILLEGAL 316
+#define TK_IMMEDIATE 317
+#define TK_IN 318
+#define TK_INDEX 319
+#define TK_INITIALLY 320
+#define TK_ID 321
+#define TK_INSERT 322
+#define TK_INSTEAD 323
+#define TK_INT 324
+#define TK_INTEGER 325
+#define TK_INTERSECT 326
+#define TK_INTO 327
+#define TK_IS 328
+#define TK_ISNULL 329
+#define TK_JOIN 330
+#define TK_JOIN_KW 331
+#define TK_KEY 332
+#define TK_LE 333
+#define TK_LIKE 334
+#define TK_LIMIT 335
+#define TK_LONG 336
+#define TK_LONGCHAR 337
+#define TK_LP 338
+#define TK_LSHIFT 339
+#define TK_LT 340
+#define TK_LOCALIZABLE 341
+#define TK_MATCH 342
+#define TK_MINUS 343
+#define TK_NE 344
+#define TK_NOT 345
+#define TK_NOTNULL 346
+#define TK_NULL 347
+#define TK_OBJECT 348
+#define TK_OF 349
+#define TK_OFFSET 350
+#define TK_ON 351
+#define TK_OR 352
+#define TK_ORACLE_OUTER_JOIN 353
+#define TK_ORDER 354
+#define TK_PLUS 355
+#define TK_PRAGMA 356
+#define TK_PRIMARY 357
+#define TK_RAISE 358
+#define TK_REFERENCES 359
+#define TK_REM 360
+#define TK_REPLACE 361
+#define TK_RESTRICT 362
+#define TK_ROLLBACK 363
+#define TK_ROW 364
+#define TK_RP 365
+#define TK_RSHIFT 366
+#define TK_SELECT 367
+#define TK_SEMI 368
+#define TK_SET 369
+#define TK_SHORT 370
+#define TK_SLASH 371
+#define TK_SPACE 372
+#define TK_STAR 373
+#define TK_STATEMENT 374
+#define TK_STRING 375
+#define TK_TABLE 376
+#define TK_TEMP 377
+#define TK_THEN 378
+#define TK_TRANSACTION 379
+#define TK_TRIGGER 380
+#define TK_UMINUS 381
+#define TK_UNCLOSED_STRING 382
+#define TK_UNION 383
+#define TK_UNIQUE 384
+#define TK_UPDATE 385
+#define TK_UPLUS 386
+#define TK_USING 387
+#define TK_VACUUM 388
+#define TK_VALUES 389
+#define TK_VIEW 390
+#define TK_WHEN 391
+#define TK_WHERE 392
+#define TK_WILDCARD 393
+#define COLUMN 395
+#define FUNCTION 396
+#define COMMENT 397
+#define UNCLOSED_STRING 398
+#define SPACE 399
+#define ILLEGAL 400
+#define END_OF_FILE 401
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 1 "./sql.y"
+
+
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2002-2004 Mike McCormack for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "query.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+#define YYLEX_PARAM info
+#define YYPARSE_PARAM info
+
+extern int SQL_error(const char *str);
+
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
+
+typedef struct tag_SQL_input
+{
+ MSIDATABASE *db;
+ LPCWSTR command;
+ DWORD n, len;
+ MSIVIEW **view; /* view structure for the resulting query */
+} SQL_input;
+
+static LPWSTR SQL_getstring( struct sql_str *str );
+static INT SQL_getint( SQL_input *sql );
+static int SQL_lex( void *SQL_lval, SQL_input *info);
+
+static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in,
+ string_list *columns );
+static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in,
+ string_list *columns );
+
+static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,
+ string_list *keys);
+
+static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r );
+static struct expr * EXPR_column( LPWSTR );
+static struct expr * EXPR_ival( struct sql_str *, int sign);
+static struct expr * EXPR_sval( struct sql_str *);
+static struct expr * EXPR_wildcard(void);
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 74 "./sql.y"
+typedef union YYSTYPE {
+ struct sql_str str;
+ LPWSTR string;
+ string_list *column_list;
+ value_list *val_list;
+ MSIVIEW *query;
+ struct expr *expr;
+ USHORT column_type;
+ create_col_info *column_info;
+ column_assignment update_col_info;
+} YYSTYPE;
+/* Line 191 of yacc.c. */
+#line 457 "sql.tab.c"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 214 of yacc.c. */
+#line 469 "sql.tab.c"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# if YYSTACK_USE_ALLOCA
+# define YYSTACK_ALLOC alloca
+# else
+# ifndef YYSTACK_USE_ALLOCA
+# if defined (alloca) || defined (_ALLOCA_H)
+# define YYSTACK_ALLOC alloca
+# else
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+# define YYSTACK_ALLOC malloc
+# define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ short yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ register YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char yysigned_char;
+#else
+ typedef short yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 23
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 125
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 147
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 25
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 63
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 123
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 401
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const unsigned char yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const unsigned char yyprhs[] =
+{
+ 0, 0, 3, 5, 7, 9, 11, 22, 34, 41,
+ 49, 56, 61, 66, 69, 71, 74, 76, 80, 82,
+ 87, 89, 91, 93, 95, 97, 99, 104, 106, 110,
+ 115, 117, 121, 123, 126, 131, 135, 139, 143, 147,
+ 151, 155, 159, 163, 167, 171, 175, 180, 182, 184,
+ 186, 190, 192, 196, 200, 202, 205, 207, 209, 211,
+ 215, 217, 219, 221
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const short yyrhs[] =
+{
+ 148, 0, -1, 158, -1, 150, -1, 149, -1, 151,
+ -1, 67, 72, 170, 83, 160, 110, 134, 83, 164,
+ 110, -1, 67, 72, 170, 83, 160, 110, 134, 83,
+ 164, 110, 122, -1, 31, 121, 170, 83, 152, 110,
+ -1, 31, 121, 170, 83, 152, 110, 59, -1, 130,
+ 170, 114, 165, 137, 162, -1, 153, 102, 77, 160,
+ -1, 153, 24, 169, 154, -1, 169, 154, -1, 155,
+ -1, 155, 86, -1, 156, -1, 156, 90, 92, -1,
+ 19, -1, 19, 83, 157, 110, -1, 82, -1, 115,
+ -1, 69, -1, 81, -1, 93, -1, 70, -1, 159,
+ 99, 16, 160, -1, 159, -1, 112, 160, 161, -1,
+ 112, 38, 160, 161, -1, 169, -1, 169, 24, 160,
+ -1, 118, -1, 52, 170, -1, 52, 170, 137, 162,
+ -1, 83, 162, 110, -1, 168, 45, 168, -1, 162,
+ 7, 162, -1, 162, 97, 162, -1, 168, 45, 163,
+ -1, 168, 57, 163, -1, 168, 85, 163, -1, 168,
+ 78, 163, -1, 168, 54, 163, -1, 168, 89, 163,
+ -1, 168, 73, 92, -1, 168, 73, 90, 92, -1,
+ 168, -1, 167, -1, 167, -1, 164, 24, 167, -1,
+ 166, -1, 166, 24, 165, -1, 169, 45, 167, -1,
+ 70, -1, 88, 70, -1, 120, -1, 138, -1, 169,
+ -1, 170, 39, 171, -1, 171, -1, 171, -1, 66,
+ -1, 120, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const unsigned short yyrline[] =
+{
+ 0, 142, 142, 147, 152, 157, 165, 173, 184, 194,
+ 207, 218, 228, 247, 259, 263, 271, 275, 282, 286,
+ 290, 294, 298, 302, 306, 313, 324, 335, 339, 353,
+ 371, 384, 397, 404, 415, 434, 438, 442, 446, 450,
+ 454, 458, 462, 466, 470, 474, 478, 485, 486, 490,
+ 502, 518, 519, 528, 544, 548, 552, 556, 563, 570,
+ 574, 581, 588, 592
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "TK_ABORT", "TK_AFTER", "TK_AGG_FUNCTION",
+ "TK_ALL", "TK_AND", "TK_AS", "TK_ASC", "TK_BEFORE", "TK_BEGIN",
+ "TK_BETWEEN", "TK_BITAND", "TK_BITNOT", "TK_BITOR", "TK_BY",
+ "TK_CASCADE", "TK_CASE", "TK_CHAR", "TK_CHECK", "TK_CLUSTER",
+ "TK_COLLATE", "TK_COLUMN", "TK_COMMA", "TK_COMMENT", "TK_COMMIT",
+ "TK_CONCAT", "TK_CONFLICT", "TK_CONSTRAINT", "TK_COPY", "TK_CREATE",
+ "TK_DEFAULT", "TK_DEFERRABLE", "TK_DEFERRED", "TK_DELETE",
+ "TK_DELIMITERS", "TK_DESC", "TK_DISTINCT", "TK_DOT", "TK_DROP",
+ "TK_EACH", "TK_ELSE", "TK_END", "TK_END_OF_FILE", "TK_EQ", "TK_EXCEPT",
+ "TK_EXPLAIN", "TK_FAIL", "TK_FLOAT", "TK_FOR", "TK_FOREIGN", "TK_FROM",
+ "TK_FUNCTION", "TK_GE", "TK_GLOB", "TK_GROUP", "TK_GT", "TK_HAVING",
+ "TK_HOLD", "TK_IGNORE", "TK_ILLEGAL", "TK_IMMEDIATE", "TK_IN",
+ "TK_INDEX", "TK_INITIALLY", "TK_ID", "TK_INSERT", "TK_INSTEAD",
+ "TK_INT", "TK_INTEGER", "TK_INTERSECT", "TK_INTO", "TK_IS", "TK_ISNULL",
+ "TK_JOIN", "TK_JOIN_KW", "TK_KEY", "TK_LE", "TK_LIKE", "TK_LIMIT",
+ "TK_LONG", "TK_LONGCHAR", "TK_LP", "TK_LSHIFT", "TK_LT",
+ "TK_LOCALIZABLE", "TK_MATCH", "TK_MINUS", "TK_NE", "TK_NOT",
+ "TK_NOTNULL", "TK_NULL", "TK_OBJECT", "TK_OF", "TK_OFFSET", "TK_ON",
+ "TK_OR", "TK_ORACLE_OUTER_JOIN", "TK_ORDER", "TK_PLUS", "TK_PRAGMA",
+ "TK_PRIMARY", "TK_RAISE", "TK_REFERENCES", "TK_REM", "TK_REPLACE",
+ "TK_RESTRICT", "TK_ROLLBACK", "TK_ROW", "TK_RP", "TK_RSHIFT",
+ "TK_SELECT", "TK_SEMI", "TK_SET", "TK_SHORT", "TK_SLASH", "TK_SPACE",
+ "TK_STAR", "TK_STATEMENT", "TK_STRING", "TK_TABLE", "TK_TEMP",
+ "TK_THEN", "TK_TRANSACTION", "TK_TRIGGER", "TK_UMINUS",
+ "TK_UNCLOSED_STRING", "TK_UNION", "TK_UNIQUE", "TK_UPDATE", "TK_UPLUS",
+ "TK_USING", "TK_VACUUM", "TK_VALUES", "TK_VIEW", "TK_WHEN", "TK_WHERE",
+ "TK_WILDCARD", "AGG_FUNCTION.", "COLUMN", "FUNCTION", "COMMENT",
+ "UNCLOSED_STRING", "SPACE", "ILLEGAL", "END_OF_FILE", "$accept",
+ "onequery", "oneinsert", "onecreate", "oneupdate", "table_def",
+ "column_def", "column_type", "data_type_l", "data_type", "data_count",
+ "oneselect", "unorderedsel", "selcollist", "from", "expr", "val",
+ "constlist", "update_assign_list", "column_assignment", "const_val",
+ "column_val", "column", "table", "string_or_id", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const unsigned short yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
+ 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
+ 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
+ 395, 396, 397, 398, 399, 400, 401
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const unsigned char yyr1[] =
+{
+ 0, 147, 148, 148, 148, 148, 149, 149, 150, 150,
+ 151, 152, 153, 153, 154, 154, 155, 155, 156, 156,
+ 156, 156, 156, 156, 156, 157, 158, 158, 159, 159,
+ 160, 160, 160, 161, 161, 162, 162, 162, 162, 162,
+ 162, 162, 162, 162, 162, 162, 162, 163, 163, 164,
+ 164, 165, 165, 166, 167, 167, 167, 167, 168, 169,
+ 169, 170, 171, 171
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const unsigned char yyr2[] =
+{
+ 0, 2, 1, 1, 1, 1, 10, 11, 6, 7,
+ 6, 4, 4, 2, 1, 2, 1, 3, 1, 4,
+ 1, 1, 1, 1, 1, 1, 4, 1, 3, 4,
+ 1, 3, 1, 2, 4, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 4, 1, 1, 1,
+ 3, 1, 3, 3, 1, 2, 1, 1, 1, 3,
+ 1, 1, 1, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char yydefact[] =
+{
+ 0, 0, 0, 0, 0, 0, 4, 3, 5, 2,
+ 27, 0, 0, 0, 62, 32, 63, 0, 30, 0,
+ 60, 0, 61, 1, 0, 0, 0, 0, 0, 28,
+ 0, 0, 0, 0, 0, 0, 29, 33, 31, 59,
+ 0, 51, 0, 26, 0, 0, 0, 0, 0, 0,
+ 0, 0, 8, 0, 0, 18, 22, 23, 20, 24,
+ 21, 13, 14, 16, 0, 0, 34, 0, 58, 10,
+ 52, 54, 0, 56, 57, 53, 9, 0, 0, 0,
+ 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 55, 12, 11, 25, 0, 17, 0,
+ 35, 37, 38, 56, 39, 48, 36, 43, 47, 40,
+ 0, 45, 42, 41, 44, 19, 0, 49, 46, 0,
+ 6, 50, 7
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yysigned_char yydefgoto[] =
+{
+ -1, 5, 6, 7, 8, 44, 45, 61, 62, 63,
+ 97, 9, 10, 17, 29, 66, 104, 116, 40, 41,
+ 105, 67, 68, 19, 20
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -105
+static const yysigned_char yypact[] =
+{
+ -30, -104, -46, -34, -51, 21, -105, -105, -105, -105,
+ -77, -51, -51, -52, -105, -105, -105, -25, 7, -1,
+ 2, -79, -105, -105, 31, -33, -32, -25, -51, -105,
+ -52, -51, -51, -52, -51, -52, -105, -88, -105, -105,
+ -82, 33, 14, -105, -48, -15, -17, -43, -50, -50,
+ -51, -64, 13, -51, -2, -6, -105, -105, -105, -105,
+ -105, -105, 6, -9, -49, -50, -4, 26, -105, -4,
+ -105, -105, 24, -105, -105, -105, -105, -17, -52, 25,
+ -105, 9, 19, -7, -50, -50, -59, -59, -59, -44,
+ -59, -59, -59, -105, -105, -105, -105, -3, -105, -64,
+ -105, -4, -4, 73, -105, -105, -105, -105, -105, -105,
+ 22, -105, -105, -105, -105, -105, -19, -105, -105, -64,
+ 1, -105, -105
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yysigned_char yypgoto[] =
+{
+ -105, -105, -105, -105, -105, -105, -105, 42, -105, -105,
+ -105, -105, -105, -5, 97, -31, 18, -105, 75, -105,
+ -41, 30, 10, 85, 8
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -64
+static const yysigned_char yytable[] =
+{
+ 84, 1, 55, 84, 13, 119, 71, 14, 27, 53,
+ 75, 71, 22, 18, 14, 14, 14, 11, 69, 22,
+ 22, 23, 24, 18, 72, 38, 12, 28, 43, 72,
+ 47, 30, 14, 65, 83, 32, 22, 2, 31, 39,
+ 18, -61, 42, 18, 46, 18, 110, 33, 111, 48,
+ 34, 35, 56, 101, 102, 49, 73, 50, 117, 51,
+ 42, 103, 52, 77, 57, 58, 15, 64, 16, 16,
+ 16, 86, 76, 95, 74, 78, 59, 79, 121, 74,
+ 87, 81, 3, 88, 15, 82, 16, 54, 18, 21,
+ 85, 120, 80, 85, 93, 96, 25, 26, 60, 89,
+ 4, 98, 99, 100, 90, 107, 109, 115, 112, 113,
+ 114, 91, -63, 37, 118, 92, 106, 108, 108, 94,
+ 108, 108, 108, 122, 36, 70
+};
+
+static const unsigned char yycheck[] =
+{
+ 7, 31, 19, 7, 38, 24, 70, 66, 13, 24,
+ 51, 70, 4, 3, 66, 66, 66, 121, 49, 11,
+ 12, 0, 99, 13, 88, 30, 72, 52, 33, 88,
+ 35, 24, 66, 83, 65, 114, 28, 67, 39, 31,
+ 30, 39, 32, 33, 34, 35, 90, 16, 92, 137,
+ 83, 83, 69, 84, 85, 137, 120, 24, 99, 45,
+ 50, 120, 110, 53, 81, 82, 118, 110, 120, 120,
+ 120, 45, 59, 78, 138, 77, 93, 83, 119, 138,
+ 54, 90, 112, 57, 118, 134, 120, 102, 78, 4,
+ 97, 110, 86, 97, 70, 70, 11, 12, 115, 73,
+ 130, 92, 83, 110, 78, 87, 88, 110, 90, 91,
+ 92, 85, 39, 28, 92, 89, 86, 87, 88, 77,
+ 90, 91, 92, 122, 27, 50
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char yystos[] =
+{
+ 0, 31, 67, 112, 130, 148, 149, 150, 151, 158,
+ 159, 121, 72, 38, 66, 118, 120, 160, 169, 170,
+ 171, 170, 171, 0, 99, 170, 170, 160, 52, 161,
+ 24, 39, 114, 16, 83, 83, 161, 170, 160, 171,
+ 165, 166, 169, 160, 152, 153, 169, 160, 137, 137,
+ 24, 45, 110, 24, 102, 19, 69, 81, 82, 93,
+ 115, 154, 155, 156, 110, 83, 162, 168, 169, 162,
+ 165, 70, 88, 120, 138, 167, 59, 169, 77, 83,
+ 86, 90, 134, 162, 7, 97, 45, 54, 57, 73,
+ 78, 85, 89, 70, 154, 160, 70, 157, 92, 83,
+ 110, 162, 162, 120, 163, 167, 168, 163, 168, 163,
+ 90, 92, 163, 163, 163, 110, 164, 167, 92, 24,
+ 110, 167, 122
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrlab1
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror ("syntax error: cannot back up");\
+ YYERROR; \
+ } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+ are run). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ Current.first_line = Rhs[1].first_line; \
+ Current.first_column = Rhs[1].first_column; \
+ Current.last_line = Rhs[N].last_line; \
+ Current.last_column = Rhs[N].last_column;
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+# define YYDSYMPRINT(Args) \
+do { \
+ if (yydebug) \
+ yysymprint Args; \
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Token, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (cinluded). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short *bottom, short *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short *bottom;
+ short *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
+#endif
+{
+ int yyi;
+ unsigned int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
+{
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+\f
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (yytype < YYNTOKENS)
+ {
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ }
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+\f
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+ /* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+ register int yystate;
+ register int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short yyssa[YYINITDEPTH];
+ short *yyss = yyssa;
+ register short *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK (yyvsp--, yyssp--)
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
+ int yylen;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow ("parser stack overflow",
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyoverflowlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyoverflowlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ short *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyoverflowlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 143 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ *sql->view = yyvsp[0].query;
+ ;}
+ break;
+
+ case 3:
+#line 148 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ *sql->view = yyvsp[0].query;
+ ;}
+ break;
+
+ case 4:
+#line 153 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ *sql->view = yyvsp[0].query;
+ ;}
+ break;
+
+ case 5:
+#line 158 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ *sql->view = yyvsp[0].query;
+ ;}
+ break;
+
+ case 6:
+#line 166 "./sql.y"
+ {
+ SQL_input *sql = (SQL_input*) info;
+ MSIVIEW *insert = NULL;
+
+ INSERT_CreateView( sql->db, &insert, yyvsp[-7].string, yyvsp[-5].column_list, yyvsp[-1].val_list, FALSE );
+ yyval.query = insert;
+ ;}
+ break;
+
+ case 7:
+#line 174 "./sql.y"
+ {
+ SQL_input *sql = (SQL_input*) info;
+ MSIVIEW *insert = NULL;
+
+ INSERT_CreateView( sql->db, &insert, yyvsp[-8].string, yyvsp[-6].column_list, yyvsp[-2].val_list, TRUE );
+ yyval.query = insert;
+ ;}
+ break;
+
+ case 8:
+#line 185 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ MSIVIEW *create = NULL;
+
+ if( !yyvsp[-1].column_info )
+ YYABORT;
+ CREATE_CreateView( sql->db, &create, yyvsp[-3].string, yyvsp[-1].column_info, FALSE );
+ yyval.query = create;
+ ;}
+ break;
+
+ case 9:
+#line 195 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ MSIVIEW *create = NULL;
+
+ if( !yyvsp[-2].column_info )
+ YYABORT;
+ CREATE_CreateView( sql->db, &create, yyvsp[-4].string, yyvsp[-2].column_info, TRUE );
+ yyval.query = create;
+ ;}
+ break;
+
+ case 10:
+#line 208 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ MSIVIEW *update = NULL;
+
+ UPDATE_CreateView( sql->db, &update, yyvsp[-4].string, &yyvsp[-2].update_col_info, yyvsp[0].expr );
+ yyval.query = update;
+ ;}
+ break;
+
+ case 11:
+#line 219 "./sql.y"
+ {
+ if( SQL_MarkPrimaryKeys( yyvsp[-3].column_info, yyvsp[0].column_list ) )
+ yyval.column_info = yyvsp[-3].column_info;
+ else
+ yyval.column_info = NULL;
+ ;}
+ break;
+
+ case 12:
+#line 229 "./sql.y"
+ {
+ create_col_info *ci;
+
+ for( ci = yyvsp[-3].column_info; ci->next; ci = ci->next )
+ ;
+
+ ci->next = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.column_info );
+ if( !ci->next )
+ {
+ /* FIXME: free $1 */
+ YYABORT;
+ }
+ ci->next->colname = yyvsp[-1].string;
+ ci->next->type = yyvsp[0].column_type;
+ ci->next->next = NULL;
+
+ yyval.column_info = yyvsp[-3].column_info;
+ ;}
+ break;
+
+ case 13:
+#line 248 "./sql.y"
+ {
+ yyval.column_info = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.column_info );
+ if( ! yyval.column_info )
+ YYABORT;
+ yyval.column_info->colname = yyvsp[-1].string;
+ yyval.column_info->type = yyvsp[0].column_type;
+ yyval.column_info->next = NULL;
+ ;}
+ break;
+
+ case 14:
+#line 260 "./sql.y"
+ {
+ yyval.column_type = yyvsp[0].column_type | MSITYPE_VALID;
+ ;}
+ break;
+
+ case 15:
+#line 264 "./sql.y"
+ {
+ FIXME("LOCALIZABLE ignored\n");
+ yyval.column_type = yyvsp[-1].column_type | MSITYPE_VALID;
+ ;}
+ break;
+
+ case 16:
+#line 272 "./sql.y"
+ {
+ yyval.column_type |= MSITYPE_NULLABLE;
+ ;}
+ break;
+
+ case 17:
+#line 276 "./sql.y"
+ {
+ yyval.column_type = yyvsp[-2].column_type;
+ ;}
+ break;
+
+ case 18:
+#line 283 "./sql.y"
+ {
+ yyval.column_type = MSITYPE_STRING | 1;
+ ;}
+ break;
+
+ case 19:
+#line 287 "./sql.y"
+ {
+ yyval.column_type = MSITYPE_STRING | 0x400 | yyvsp[-1].column_type;
+ ;}
+ break;
+
+ case 20:
+#line 291 "./sql.y"
+ {
+ yyval.column_type = 2;
+ ;}
+ break;
+
+ case 21:
+#line 295 "./sql.y"
+ {
+ yyval.column_type = 2;
+ ;}
+ break;
+
+ case 22:
+#line 299 "./sql.y"
+ {
+ yyval.column_type = 2;
+ ;}
+ break;
+
+ case 23:
+#line 303 "./sql.y"
+ {
+ yyval.column_type = 4;
+ ;}
+ break;
+
+ case 24:
+#line 307 "./sql.y"
+ {
+ yyval.column_type = 0;
+ ;}
+ break;
+
+ case 25:
+#line 314 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ int val = SQL_getint(sql);
+ if( ( val > 255 ) || ( val < 0 ) )
+ YYABORT;
+ yyval.column_type = val;
+ ;}
+ break;
+
+ case 26:
+#line 325 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+
+ if( !yyvsp[-3].query )
+ YYABORT;
+ if( yyvsp[0].column_list )
+ yyval.query = do_order_by( sql->db, yyvsp[-3].query, yyvsp[0].column_list );
+ else
+ yyval.query = yyvsp[-3].query;
+ ;}
+ break;
+
+ case 28:
+#line 340 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ if( !yyvsp[0].query )
+ YYABORT;
+ if( yyvsp[-1].column_list )
+ {
+ yyval.query = do_one_select( sql->db, yyvsp[0].query, yyvsp[-1].column_list );
+ if( !yyval.query )
+ YYABORT;
+ }
+ else
+ yyval.query = yyvsp[0].query;
+ ;}
+ break;
+
+ case 29:
+#line 354 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ MSIVIEW *view = yyvsp[0].query;
+
+ if( !view )
+ YYABORT;
+ if( yyvsp[-1].column_list )
+ {
+ view = do_one_select( sql->db, view, yyvsp[-1].column_list );
+ if( !view )
+ YYABORT;
+ }
+ DISTINCT_CreateView( sql->db, & yyval.query, view );
+ ;}
+ break;
+
+ case 30:
+#line 372 "./sql.y"
+ {
+ string_list *list;
+
+ list = HeapAlloc( GetProcessHeap(), 0, sizeof *list );
+ if( !list )
+ YYABORT;
+ list->string = yyvsp[0].string;
+ list->next = NULL;
+
+ yyval.column_list = list;
+ TRACE("Collist %s\n",debugstr_w(yyval.column_list->string));
+ ;}
+ break;
+
+ case 31:
+#line 385 "./sql.y"
+ {
+ string_list *list;
+
+ list = HeapAlloc( GetProcessHeap(), 0, sizeof *list );
+ if( !list )
+ YYABORT;
+ list->string = yyvsp[-2].string;
+ list->next = yyvsp[0].column_list;
+
+ yyval.column_list = list;
+ TRACE("From table: %s\n",debugstr_w(yyval.column_list->string));
+ ;}
+ break;
+
+ case 32:
+#line 398 "./sql.y"
+ {
+ yyval.column_list = NULL;
+ ;}
+ break;
+
+ case 33:
+#line 405 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ UINT r;
+
+ yyval.query = NULL;
+ TRACE("From table: %s\n",debugstr_w(yyvsp[0].string));
+ r = TABLE_CreateView( sql->db, yyvsp[0].string, & yyval.query );
+ if( r != ERROR_SUCCESS )
+ YYABORT;
+ ;}
+ break;
+
+ case 34:
+#line 416 "./sql.y"
+ {
+ SQL_input* sql = (SQL_input*) info;
+ MSIVIEW *view = NULL;
+ UINT r;
+
+ yyval.query = NULL;
+ TRACE("From table: %s\n",debugstr_w(yyvsp[-2].string));
+ r = TABLE_CreateView( sql->db, yyvsp[-2].string, &view );
+ if( r != ERROR_SUCCESS )
+ YYABORT;
+ r = WHERE_CreateView( sql->db, &view, view, yyvsp[0].expr );
+ if( r != ERROR_SUCCESS )
+ YYABORT;
+ yyval.query = view;
+ ;}
+ break;
+
+ case 35:
+#line 435 "./sql.y"
+ {
+ yyval.expr = yyvsp[-1].expr;
+ ;}
+ break;
+
+ case 36:
+#line 439 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_EQ, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 37:
+#line 443 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_AND, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 38:
+#line 447 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_OR, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 39:
+#line 451 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_EQ, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 40:
+#line 455 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_GT, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 41:
+#line 459 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_LT, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 42:
+#line 463 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_LE, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 43:
+#line 467 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_GE, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 44:
+#line 471 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_NE, yyvsp[0].expr );
+ ;}
+ break;
+
+ case 45:
+#line 475 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_ISNULL, NULL );
+ ;}
+ break;
+
+ case 46:
+#line 479 "./sql.y"
+ {
+ yyval.expr = EXPR_complex( yyvsp[-3].expr, OP_NOTNULL, NULL );
+ ;}
+ break;
+
+ case 49:
+#line 491 "./sql.y"
+ {
+ value_list *vals;
+
+ vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );
+ if( vals )
+ {
+ vals->val = yyvsp[0].expr;
+ vals->next = NULL;
+ }
+ yyval.val_list = vals;
+ ;}
+ break;
+
+ case 50:
+#line 503 "./sql.y"
+ {
+ value_list *vals;
+
+ vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );
+ if( vals )
+ {
+ vals->val = yyvsp[0].expr;
+ vals->next = NULL;
+ }
+ yyvsp[-2].val_list->next = vals;
+ yyval.val_list = yyvsp[-2].val_list;
+ ;}
+ break;
+
+ case 52:
+#line 520 "./sql.y"
+ {
+ yyvsp[-2].update_col_info.col_list->next = yyvsp[0].update_col_info.col_list;
+ yyvsp[-2].update_col_info.val_list->next = yyvsp[0].update_col_info.val_list;
+ yyval.update_col_info = yyvsp[-2].update_col_info;
+ ;}
+ break;
+
+ case 53:
+#line 529 "./sql.y"
+ {
+ yyval.update_col_info.col_list = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.update_col_info.col_list );
+ if( !yyval.update_col_info.col_list )
+ YYABORT;
+ yyval.update_col_info.col_list->string = yyvsp[-2].string;
+ yyval.update_col_info.col_list->next = NULL;
+ yyval.update_col_info.val_list = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.update_col_info.val_list );
+ if( !yyval.update_col_info.val_list )
+ YYABORT;
+ yyval.update_col_info.val_list->val = yyvsp[0].expr;
+ yyval.update_col_info.val_list->next = 0;
+ ;}
+ break;
+
+ case 54:
+#line 545 "./sql.y"
+ {
+ yyval.expr = EXPR_ival( &yyvsp[0].str, 1 );
+ ;}
+ break;
+
+ case 55:
+#line 549 "./sql.y"
+ {
+ yyval.expr = EXPR_ival( &yyvsp[0].str, -1 );
+ ;}
+ break;
+
+ case 56:
+#line 553 "./sql.y"
+ {
+ yyval.expr = EXPR_sval( &yyvsp[0].str );
+ ;}
+ break;
+
+ case 57:
+#line 557 "./sql.y"
+ {
+ yyval.expr = EXPR_wildcard();
+ ;}
+ break;
+
+ case 58:
+#line 564 "./sql.y"
+ {
+ yyval.expr = EXPR_column( yyvsp[0].string );
+ ;}
+ break;
+
+ case 59:
+#line 571 "./sql.y"
+ {
+ yyval.string = yyvsp[0].string; /* FIXME */
+ ;}
+ break;
+
+ case 60:
+#line 575 "./sql.y"
+ {
+ yyval.string = yyvsp[0].string;
+ ;}
+ break;
+
+ case 61:
+#line 582 "./sql.y"
+ {
+ yyval.string = yyvsp[0].string;
+ ;}
+ break;
+
+ case 62:
+#line 589 "./sql.y"
+ {
+ yyval.string = SQL_getstring( &yyvsp[0].str );
+ ;}
+ break;
+
+ case 63:
+#line 593 "./sql.y"
+ {
+ yyval.string = SQL_getstring( &yyvsp[0].str );
+ ;}
+ break;
+
+
+ }
+
+/* Line 999 of yacc.c. */
+#line 2055 "sql.tab.c"
+\f
+ yyvsp -= yylen;
+ yyssp -= yylen;
+
+
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+ YYSIZE_T yysize = 0;
+ int yytype = YYTRANSLATE (yychar);
+ const char* yyprefix;
+ char *yymsg;
+ int yyx;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 0;
+
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+ yycount += 1;
+ if (yycount == 5)
+ {
+ yysize = 0;
+ break;
+ }
+ }
+ yysize += (sizeof ("syntax error, unexpected ")
+ + yystrlen (yytname[yytype]));
+ yymsg = (char *) YYSTACK_ALLOC (yysize);
+ if (yymsg != 0)
+ {
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+ yyp = yystpcpy (yyp, yytname[yytype]);
+
+ if (yycount < 5)
+ {
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yyp = yystpcpy (yyp, yyprefix);
+ yyp = yystpcpy (yyp, yytname[yyx]);
+ yyprefix = " or ";
+ }
+ }
+ yyerror (yymsg);
+ YYSTACK_FREE (yymsg);
+ }
+ else
+ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror ("syntax error");
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ {
+ /* Pop the error token. */
+ YYPOPSTACK;
+ /* Pop the rest of the stack. */
+ while (yyss < yyssp)
+ {
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[*yyssp], yyvsp);
+ YYPOPSTACK;
+ }
+ YYABORT;
+ }
+
+ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+ yydestruct (yytoken, &yylval);
+ yychar = YYEMPTY;
+
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*----------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action. |
+`----------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[yystate], yyvsp);
+ yyvsp--;
+ yystate = *--yyssp;
+
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+yyoverflowlab:
+ yyerror ("parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+ return yyresult;
+}
+
+
+#line 598 "./sql.y"
+
+
+int SQL_lex( void *SQL_lval, SQL_input *sql)
+{
+ int token;
+ struct sql_str * str = SQL_lval;
+
+ do
+ {
+ sql->n += sql->len;
+ if( ! sql->command[sql->n] )
+ return 0; /* end of input */
+
+ TRACE("string : %s\n", debugstr_w(&sql->command[sql->n]));
+ sql->len = sqliteGetToken( &sql->command[sql->n], &token );
+ if( sql->len==0 )
+ break;
+ str->data = &sql->command[sql->n];
+ str->len = sql->len;
+ }
+ while( token == TK_SPACE );
+
+ TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len));
+
+ return token;
+}
+
+LPWSTR SQL_getstring( struct sql_str *strdata)
+{
+ LPCWSTR p = strdata->data;
+ UINT len = strdata->len;
+ LPWSTR str;
+
+ /* if there's quotes, remove them */
+ if( ( (p[0]=='`') && (p[len-1]=='`') ) ||
+ ( (p[0]=='\'') && (p[len-1]=='\'') ) )
+ {
+ p++;
+ len -= 2;
+ }
+ str = HeapAlloc( GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
+ if(!str )
+ return str;
+ memcpy(str, p, len*sizeof(WCHAR) );
+ str[len]=0;
+
+ return str;
+}
+
+INT SQL_getint( SQL_input *sql )
+{
+ LPCWSTR p = &sql->command[sql->n];
+
+ return atoiW( p );
+}
+
+int SQL_error(const char *str)
+{
+ return 0;
+}
+
+static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in,
+ string_list *columns )
+{
+ MSIVIEW *view = NULL;
+
+ SELECT_CreateView( db, &view, in, columns );
+ delete_string_list( columns );
+ if( !view )
+ ERR("Error creating select query\n");
+ return view;
+}
+
+static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in,
+ string_list *columns )
+{
+ MSIVIEW *view = NULL;
+
+ ORDER_CreateView( db, &view, in );
+ if( view )
+ {
+ string_list *x = columns;
+
+ for( x = columns; x ; x = x->next )
+ ORDER_AddColumn( view, x->string );
+ }
+ else
+ ERR("Error creating select query\n");
+ delete_string_list( columns );
+ return view;
+}
+
+static struct expr * EXPR_wildcard()
+{
+ struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
+ if( e )
+ {
+ e->type = EXPR_WILDCARD;
+ }
+ return e;
+}
+
+static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r )
+{
+ struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
+ if( e )
+ {
+ e->type = EXPR_COMPLEX;
+ e->u.expr.left = l;
+ e->u.expr.op = op;
+ e->u.expr.right = r;
+ }
+ return e;
+}
+
+static struct expr * EXPR_column( LPWSTR str )
+{
+ struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
+ if( e )
+ {
+ e->type = EXPR_COLUMN;
+ e->u.sval = str;
+ }
+ return e;
+}
+
+static struct expr * EXPR_ival( struct sql_str *str , int sign)
+{
+ struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
+ if( e )
+ {
+ e->type = EXPR_IVAL;
+ e->u.ival = atoiW( str->data ) * sign;
+ }
+ return e;
+}
+
+static struct expr * EXPR_sval( struct sql_str *str )
+{
+ struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
+ if( e )
+ {
+ e->type = EXPR_SVAL;
+ e->u.sval = SQL_getstring( str );
+ }
+ return e;
+}
+
+void delete_expr( struct expr *e )
+{
+ if( !e )
+ return;
+ if( e->type == EXPR_COMPLEX )
+ {
+ delete_expr( e->u.expr.left );
+ delete_expr( e->u.expr.right );
+ }
+ else if( e->type == EXPR_UTF8 )
+ HeapFree( GetProcessHeap(), 0, e->u.utf8 );
+ else if( e->type == EXPR_SVAL )
+ HeapFree( GetProcessHeap(), 0, e->u.sval );
+ HeapFree( GetProcessHeap(), 0, e );
+}
+
+void delete_string_list( string_list *sl )
+{
+ while( sl )
+ {
+ string_list *t = sl->next;
+ HeapFree( GetProcessHeap(), 0, sl->string );
+ HeapFree( GetProcessHeap(), 0, sl );
+ sl = t;
+ }
+}
+
+void delete_value_list( value_list *vl )
+{
+ while( vl )
+ {
+ value_list *t = vl->next;
+ delete_expr( vl->val );
+ HeapFree( GetProcessHeap(), 0, vl );
+ vl = t;
+ }
+}
+
+static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,
+ string_list *keys )
+{
+ string_list *k;
+ BOOL found = TRUE;
+
+ for( k = keys; k && found; k = k->next )
+ {
+ create_col_info *c;
+
+ found = FALSE;
+ for( c = cols; c && !found; c = c->next )
+ {
+ if( lstrcmpW( k->string, c->colname ) )
+ continue;
+ c->type |= MSITYPE_KEY;
+ found = TRUE;
+ }
+ }
+
+ return found;
+}
+
+UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview )
+{
+ SQL_input sql;
+ int r;
+
+ *phview = NULL;
+
+ sql.db = db;
+ sql.command = command;
+ sql.n = 0;
+ sql.len = 0;
+ sql.view = phview;
+
+ r = SQL_parse(&sql);
+
+ TRACE("Parse returned %d\n", r);
+ if( r )
+ {
+ if( *sql.view )
+ (*sql.view)->ops->delete( *sql.view );
+ *sql.view = NULL;
+ return ERROR_BAD_QUERY_SYNTAX;
+ }
+
+ return ERROR_SUCCESS;
+}
+