desc.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /***************************************************************************
  2. * Licensed Materials - Property of IBM and/or HCL
  3. *
  4. * IBM Informix Client-SDK
  5. *
  6. * (C) Copyright IBM Corporation 1997, 2004 All rights reserved.
  7. * (c) Copyright HCL Technologies Ltd. 2017. All Rights Reserved.
  8. *
  9. *
  10. *
  11. *
  12. *
  13. * Title: desc.c
  14. *
  15. * Description: To allocate a single descriptor and use it as the ARD
  16. * for a SELECT statement and as the APD for an INSERT
  17. * statement.
  18. * The data will be selected from the 'customer' table
  19. * and inserted into a new table called 'new_cust'
  20. *
  21. ***************************************************************************
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #ifndef NO_WIN32
  27. #include <io.h>
  28. #include <windows.h>
  29. #include <conio.h>
  30. #endif /*NO_WIN32*/
  31. #include "infxcli.h"
  32. #define BUFFER_LEN 10
  33. #define ERRMSG_LEN 200
  34. SQLCHAR defDsn[] = "odbc_demo";
  35. SQLINTEGER checkError (SQLRETURN rc,
  36. SQLSMALLINT handleType,
  37. SQLHANDLE handle,
  38. SQLCHAR* errmsg)
  39. {
  40. SQLRETURN retcode = SQL_SUCCESS;
  41. SQLSMALLINT errNum = 1;
  42. SQLCHAR sqlState[6];
  43. SQLINTEGER nativeError;
  44. SQLCHAR errMsg[ERRMSG_LEN];
  45. SQLSMALLINT textLengthPtr;
  46. if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
  47. {
  48. while (retcode != SQL_NO_DATA)
  49. {
  50. retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState, &nativeError, errMsg, ERRMSG_LEN, &textLengthPtr);
  51. if (retcode == SQL_INVALID_HANDLE)
  52. {
  53. fprintf (stderr, "checkError function was called with an invalid handle!!\n");
  54. return 1;
  55. }
  56. if ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
  57. fprintf (stderr, "ERROR: %d: %s : %s \n", nativeError, sqlState, errMsg);
  58. errNum++;
  59. }
  60. fprintf (stderr, "%s\n", errmsg);
  61. return 1; /* all errors on this handle have been reported */
  62. }
  63. else
  64. return 0; /* no errors to report */
  65. }
  66. int main (long argc,
  67. char* argv[])
  68. {
  69. /* Declare variables
  70. */
  71. /* Handles */
  72. SQLHDBC hdbc;
  73. SQLHENV henv;
  74. SQLHSTMT hTableStmt;
  75. SQLHSTMT hSelectStmt;
  76. SQLHSTMT hInsertStmt;
  77. SQLHDESC hdesc;
  78. /* Miscellaneous variables */
  79. SQLCHAR dsn[20]; /*name of the DSN used for connecting to the database*/
  80. SQLRETURN rc = 0;
  81. SQLINTEGER i, in;
  82. SQLCHAR* createTableStmt = (SQLCHAR *) "CREATE TABLE new_cust(cust_num INTEGER,\
  83. fname VARCHAR(10),\
  84. lname VARCHAR(10))";
  85. SQLCHAR* selectStmt = (SQLCHAR *) "SELECT cust_num, fname, lname from customer where cust_num < 110";
  86. SQLCHAR* insertStmt = (SQLCHAR *) "INSERT INTO new_cust (cust_num, fname, lname) VALUES (?, ?, ?)";
  87. SQLINTEGER custnumArray[9]; /*array to hold values of 'cust_num' from table 'customer'*/
  88. SQLCHAR fnameArray[9][BUFFER_LEN]; /*array to hold values of 'fname' from table 'customer'*/
  89. SQLCHAR lnameArray[9][BUFFER_LEN]; /*array to hold values of 'lname' from table 'customer'*/
  90. SQLINTEGER newCustnum; /*value of 'cust_num' from table 'new_cust'*/
  91. SQLCHAR newFname[BUFFER_LEN]; /*value of 'fname' from table 'new_cust'*/
  92. SQLCHAR newLname[BUFFER_LEN]; /*value of 'lname' from table 'new_cust'*/
  93. SQLLEN cbCustnum = 0, cbFname = SQL_NTS, cbLname = SQL_NTS;
  94. /* STEP 1. Get data source name from command line (or use default)
  95. ** Allocate the environment handle and set ODBC version
  96. ** Allocate the connection handle
  97. ** Establish the database connection
  98. ** Allocate the statement handles
  99. ** Allocate the descriptor handle
  100. */
  101. /* If(dsn is not explicitly passed in as arg) */
  102. if (argc != 2)
  103. {
  104. /* Use default dsn - odbc_demo */
  105. fprintf (stdout, "\nUsing default DSN : %s\n", defDsn);
  106. strcpy ((char *)dsn, (char *)defDsn);
  107. }
  108. else
  109. {
  110. /* Use specified dsn */
  111. strcpy ((char *)dsn, (char *)argv[1]);
  112. fprintf (stdout, "\nUsing specified DSN : %s\n", dsn);
  113. }
  114. /* Allocate the Environment handle */
  115. rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
  116. if (rc != SQL_SUCCESS)
  117. {
  118. fprintf (stdout, "Environment Handle Allocation failed\nExiting!!");
  119. return (1);
  120. }
  121. /* Set the ODBC version to 3.0 */
  122. rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
  123. if (checkError (rc, SQL_HANDLE_ENV, henv, (SQLCHAR *) "Error in Step 1 -- SQLSetEnvAttr failed\nExiting!!"))
  124. return (1);
  125. /* Allocate the connection handle */
  126. rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
  127. if (checkError (rc, SQL_HANDLE_ENV, henv, (SQLCHAR *) "Error in Step 1 -- Connection Handle Allocation failed\nExiting!!"))
  128. return (1);
  129. /* Establish the database connection */
  130. rc = SQLConnect (hdbc, dsn, SQL_NTS, (SQLCHAR *) "", SQL_NTS, (SQLCHAR *) "", SQL_NTS);
  131. if (checkError (rc, SQL_HANDLE_DBC, hdbc, (SQLCHAR *) "Error in Step 1 -- SQLConnect failed\nExiting!!"))
  132. return (1);
  133. /* Allocate the statement handle for the CREATE TABLE statement */
  134. rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hTableStmt);
  135. if (checkError (rc, SQL_HANDLE_DBC, hdbc, (SQLCHAR *) "Error in Step 1 -- Create Table Statement Handle Allocation failed\nExiting!!"))
  136. return (1);
  137. /* Allocate the statement handle for the SELECT statement */
  138. rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hSelectStmt);
  139. if (checkError (rc, SQL_HANDLE_DBC, hdbc, (SQLCHAR *) "Error in Step 1 -- Select Statement Handle Allocation failed\nExiting!!"))
  140. return (1);
  141. /* Allocate the statement handle for the INSERT statement */
  142. rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hInsertStmt);
  143. if (checkError (rc, SQL_HANDLE_DBC, hdbc, (SQLCHAR *) "Error in Step 1 -- Insert Statement Handle Allocation failed\nExiting!!"))
  144. return (1);
  145. /* Allocate the descriptor handle */
  146. rc = SQLAllocHandle (SQL_HANDLE_DESC, hdbc, &hdesc);
  147. if (checkError (rc, SQL_HANDLE_DBC, hdbc, (SQLCHAR *) "Error in Step 1 -- Insert Statement Handle Allocation failed\nExiting!!"))
  148. return (1);
  149. fprintf (stdout, "STEP 1 done...connected to database\n");
  150. /* STEP 2. Create the database table 'new_cust' where the data is to be inserted
  151. */
  152. /* Execute the SQL statement to create the table 'new_cust' */
  153. rc = SQLExecDirect (hTableStmt, createTableStmt, SQL_NTS);
  154. if (checkError (rc, SQL_HANDLE_STMT, hTableStmt, (SQLCHAR *) "Error in Step 2 -- SQLExecDirect failed\n" ))
  155. goto Exit;
  156. fprintf (stdout, "STEP 2 done...table new_cust created in the datbase\n");
  157. /* STEP 3. For each column, set the following descriptor fields to appropriate values
  158. ** -- column 'cust_num' : descriptor fields - SQL_DESC_TYPE
  159. ** -- column 'fname' : descriptor fields - SQL_DESC_TYPE, SQL_DESC_LENGTH,
  160. ** SQL_DESC_OCTET_LENGTH
  161. ** -- column 'lname' : descriptor fields - SQL_DESC_TYPE, SQL_DESC_LENGTH,
  162. ** SQL_DESC_OCTET_LENGTH
  163. */
  164. /* Setting descriptor fields for column - cust_num */
  165. rc = SQLSetDescField (hdesc, 1, SQL_DESC_TYPE, (SQLPOINTER) SQL_C_SLONG, 0);
  166. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 3 -- SQLSetDescField (SQL_DESC_DATA_TYPE) failed for column cust_num\n"))
  167. goto Exit;
  168. /* Setting descriptor fields for column - fname */
  169. rc = SQLSetDescField (hdesc, 2, SQL_DESC_TYPE, (SQLPOINTER) SQL_C_CHAR, 0);
  170. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 3 -- SQLSetDescField (SQL_DESC_DATA_TYPE) failed for column fname\n"))
  171. goto Exit;
  172. rc = SQLSetDescField (hdesc, 2, SQL_DESC_LENGTH, (SQLPOINTER) BUFFER_LEN, 0);
  173. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 3 -- SQLSetDescField (SQL_DESC_LENGTH) failed for column fname\n"))
  174. goto Exit;
  175. rc = SQLSetDescField (hdesc, 2, SQL_DESC_OCTET_LENGTH, (SQLPOINTER) BUFFER_LEN, 0);
  176. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 3 -- SQLSetDescField (SQL_DESC_OCTET_LENGTH) failed for column fname\n"))
  177. goto Exit;
  178. /* Setting descriptor fields for column - lname */
  179. rc = SQLSetDescField (hdesc, 3, SQL_DESC_TYPE, (SQLPOINTER) SQL_C_CHAR, 0);
  180. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 3 -- SQLSetDescField (SQL_DESC_DATA_TYPE) failed for column lname\n"))
  181. goto Exit;
  182. rc = SQLSetDescField (hdesc, 3, SQL_DESC_LENGTH, (SQLPOINTER) BUFFER_LEN, 0);
  183. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 3 -- SQLSetDescField (SQL_DESC_LENGTH) failed for column lname\n"))
  184. goto Exit;
  185. rc = SQLSetDescField (hdesc, 3, SQL_DESC_OCTET_LENGTH, (SQLPOINTER) BUFFER_LEN, 0);
  186. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 3 -- SQLSetDescField (SQL_DESC_OCTET_LENGTH) failed for column lname\n"))
  187. goto Exit;
  188. fprintf (stdout, "STEP 3 done...descriptor fields set for all columns\nRetrieving data from table 'customer'\n\n");
  189. /* STEP 4. Set the explicitly allocated descriptor handle as the ARD for the select
  190. ** statement's handle
  191. ** Execute the SELECT statement
  192. ** Set the descriptor fields with the values returned by the SELECT statement
  193. ** Fetch the results
  194. ** Close the result set cursor
  195. */
  196. /* Set the explicitly allocated descriptor handle as the ARD for the select statement */
  197. rc = SQLSetStmtAttr (hSelectStmt, SQL_ATTR_APP_ROW_DESC, (SQLPOINTER) hdesc, 0);
  198. if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 4 -- SQLSetStmtAttr failed\n"))
  199. goto Exit;
  200. /* Execute the SELECT statement */
  201. rc = SQLExecDirect (hSelectStmt, selectStmt, SQL_NTS);
  202. if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 4 -- SQLExecDirect failed\n"))
  203. goto Exit;
  204. for (i = 0; i < 9; i++)
  205. {
  206. /* Set the descriptor fields for the values being returned */
  207. rc = SQLSetDescField (hdesc, 1, SQL_DESC_DATA_PTR, &(custnumArray[i]), sizeof(custnumArray[i])/*SQL_IS_INTEGER*/);
  208. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 4 -- SQLSetDescField failed for column cust_num\n"))
  209. goto Exit;
  210. rc = SQLSetDescField (hdesc, 2, SQL_DESC_DATA_PTR, fnameArray[i], BUFFER_LEN);
  211. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 4 -- SQLSetDescField failed for column fname\n"))
  212. goto Exit;
  213. rc = SQLSetDescField (hdesc, 3, SQL_DESC_DATA_PTR, lnameArray[i], BUFFER_LEN);
  214. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 4 -- SQLSetDescField failed for column lname\n"))
  215. goto Exit;
  216. /* Fetch the results */
  217. rc = SQLFetch (hSelectStmt);
  218. if (rc == SQL_NO_DATA_FOUND)
  219. break;
  220. else if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 4 -- SQLFetch failed\n"))
  221. goto Exit;
  222. /* Display the results */
  223. fprintf (stdout, "Row retrieved from table 'customer' is - cust_num=%d, fname=%s, lname=%s\n",
  224. custnumArray[i], fnameArray[i], lnameArray[i]);
  225. }
  226. /* Close the result set cursor */
  227. rc = SQLCloseCursor (hSelectStmt);
  228. if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 4 -- SQLCloseCursor failed\n"))
  229. goto Exit;
  230. fprintf (stdout, "\n\nSTEP 4 done...SELECT statement executed...descriptor fields set with data retrieved\n");
  231. /* STEP 5. Set the explicitly allocated descriptor handle as the APD for the INSERT
  232. ** statement's handle
  233. ** Bind the input parameters for the INSERT statement
  234. ** For each row, set the SQL_DESC_DATA_PTR field to the value in the allocated
  235. ** arrays and execute the INSERT statement
  236. */
  237. /* Set the explicitly allocated descriptor handle as the APD for the INSERT statement */
  238. rc = SQLSetStmtAttr (hInsertStmt, SQL_ATTR_APP_PARAM_DESC, (SQLPOINTER) hdesc, 0);
  239. if (checkError (rc, SQL_HANDLE_STMT, hInsertStmt, (SQLCHAR *) "Error in Step 5 -- SQLSetStmtAttr failed\n"))
  240. goto Exit;
  241. /* Bind the input parameters for the INSERT statement */
  242. rc = SQLBindParameter (hInsertStmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
  243. 0, 0, &(custnumArray[i]), sizeof(custnumArray[i]), &cbCustnum);
  244. if (checkError (rc, SQL_HANDLE_STMT, hInsertStmt, (SQLCHAR *) "Error in Step 5 -- SQLBindParameter failed (param 1)\n"))
  245. goto Exit;
  246. rc = SQLBindParameter (hInsertStmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, BUFFER_LEN,
  247. 0, fnameArray[i], BUFFER_LEN, &cbFname);
  248. if (checkError (rc, SQL_HANDLE_STMT, hInsertStmt, (SQLCHAR *) "Error in Step 5 -- SQLBindParameter failed (param 2)\n"))
  249. goto Exit;
  250. rc = SQLBindParameter (hInsertStmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, BUFFER_LEN,
  251. 0, lnameArray[i], BUFFER_LEN, &cbLname);
  252. if (checkError (rc, SQL_HANDLE_STMT, hInsertStmt, (SQLCHAR *) "Error in Step 5 -- SQLBindParameter failed (param 3)\n"))
  253. goto Exit;
  254. /* For each row, set the SQL_DESC_DATA_PTR field and execute the INSERT statement */
  255. for (i = 0; i < 9; i++)
  256. {
  257. rc = SQLSetDescField (hdesc, 1, SQL_DESC_DATA_PTR, &(custnumArray[i]), sizeof(custnumArray[i]));
  258. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 5 -- SQLSetDescField failed for column cust_num\n"))
  259. goto Exit;
  260. rc = SQLSetDescField (hdesc, 2, SQL_DESC_DATA_PTR, fnameArray[i], BUFFER_LEN);
  261. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 5 -- SQLSetDescField failed for column fname\n"))
  262. goto Exit;
  263. rc = SQLSetDescField (hdesc, 3, SQL_DESC_DATA_PTR, lnameArray[i], BUFFER_LEN);
  264. if (checkError (rc, SQL_HANDLE_DESC, hdesc, (SQLCHAR *) "Error in Step 5 -- SQLSetDescField failed for column lname\n"))
  265. goto Exit;
  266. /* Execute the INSERT statement */
  267. rc = SQLExecDirect (hInsertStmt, insertStmt, SQL_NTS);
  268. if (checkError (rc, SQL_HANDLE_STMT, hInsertStmt, (SQLCHAR *) "Error in Step 5 -- SQLExecDirect failed\n"))
  269. goto Exit;
  270. }
  271. fprintf (stdout, "STEP 5 done...data inserted into table new_cust\n");
  272. fprintf (stdout, "\nRetrieving data from table 'new_cust'...\nHit <Enter> to continue...\n");
  273. in = getchar ();
  274. /* STEP 6. Execute the SELECT statement to retrieve data from
  275. ** table 'new_cust'
  276. ** Bind the result set columns
  277. ** Fetch and display the data
  278. */
  279. /* Execute the SELECT statement */
  280. rc = SQLExecDirect (hSelectStmt, (SQLCHAR *) "SELECT * FROM new_cust", SQL_NTS);
  281. if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 6 -- SQLExecDirect failed\n"))
  282. goto Exit;
  283. /* Bind the result set columns */
  284. rc = SQLBindCol (hSelectStmt, 1, SQL_C_LONG, &newCustnum, sizeof(newCustnum), &cbCustnum);
  285. if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 6 -- SQLBindCol failed (column 1)\n"))
  286. goto Exit;
  287. rc = SQLBindCol (hSelectStmt, 2, SQL_C_CHAR, newFname, BUFFER_LEN, &cbFname);
  288. if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 6 -- SQLBindCol failed (column 2)\n"))
  289. goto Exit;
  290. rc = SQLBindCol (hSelectStmt, 3, SQL_C_CHAR, newLname, BUFFER_LEN, &cbLname);
  291. if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 6 -- SQLBindCol failed (column 3)\n"))
  292. goto Exit;
  293. /* Fetch and display the data retrieved */
  294. while (1)
  295. {
  296. /* Fetch the results */
  297. rc = SQLFetch (hSelectStmt);
  298. if (rc == SQL_NO_DATA_FOUND)
  299. break;
  300. else if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 6 -- SQLFetch failed\n"))
  301. goto Exit;
  302. /* Display the results */
  303. fprintf (stdout, "Row retrieved from table 'new_cust' is - cust_num=%d, fname=%s, lname=%s\n", newCustnum, newFname, newLname);
  304. }
  305. /* Close the result set cursor */
  306. rc = SQLCloseCursor (hSelectStmt);
  307. if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, (SQLCHAR *) "Error in Step 6 -- SQLCloseCursor failed\n"))
  308. goto Exit;
  309. fprintf (stdout, "\n\nSTEP 6 done...SELECT statement executed...data retrieved from table 'new_cust'\n");
  310. Exit:
  311. /* CLEANUP: Drop table 'new_cust' from the database
  312. ** Close the statement handle
  313. ** Free the statement handle
  314. ** Disconnect from the datasource
  315. ** Free the connection and environment handles
  316. ** Exit
  317. */
  318. SQLExecDirect (hTableStmt, (SQLCHAR *) "DROP TABLE new_cust", SQL_NTS);
  319. /* Close all the statement handles */
  320. SQLFreeStmt (hTableStmt, SQL_CLOSE);
  321. SQLFreeStmt (hSelectStmt, SQL_CLOSE);
  322. SQLFreeStmt (hInsertStmt, SQL_CLOSE);
  323. /* Free all the statement handles */
  324. SQLFreeHandle (SQL_HANDLE_STMT, hTableStmt);
  325. SQLFreeHandle (SQL_HANDLE_STMT, hSelectStmt);
  326. SQLFreeHandle (SQL_HANDLE_STMT, hInsertStmt);
  327. /* Free the descriptor handle */
  328. SQLFreeHandle (SQL_HANDLE_DESC, hdesc);
  329. /* Disconnect from the data source */
  330. SQLDisconnect (hdbc);
  331. /* Free the environment handle and the database connection handle */
  332. SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
  333. SQLFreeHandle (SQL_HANDLE_ENV, henv);
  334. fprintf (stdout,"\n\nHit <Enter> to terminate the program...\n\n");
  335. in = getchar ();
  336. return (rc);
  337. }