@@ -54,6 +54,31 @@ static const char *tagstr = "@plpgsql_check_options:";
5454#define PRAGMA_TOKEN_NUMBER 130
5555#define PRAGMA_TOKEN_STRING 131
5656
57+ #ifdef _MSC_VER
58+
59+ static void *
60+ memmem (const void * haystack , size_t haystack_len ,
61+ const void * const needle , const size_t needle_len )
62+ {
63+ if (haystack == NULL ) return NULL ; // or assert(haystack != NULL);
64+ if (haystack_len == 0 ) return NULL ;
65+ if (needle == NULL ) return NULL ; // or assert(needle != NULL);
66+ if (needle_len == 0 ) return NULL ;
67+
68+ for (const char * h = haystack ;
69+ haystack_len >= needle_len ;
70+ ++ h , -- haystack_len )
71+ {
72+ if (!memcmp (h , needle , needle_len ))
73+ {
74+ return h ;
75+ }
76+ }
77+ return NULL ;
78+ }
79+
80+ #endif
81+
5782/*
5883 * Is character a valid identifier start?
5984 * Must match scan.l's {ident_start} character class.
@@ -1207,6 +1232,63 @@ get_table_comment_option(TokenizerState *tstate, const char *name, plpgsql_check
12071232 name , cinfo -> fn_oid );
12081233}
12091234
1235+ static bool
1236+ is_keyword (char * str , size_t bytes , const char * keyword )
1237+ {
1238+ if (bytes != strlen (keyword ))
1239+ return false;
1240+
1241+ if (strncasecmp (str , keyword , bytes ) != 0 )
1242+ return false;
1243+
1244+ return true;
1245+ }
1246+
1247+ char *
1248+ plpgsql_check_process_echo_string (char * str , plpgsql_check_info * cinfo )
1249+ {
1250+ StringInfoData sinfo ;
1251+
1252+ initStringInfo (& sinfo );
1253+
1254+ while (* str )
1255+ {
1256+ if (* str == '@' && str [1 ] == '@' )
1257+ {
1258+ char * start ;
1259+ size_t bytes ;
1260+
1261+ str += 2 ;
1262+ start = str ;
1263+
1264+ while (* str && isalpha (* str ))
1265+ {
1266+ str += 1 ;
1267+ }
1268+
1269+ bytes = str - start ;
1270+ if (is_keyword (start , bytes , "id" ))
1271+ {
1272+ appendStringInfo (& sinfo , "%u" , cinfo -> fn_oid );
1273+ }
1274+ else if (is_keyword (start , bytes , "name" ))
1275+ {
1276+ appendStringInfoString (& sinfo , get_func_name (cinfo -> fn_oid ));
1277+ }
1278+ else if (is_keyword (start , bytes , "signature" ))
1279+ {
1280+ appendStringInfoString (& sinfo , format_procedure (cinfo -> fn_oid ));
1281+ }
1282+ else
1283+ appendStringInfo (& sinfo , "@@%.*s" , (int ) bytes , start );
1284+ }
1285+ else
1286+ appendStringInfoChar (& sinfo , * str ++ );
1287+ }
1288+
1289+ return sinfo .data ;
1290+ }
1291+
12101292static void
12111293comment_options_parser (char * str , plpgsql_check_info * cinfo )
12121294{
@@ -1305,13 +1387,13 @@ comment_options_parser(char *str, plpgsql_check_info *cinfo)
13051387 }
13061388
13071389 if (_token -> value == PRAGMA_TOKEN_IDENTIF )
1308- elog (NOTICE , "comment option \"echo\" is %s" , make_string (_token ));
1390+ elog (NOTICE , "comment option \"echo\" is %s" , plpgsql_check_process_echo_string ( make_string (_token ), cinfo ));
13091391 else if (_token -> value == PRAGMA_TOKEN_QIDENTIF )
1310- elog (NOTICE , "comment option \"echo\" is \"%s\"" , make_string (_token ));
1392+ elog (NOTICE , "comment option \"echo\" is \"%s\"" , plpgsql_check_process_echo_string ( make_string (_token ), cinfo ));
13111393 else if (_token -> value == PRAGMA_TOKEN_NUMBER )
1312- elog (NOTICE , "comment option \"echo\" is %s" , make_string (_token ));
1394+ elog (NOTICE , "comment option \"echo\" is %s" , plpgsql_check_process_echo_string ( make_string (_token ), cinfo ));
13131395 else if (_token -> value == PRAGMA_TOKEN_STRING )
1314- elog (NOTICE , "comment option \"echo\" is '%s'" , make_string (_token ));
1396+ elog (NOTICE , "comment option \"echo\" is '%s'" , plpgsql_check_process_echo_string ( make_string (_token ), cinfo ));
13151397 else
13161398 elog (NOTICE , "comment option \"echo\" is '%c'" , _token -> value );
13171399 }
@@ -1330,30 +1412,6 @@ comment_options_parser(char *str, plpgsql_check_info *cinfo)
13301412 while (_token );
13311413}
13321414
1333- #ifdef _MSC_VER
1334-
1335- static void *
1336- memmem (const void * haystack , size_t haystack_len ,
1337- const void * const needle , const size_t needle_len )
1338- {
1339- if (haystack == NULL ) return NULL ; // or assert(haystack != NULL);
1340- if (haystack_len == 0 ) return NULL ;
1341- if (needle == NULL ) return NULL ; // or assert(needle != NULL);
1342- if (needle_len == 0 ) return NULL ;
1343-
1344- for (const char * h = haystack ;
1345- haystack_len >= needle_len ;
1346- ++ h , -- haystack_len )
1347- {
1348- if (!memcmp (h , needle , needle_len ))
1349- {
1350- return h ;
1351- }
1352- }
1353- return NULL ;
1354- }
1355-
1356- #endif
13571415
13581416static void
13591417comment_options_parsecontent (char * str , size_t bytes , plpgsql_check_info * cinfo )
0 commit comments