/* * psprintf * * Format text data under the control of fmt (an sprintf-style format string) * and return it in an allocated-on-demand buffer. The buffer is allocated * with palloc in the backend, or malloc in frontend builds. Caller is * responsible to free the buffer when no longer needed, if appropriate. * * Errors are not returned to the caller, but are reported via elog(ERROR) * in the backend, or printf-to-stderr-and-exit() in frontend builds. * One should therefore think twice about using this in libpq. */ char * psprintf(const char *fmt,...) { size_t len = 128; /* initial assumption about buffer size */ for (;;) { char *result; va_list args; size_t newlen; /* * Allocate result buffer. Note that in frontend this maps to malloc * with exit-on-error. */ result = (char *) palloc(len); /* Try to format the data. */ va_start(args, fmt); newlen = pvsnprintf(result, len, fmt, args); va_end(args); if (newlen < len) return result; /* success */ /* Release buffer and loop around to try again with larger len. */ pfree(result); len = newlen; } }
// // I_FatalError // // haleyjd 05/21/10: Call this for super-evil errors such as heap corruption, // system-related problems, etc. // void I_FatalError(int code, const char *error, ...) { // Flag a fatal error, so that some shutdown code will not be executed; // chiefly, saving the configuration files, which can malfunction in // unpredictable ways when heap corruption is present. We do this even // if an error has already occurred, since, for example, if a Z_ChangeTag // error happens during M_SaveDefaults, we do not want to subsequently // run M_SaveSysConfig etc. in I_Quit. error_exitcode = I_ERRORLEVEL_FATAL; if(code == I_ERR_ABORT) { // kill with utmost contempt abort(); } else { if(!*errmsg) // ignore all but the first message -- killough { va_list argptr; va_start(argptr,error); pvsnprintf(errmsg, sizeof(errmsg), error, argptr); va_end(argptr); } if(!has_exited) // If it hasn't exited yet, exit now -- killough { has_exited = 1; // Prevent infinitely recursive exits -- killough exit(-1); } else abort(); // double fault, must abort } }
int psnprintf(char *str, size_t n, const char *format, ...) { va_list args; int ret; va_start(args, format); ret = pvsnprintf(str, n, format, args); va_end(args); return ret; }
// // MN_Alert // // alert message // -- just press enter // void MN_Alert(const char *message, ...) { va_list args; // haleyjd 02/24/02: bug fix for menuactive state popupMenuActive = menuactive; MN_ActivateMenu(); // hook in widget so message will be displayed MN_PushWidget(&popup_widget); popup_message_type = popup_alert; va_start(args, message); pvsnprintf(popup_message, sizeof(popup_message), message, args); va_end(args); }
// // I_ErrorVA // // haleyjd: varargs version of I_Error used chiefly by libConfuse. // void I_ErrorVA(const char *error, va_list args) { // do not demote error level if(error_exitcode < I_ERRORLEVEL_NORMAL) error_exitcode = I_ERRORLEVEL_NORMAL; if(!*errmsg) pvsnprintf(errmsg, sizeof(errmsg), error, args); if(!has_exited) { has_exited = 1; exit(-1); } else I_FatalError(I_ERR_ABORT, "I_ErrorVA: double faulted\n"); }
// // I_ExitWithMessage // // haleyjd 06/05/10: exit with a message which is not technically an error. The // code used to call I_Error for this, but it wasn't semantically correct. // void I_ExitWithMessage(const char *msg, ...) { // do not demote error level if(error_exitcode < I_ERRORLEVEL_MESSAGE) error_exitcode = I_ERRORLEVEL_MESSAGE; // just a message if(!*errmsg) // ignore all but the first message -- killough { va_list argptr; va_start(argptr, msg); pvsnprintf(errmsg, sizeof(errmsg), msg, argptr); va_end(argptr); } if(!has_exited) // If it hasn't exited yet, exit now -- killough { has_exited = 1; // Prevent infinitely recursive exits -- killough exit(0); } }
// // I_Error // // Normal error reporting / exit routine. // void I_Error(const char *error, ...) // killough 3/20/98: add const { // do not demote error level if(error_exitcode < I_ERRORLEVEL_NORMAL) error_exitcode = I_ERRORLEVEL_NORMAL; // a normal error if(!*errmsg) // ignore all but the first message -- killough { va_list argptr; va_start(argptr,error); pvsnprintf(errmsg, sizeof(errmsg), error, argptr); va_end(argptr); } if(!has_exited) // If it hasn't exited yet, exit now -- killough { has_exited = 1; // Prevent infinitely recursive exits -- killough exit(-1); } else I_FatalError(I_ERR_ABORT, "I_Error: double faulted\n"); }
/* * appendStringInfoVA * * Attempt to format text data under the control of fmt (an sprintf-style * format string) and append it to whatever is already in str. If successful * return zero; if not (because there's not enough space), return an estimate * of the space needed, without modifying str. Typically the caller should * pass the return value to enlargeStringInfo() before trying again; see * appendStringInfo for standard usage pattern. * * XXX This API is ugly, but there seems no alternative given the C spec's * restrictions on what can portably be done with va_list arguments: you have * to redo va_start before you can rescan the argument list, and we can't do * that from here. */ int appendStringInfoVA(StringInfo str, const char *fmt, va_list args) { int avail; size_t nprinted; Assert(str != NULL); /* * If there's hardly any space, don't bother trying, just fail to make the * caller enlarge the buffer first. We have to guess at how much to * enlarge, since we're skipping the formatting work. */ avail = str->maxlen - str->len; if (avail < 16) return 32; nprinted = pvsnprintf(str->data + str->len, (size_t) avail, fmt, args); if (nprinted < (size_t) avail) { /* Success. Note nprinted does not include trailing null. */ str->len += (int) nprinted; return 0; } /* Restore the trailing null so that str is unmodified. */ str->data[str->len] = '\0'; /* * Return pvsnprintf's estimate of the space needed. (Although this is * given as a size_t, we know it will fit in int because it's not more * than MaxAllocSize.) */ return (int) nprinted; }