alpar@1: %* glpk06.tex *% alpar@1: alpar@1: \chapter{Miscellaneous API Routines} alpar@1: alpar@1: \section{GLPK environment routines} alpar@1: alpar@1: \subsection{glp\_long---64-bit integer data type} alpar@1: alpar@1: Some GLPK API routines use 64-bit integer data type, which is declared alpar@1: in the header \verb|glpk.h| as follows: alpar@1: alpar@1: \begin{verbatim} alpar@1: typedef struct { int lo, hi; } glp_long; alpar@1: \end{verbatim} alpar@1: alpar@1: \noindent alpar@1: where \verb|lo| contains low 32 bits, and \verb|hi| contains high 32 alpar@1: bits of 64-bit integer value.\footnote{GLPK conforms to ILP32, LLP64, alpar@1: and LP64 programming models, where the built-in type {\tt int} alpar@1: corresponds to 32-bit integers.} alpar@1: alpar@1: \subsection{glp\_init\_env---initialize GLPK environment} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: int glp_init_env(void); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_init_env| initializes the GLPK environment. alpar@1: Normally the application program does not need to call this routine, alpar@1: because it is called automatically on the first call to any API routine. alpar@1: alpar@1: \newpage alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_init_env| returns one of the following codes: alpar@1: alpar@1: \noindent alpar@1: 0 --- initialization successful; alpar@1: alpar@1: \noindent alpar@1: 1 --- environment is already initialized; alpar@1: alpar@1: \noindent alpar@1: 2 --- initialization failed (insufficient memory); alpar@1: alpar@1: \noindent alpar@1: 3 --- initialization failed (unsupported programming model). alpar@1: alpar@1: \subsection{glp\_version---determine library version} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: const char *glp_version(void); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_version| returns a pointer to a null-terminated alpar@1: character string, which specifies the version of the GLPK library in alpar@1: the form \verb|"X.Y"|, where `\verb|X|' is the major version number, and alpar@1: `\verb|Y|' is the minor version number, for example, \verb|"4.16"|. alpar@1: alpar@1: \subsubsection*{Example} alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: printf("GLPK version is %s\n", glp_version()); alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: \subsection{glp\_free\_env---free GLPK environment} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: int glp_free_env(void); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_free_env| frees all resources used by GLPK alpar@1: routines (memory blocks, etc.) which are currently still in use. alpar@1: alpar@1: Normally the application program does not need to call this routine, alpar@1: because GLPK routines always free all unused resources. However, if alpar@1: the application program even has deleted all problem objects, there alpar@1: will be several memory blocks still allocated for the internal library alpar@1: needs. For some reasons the application program may want GLPK to free alpar@1: this memory, in which case it should call \verb|glp_free_env|. alpar@1: alpar@1: Note that a call to \verb|glp_free_env| invalidates all problem objects alpar@1: which still exist. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_free_env| returns one of the following codes: alpar@1: alpar@1: \noindent alpar@1: 0 --- termination successful; alpar@1: alpar@1: \noindent alpar@1: 1 --- environment is inactive (was not initialized). alpar@1: alpar@1: \subsection{glp\_printf---write formatted output to terminal} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_printf(const char *fmt, ...); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_printf| uses the format control string alpar@1: \verb|fmt| to format its parameters and writes the formatted output to alpar@1: the terminal. alpar@1: alpar@1: This routine is a replacement of the standard C function alpar@1: \verb|printf| and used by all GLPK routines to perform terminal alpar@1: output. The application program may use \verb|glp_printf| for the same alpar@1: purpose that allows controlling its terminal output with the routines alpar@1: \verb|glp_term_out| and \verb|glp_term_hook|. alpar@1: alpar@1: \subsection{glp\_vprintf---write formatted output to terminal} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_vprintf(const char *fmt, va_list arg); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_vprintf| uses the format control string alpar@1: \verb|fmt| to format its parameters specified by the list \verb|arg| alpar@1: and writes the formatted output to the terminal. alpar@1: alpar@1: This routine is a replacement of the standard C function alpar@1: \verb|vprintf| and used by all GLPK routines to perform terminal alpar@1: output. The application program may use \verb|glp_vprintf| for the same alpar@1: purpose that allows controlling its terminal output with the routines alpar@1: \verb|glp_term_out| and \verb|glp_term_hook|. alpar@1: alpar@1: \newpage alpar@1: alpar@1: \subsection{glp\_term\_out---enable/disable terminal output} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: int glp_term_out(int flag); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: Depending on the parameter flag the routine \verb|glp_term_out| enables alpar@1: or disables terminal output performed by glpk routines: alpar@1: alpar@1: \verb|GLP_ON | --- enable terminal output; alpar@1: alpar@1: \verb|GLP_OFF| --- disable terminal output. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_term_out| returns the previous value of the alpar@1: terminal output flag (\verb|GLP_ON| or \verb|GLP_OFF|). alpar@1: alpar@1: \subsection{glp\_term\_hook---intercept terminal output} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_term_hook(int (*func)(void *info, const char *s), alpar@1: void *info); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_term_hook| installs the user-defined hook routine alpar@1: to intercept all terminal output performed by GLPK routines. alpar@1: alpar@1: %This feature can be used to redirect the terminal output to other alpar@1: %destination, for example, to a file or a text window. alpar@1: alpar@1: The parameter {\it func} specifies the user-defined hook routine. It is alpar@1: called from an internal printing routine, which passes to it two alpar@1: parameters: {\it info} and {\it s}. The parameter {\it info} is a alpar@1: transit pointer specified in corresponding call to the routine alpar@1: \verb|glp_term_hook|; it may be used to pass some additional information alpar@1: to the hook routine. The parameter {\it s} is a pointer to the null alpar@1: terminated character string, which is intended to be written to the alpar@1: terminal. If the hook routine returns zero, the printing routine writes alpar@1: the string {\it s} to the terminal in a usual way; otherwise, if the alpar@1: hook routine returns non-zero, no terminal output is performed. alpar@1: alpar@1: To uninstall the hook routine both parameters {\it func} and {\it info} alpar@1: should be specified as \verb|NULL|. alpar@1: alpar@1: \newpage alpar@1: alpar@1: \subsubsection*{Example} alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: static int hook(void *info, const char *s) alpar@1: { FILE *foo = info; alpar@1: fputs(s, foo); alpar@1: return 1; alpar@1: } alpar@1: alpar@1: int main(void) alpar@1: { FILE *foo; alpar@1: . . . alpar@1: /* redirect terminal output */ alpar@1: glp_term_hook(hook, foo); alpar@1: . . . alpar@1: /* resume terminal output */ alpar@1: glp_term_hook(NULL, NULL); alpar@1: . . . alpar@1: } alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: \subsection{glp\_open\_tee---start copying terminal output} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: int glp_open_tee(const char *fname); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_open_tee| starts copying all the terminal output alpar@1: to an output text file, whose name is specified by the character string alpar@1: \verb|fname|. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_open_tee| returns one of the following codes: alpar@1: alpar@1: \noindent alpar@1: 0 --- operation successful; alpar@1: alpar@1: \noindent alpar@1: 1 --- copying terminal output is already active; alpar@1: alpar@1: \noindent alpar@1: 2 --- unable to create output file. alpar@1: alpar@1: \newpage alpar@1: alpar@1: \subsection{glp\_close\_tee---stop copying terminal output} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: int glp_close_tee(void); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_close_tee| stops copying the terminal output to alpar@1: the output text file previously open by the routine \verb|glp_open_tee| alpar@1: closing that file. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_close_tee| returns one of the following codes: alpar@1: alpar@1: \noindent alpar@1: 0 --- operation successful; alpar@1: alpar@1: \noindent alpar@1: 1 --- copying terminal output was not started. alpar@1: alpar@1: \subsection{glp\_error---display error message and terminate execution} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_error(const char *fmt, ...); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_error| (implemented as a macro) formats its alpar@1: parameters using the format control string \verb|fmt|, writes the alpar@1: formatted message to the terminal, and then abnormally terminates the alpar@1: program. alpar@1: alpar@1: \subsection{glp\_assert---check logical condition} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_assert(int expr); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_assert| (implemented as a macro) checks alpar@1: a logical condition specified by the expression \verb|expr|. If the alpar@1: condition is true (non-zero), the routine does nothing; otherwise, if alpar@1: the condition is false (zero), the routine prints an error message and alpar@1: abnormally terminates the program. alpar@1: alpar@1: This routine is a replacement of the standard C function \verb|assert| alpar@1: and used by all GLPK routines to check program logic. The application alpar@1: program may use \verb|glp_assert| for the same purpose. alpar@1: alpar@1: \subsection{glp\_error\_hook---install hook to intercept abnormal alpar@1: termination} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_error_hook(void (*func)(void *info), void *info); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_error_hook| installs a user-defined hook routine alpar@1: to intercept abnormal termination. alpar@1: alpar@1: The parameter \verb|func| specifies the user-defined hook routine. It alpar@1: is called from the routine \verb|glp_error| before the latter calls the alpar@1: abort function to abnormally terminate the application program because alpar@1: of fatal error. The parameter \verb|info| is a transit pointer, alpar@1: specified in the corresponding call to the routine alpar@1: \verb|glp_error_hook|; it may be used to pass some information to the alpar@1: hook routine. alpar@1: alpar@1: To uninstall the hook routine the parameters \verb|func| and \verb|info| alpar@1: should be specified as \verb|NULL|. alpar@1: alpar@1: \subsubsection*{Usage note} alpar@1: alpar@1: If the hook routine returns, the application program is abnormally alpar@1: terminated. To prevent abnormal termnation the hook routine may perform alpar@1: a global jump using the standard function \verb|longjmp|, in which case alpar@1: the application program {\it must} call the routine \verb|glp_free_env|. alpar@1: alpar@1: \subsection{glp\_malloc---allocate memory block} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void *glp_malloc(int size); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_malloc| dynamically allocates a memory block of alpar@1: \verb|size| bytes long. Should note that: alpar@1: alpar@1: 1) the parameter \verb|size| must be positive; alpar@1: alpar@1: 2) being allocated the memory block contains arbitrary data, that is, alpar@1: it is {\it not} initialized by binary zeros; alpar@1: alpar@1: 3) if the block cannot be allocated due to insufficient memory, the alpar@1: routine prints an error message and abnormally terminates the program. alpar@1: alpar@1: This routine is a replacement of the standard C function \verb|malloc| alpar@1: and used by all GLPK routines for dynamic memory allocation. The alpar@1: application program may use \verb|glp_malloc| for the same purpose. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_malloc| returns a pointer to the memory block alpar@1: allocated. To free this block the routine \verb|glp_free| (not the alpar@1: standard C function \verb|free|!) must be used. alpar@1: alpar@1: \subsection{glp\_calloc---allocate memory block} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void *glp_calloc(int n, int size); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_calloc| dynamically allocates a memory block of alpar@1: \verb|n|$\times$\verb|size| bytes long. Should note that: alpar@1: alpar@1: 1) both parameters \verb|n| and \verb|size| must be positive; alpar@1: alpar@1: 2) being allocated the memory block contains arbitrary data, that is, alpar@1: it is {\it not} initialized by binary zeros; alpar@1: alpar@1: 3) if the block cannot be allocated due to insufficient memory, the alpar@1: routine prints an error message and abnormally terminates the program. alpar@1: alpar@1: This routine is a replacement of the standard C function \verb|calloc| alpar@1: (with exception that the block is not cleaned) and used by all GLPK alpar@1: routines for dynamic memory allocation. The application program may use alpar@1: \verb|glp_calloc| for the same purpose. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_calloc| returns a pointer to the memory block alpar@1: allocated. To free this block the routine \verb|glp_free| (not the alpar@1: standard C function \verb|free|!) must be used. alpar@1: alpar@1: \subsection{glp\_free---free memory block} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_free(void *ptr); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_free| frees (deallocates) a memory block pointed alpar@1: to by \verb|ptr|, which was previously allocated by the routine alpar@1: \verb|glp_malloc| or \verb|glp_calloc|. Note that the pointer \verb|ptr| alpar@1: must valid and must not be \verb|NULL|. alpar@1: alpar@1: This routine is a replacement of the standard C function \verb|free| alpar@1: and used by all GLPK routines for dynamic memory allocation. The alpar@1: application program may use \verb|glp_free| for the same purpose. alpar@1: alpar@1: \subsection{glp\_mem\_usage---get memory usage information} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_mem_usage(int *count, int *cpeak, glp_long *total, alpar@1: glp_long *tpeak); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_mem_usage| reports some information about alpar@1: utilization of the memory by the routines \verb|glp_malloc|, alpar@1: \verb|glp_calloc|, and \verb|glp_free|. Information is stored to alpar@1: locations specified by corresponding parameters (see below). Any alpar@1: parameter can be specified as \verb|NULL|, in which case corresponding alpar@1: information is not stored. alpar@1: alpar@1: \verb|*count| is the number of currently allocated memory blocks. alpar@1: alpar@1: \verb|*cpeak| is the peak value of \verb|*count| reached since the alpar@1: initialization of the GLPK library environment. alpar@1: alpar@1: \verb|*total| is the total amount, in bytes, of currently allocated alpar@1: memory blocks. alpar@1: alpar@1: \verb|*tpeak| is the peak value of \verb|*total| reached since the alpar@1: initialization of the GLPK library envirionment. alpar@1: alpar@1: \subsubsection*{Example} alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: glp_mem_usage(&count, NULL, NULL, NULL); alpar@1: printf("%d memory block(s) are still allocated\n", count); alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: \subsection{glp\_mem\_limit---set memory usage limit} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_mem_limit(int limit); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_mem_limit| limits the amount of memory available alpar@1: for dynamic allocation (with the routines \verb|glp_malloc| and alpar@1: \verb|glp_calloc|) to \verb|limit| megabytes. alpar@1: alpar@1: \subsection{glp\_time---determine current universal time} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: glp_long glp_time(void); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_time| returns the current universal time (UTC), alpar@1: in milliseconds, elapsed since 00:00:00 GMT January 1, 1970. alpar@1: alpar@1: \subsection{glp\_difftime---compute difference between two time values} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: double glp_difftime(glp_long t1, glp_long t0); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_difftime| returns the difference between two time alpar@1: values \verb|t1| and \verb|t0|, expressed in seconds. alpar@1: alpar@1: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% alpar@1: alpar@1: \newpage alpar@1: alpar@1: \section{Plain data file reading routines} alpar@1: alpar@1: \subsection{Introduction} alpar@1: alpar@1: On developing simple applications to solve optimization problems it is alpar@1: often needed to read data from plain text files. To do this the standard alpar@1: C function \verb|fscanf| may be used, however, it is not convenient; for alpar@1: example, if it scans an integer number according to the format alpar@1: specification `\verb|%d|', and that number is coded incorrectly, alpar@1: no diagnostics is provided. alpar@1: alpar@1: This section describes a set of GLPK API routines, which may be used in alpar@1: application programs to simplify reading data from plain text files. alpar@1: alpar@1: \subsubsection*{Example 1} alpar@1: alpar@1: The following main program reads ten integer numbers from plain text alpar@1: file \verb|data.txt| and prints their sum. alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: /* sdfsamp1.c */ alpar@1: alpar@1: #include alpar@1: #include alpar@1: #include alpar@1: alpar@1: int main(void) alpar@1: { glp_data *data; alpar@1: int j, num, sum; alpar@1: /* open plain data file */ alpar@1: data = glp_sdf_open_file("data.txt"); alpar@1: if (data == NULL) exit(EXIT_FAILURE); alpar@1: sum = 0; alpar@1: for (j = 1; j <= 10; j++) alpar@1: { /* read next integer number */ alpar@1: num = glp_sdf_read_int(data); alpar@1: sum += num; alpar@1: } alpar@1: printf("sum = %d\n", sum); alpar@1: /* close plain data file */ alpar@1: glp_sdf_close_file(data); alpar@1: return 0; alpar@1: } alpar@1: alpar@1: /* eof */ alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: The input data are coded in free format. For example, the file alpar@1: \verb|data.txt| may look like this: alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: 123 65 432 890 -12 743 895 -7 111 326 alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: \noindent alpar@1: or like this: alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: 123 65 432 890 -12 alpar@1: 743 895 -7 111 326 alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: \noindent alpar@1: If the input data file contains incorrect data, the routine alpar@1: \verb|glp_sdf_read_int| prints an error message and, if no error alpar@1: handling is provided by the application program, abnormally terminates alpar@1: program execution. For example, the file \verb|data.txt| could contain alpar@1: the following data: alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: 123 65 432 890 -12 alpar@1: 743 895 =7 111 326 alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: \noindent alpar@1: in which case the error message would be the following: alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: data.txt:2: cannot convert `=7' to integer alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: \subsubsection*{Example 2} alpar@1: alpar@1: As it was said above, by default any attempt to read incorrect data alpar@1: leads to abnormal termination. However, sometimes it is desirable to alpar@1: catch such errors. This feature is illustrated by the following main alpar@1: program, which does the same job as in the previous example. alpar@1: alpar@1: \begin{footnotesize} alpar@1: \begin{verbatim} alpar@1: /* sdfsamp2.c */ alpar@1: alpar@1: #include alpar@1: #include alpar@1: #include alpar@1: #include alpar@1: alpar@1: int main(void) alpar@1: { glp_data *data; alpar@1: jmp_buf jump; alpar@1: int j, num, sum, ret; alpar@1: /* open plain data file */ alpar@1: data = glp_sdf_open_file("data.txt"); alpar@1: if (data == NULL) alpar@1: { ret = EXIT_FAILURE; alpar@1: goto done; alpar@1: } alpar@1: /* set up error handling */ alpar@1: if (setjmp(jump)) alpar@1: { ret = EXIT_FAILURE; alpar@1: goto done; alpar@1: } alpar@1: glp_sdf_set_jump(data, jump); alpar@1: /* read and process data */ alpar@1: sum = 0; alpar@1: for (j = 1; j <= 10; j++) alpar@1: { /* read next integer number */ alpar@1: num = glp_sdf_read_int(data); alpar@1: if (abs(num) > 1000) alpar@1: glp_sdf_error(data, "integer %d too big\n", num); alpar@1: if (num < 0) alpar@1: glp_sdf_warning(data, "integer %d is negative\n", num); alpar@1: sum += num; alpar@1: } alpar@1: printf("sum = %d\n", sum); alpar@1: ret = EXIT_SUCCESS; alpar@1: done: /* close plain data file */ alpar@1: if (data != NULL) glp_sdf_close_file(data); alpar@1: return ret; alpar@1: } alpar@1: alpar@1: /* eof */ alpar@1: \end{verbatim} alpar@1: \end{footnotesize} alpar@1: alpar@1: \subsection{glp\_sdf\_open\_file---open plain data file} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: glp_data *glp_sdf_open_file(const char *fname); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_open_file| opens a plain data file, whose alpar@1: name is specified by the character string \verb|fname|. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: If the operation was successful, the routine \verb|glp_sdf_open_file| alpar@1: returns a pointer to the opaque program object of the type alpar@1: \verb|glp_data|\footnote{This data structure is declared in the header alpar@1: file {\tt glpk.h}.} associated with the plain data file. Otherwise, if alpar@1: the operation failed, the routine prints an error message and returns alpar@1: \verb|NULL|. alpar@1: alpar@1: \subsubsection*{Note} alpar@1: alpar@1: The application program should use the pointer returned by the routine alpar@1: \verb|glp_sdf_open_file| to perform all subsequent operations on the alpar@1: data file. alpar@1: alpar@1: \newpage alpar@1: alpar@1: \subsection{glp\_sdf\_set\_jump---set up error handling} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_sdf_set_jump(glp_data *data, jmp_buf jump); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_set_jump| sets up error handling for the alpar@1: plain data file specified by the parameter \verb|data|. alpar@1: alpar@1: The parameter \verb|jump| specifies the environment buffer, which must alpar@1: be initialized with the standard C function \verb|setjmp| prior to call alpar@1: to the routine \verb|glp_sdf_set_jump|. Detecting any incorrect data in alpar@1: the corresponding plain data file will cause non-local ``go to'' by alpar@1: a call to the standard C function \verb|longjmp|. alpar@1: alpar@1: The parameter \verb|jump| can be specified as \verb|NULL|, in which alpar@1: case the routine \verb|glp_sdf_set_jump| restores the default behavior, alpar@1: in which case detecting incorrect data leads to abnormal termination. alpar@1: alpar@1: \subsection{glp\_sdf\_error---print error message} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_sdf_error(glp_data *data, const char *fmt, ...); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_error| prints an error message related to the alpar@1: plain data file specified by the parameter \verb|data|. If error handing alpar@1: was not previously provided, the routine then abnormally terminates alpar@1: execution of the application program. Otherwise, it signals about the alpar@1: error by a call to the standard C function \verb|longjmp|. alpar@1: alpar@1: The character string \verb|fmt| and optional parameters following it alpar@1: have the same meaning as for the standard C function \verb|printf|. alpar@1: alpar@1: The message produced by the routine \verb|glp_sdf_error| looks like alpar@1: follows: alpar@1: alpar@1: \medskip alpar@1: alpar@1: {\it file}{\tt :}{\it line}{\tt :} {\it message text} alpar@1: alpar@1: \medskip alpar@1: alpar@1: \noindent alpar@1: where {\it file} is the filename passed to the routine alpar@1: \verb|glp_sdf_open| and {\it line} is the current line number. alpar@1: alpar@1: \newpage alpar@1: alpar@1: \subsection{glp\_sdf\_warning---print warning message} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_sdf_warning(glp_data *data, const char *fmt, ...); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_warning| prints a warning message related to alpar@1: the plain data file specified by the parameter \verb|data|. alpar@1: alpar@1: The character string \verb|fmt| and optional parameters following it alpar@1: have the same meaning as for the standard C function \verb|printf|. alpar@1: alpar@1: The message produced by the routine \verb|glp_sdf_warning| looks like alpar@1: follows: alpar@1: alpar@1: \medskip alpar@1: alpar@1: {\it file}{\tt :}{\it line}\verb|: warning:| {\it message text} alpar@1: alpar@1: \medskip alpar@1: alpar@1: \noindent alpar@1: where {\it file} is the filename passed to the routine alpar@1: \verb|glp_sdf_open| and {\it line} is the current line number. alpar@1: alpar@1: \subsection{glp\_sdf\_read\_int---read integer number} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: int glp_sdf_read_int(glp_data *data); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_read_int| skips optional white-space alpar@1: characters and then reads an integer number from the plain data file alpar@1: specified by the parameter \verb|data|. If the operation failed, the alpar@1: routine \verb|glp_sdf_read_int| calls the routine \verb|glp_sdf_error| alpar@1: (see above). alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_sdf_read_int| returns the integer number read. alpar@1: alpar@1: \newpage alpar@1: alpar@1: \subsection{glp\_sdf\_read\_num---read floating-point number} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: double glp_sdf_read_num(glp_data *data); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_read_num| skips optional white-space alpar@1: characters and then reads a floating-point number from the plain data alpar@1: file specified by the parameter \verb|data|. If the operation failed, alpar@1: the routine \verb|glp_sdf_num| calls the routine \verb|glp_sdf_error| alpar@1: (see above). alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_sdf_read_num| returns the floating-point number alpar@1: read. alpar@1: alpar@1: \subsection{glp\_sdf\_read\_item---read data item} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: const char *glp_sdf_read_item(glp_data *data); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_read_item| skips optional white-space alpar@1: characters and then reads a data item from the plain data file specified alpar@1: by the parameter \verb|data|. If the operation failed, the routine alpar@1: \verb|glp_sdf_read_item| calls the routine \verb|glp_sdf_error| (see alpar@1: above). alpar@1: alpar@1: {\it Data item} is a sequence of 1 to 255 arbitrary graphic characters alpar@1: delimited by white-space characters. Data items may be used to represent alpar@1: symbolic names, identifiers, etc. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_sdf_read_item| returns a pointer to the internal alpar@1: buffer, which contains the data item read in the form of a alpar@1: null-terminated character string. alpar@1: alpar@1: \newpage alpar@1: alpar@1: \subsection{glp\_sdf\_read\_text---read text until end of line} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: const char *glp_sdf_read_text(glp_data *data); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_read_text| reads a text from the plain data alpar@1: file specified by the parameter \verb|data|. alpar@1: alpar@1: Reading starts from the current position and extends until end of the alpar@1: current line. Initial and trailing white-space characters as well as alpar@1: the newline character are not included in the text. alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_sdf_read_text| returns a pointer to the internal alpar@1: buffer, which contains the text read in the form of a null-terminated alpar@1: character string. alpar@1: alpar@1: \subsection{glp\_sdf\_line---determine current line number} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: int glp_sdf_line(glp_data *data); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Returns} alpar@1: alpar@1: The routine \verb|glp_sdf_line| returns the current line number for the alpar@1: plain data file specified by the parameter \verb|data|. alpar@1: alpar@1: \subsection{glp\_sdf\_close\_file---close plain data file} alpar@1: alpar@1: \subsubsection*{Synopsis} alpar@1: alpar@1: \begin{verbatim} alpar@1: void glp_sdf_close_file(glp_data *data); alpar@1: \end{verbatim} alpar@1: alpar@1: \subsubsection*{Description} alpar@1: alpar@1: The routine \verb|glp_sdf_close_file| closes the plain data file alpar@1: specified by the parameter \verb|data| and frees all the resources alpar@1: allocated to this program object. alpar@1: alpar@1: %* eof *%