#!/usr/bin/env rdmd /* Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ import std.stdio; import std.getopt; import std.algorithm; import std.regex; import std.uri; import std.process; int main(string[] args) { char dman = 'd'; if (find(args[0], "cman").length) dman = 'c'; if (args.length < 2) { writefln("%sman: Look up %s topics in the manual Usage: %sman [--man] topic ", dman, dman == 'c' ? 'C' : 'D', dman); return 1; } bool man; getopt(args, "man", { man = true; }); if (man) { browse("http://www.digitalmars.com/ctg/dman.html"); return 0; } else if (args.length < 2) { writefln("%sman: no topic", dman); return 1; } auto topic = args[1]; foreach (a; args[2..$]) topic ~= " " ~ a; auto url = topic2url(dman, topic); if (url) { browse(url); } else { writefln("%sman: topic '%s' not found", dman, topic); return 1; } return 0; } string topic2url(char dman, string topic) { /* Instead of hardwiring these, dman should read from a .json database pointed to * by sc.ini or dmd.conf. */ string url; if (dman == 'c') { url = DmcCommands(topic); if (!url) url = CHeader(topic); if (!url) url = Clib(topic); if (!url) url = Misc(topic); if (!url) // Try "I'm Feeling Lucky" url = "http://www.google.com/search?q=" ~ "site:digitalmars.com " ~ std.uri.encode(topic) ~ "&btnI=I%27m+Feeling+Lucky"; } else { url = DmcCommands(topic); if (!url) url = Misc(topic); if (!url) url = D(topic); if (!url) url = CHeader(topic); if (!url) url = Clib(topic); if (!url) // Try "I'm Feeling Lucky" url = "http://www.google.com/search?q=" ~ std.uri.encode(topic) ~ "&as_oq=site:dlang.org+site:digitalmars.com&btnI=I%27m+Feeling+Lucky"; } return url; } string DmcCommands(string topic) { static string[] dmccmds = [ "bcc", "chmod", "cl", "coff2omf", "coffimplib", "dmc", "diff", "diffdir", "dman", "dump", "dumpobj", "dumpexe", "exe2bin", "flpyimg", "grep", "hc", "htod", "implib", "lib", "libunres", "link", "linker", "make", "makedep", "me", "obj2asm", "optlink", "patchobj", "rc", "rcc", "sc", "shell", "smake", "touch", "unmangle", "whereis", ]; if (find(dmccmds, topic).length) { if (topic == "dmc") topic = "sc"; else if (topic == "link") topic = "optlink"; else if (topic == "linker") topic = "optlink"; return "http://www.digitalmars.com/ctg/" ~ topic ~ ".html"; } return null; } string D(string topic) { static immutable tagJson = import("d-tags.json"); import std.json; JSONValue tags = parseJSON(tagJson); if (topic in tags && tags[topic].array.length) return tags[topic][0].str; return null; } string CHeader(string topic) { static string[] dmccmds = [ "assert.h", "complex.h", "ctype.h", "fenv.h", "float.h", "locale.h", "math.h", "setjmp.h", "signal.h", "stdarg.h", "stddef.h", "stdio.h", "stdlib.h", "string.h", "time.h", "gc.h", "bios.h", "cerror.h", "disp.h", "dos.h", "emm.h", "handle.h", "int.h", "msmouse.h", "sound.h", "swap.h", "tsr.h", "winio.h", "bitops.h", "conio.h", "controlc.h", "direct.h", "fltpnt.h", "io.h", "page.h", "process.h", "search.h", "sys/stat.h", "tabsize.h", "trace.h", "utime.h", "unmangle.h", "util.h", "regexp.h", "complex.h", "iostream.h", ]; if (find(dmccmds, topic).length) { return "http://www.digitalmars.com/rtl/" ~ topic ~ "tml"; } return null; } string Clib(string topic) { static string rtl = "http://www.digitalmars.com/rtl/"; /******************** assert.h ***************************/ if (topic == "assert") return rtl ~ "assert.html#assert"; /**************** bios.h *******************************/ static string[] biosfuncs = [ "biosdisk", "_bios_keybrd", "biosprint", "biostime", "_bios_disk", "_bios_equiplist", "_bios_memsize", "_bios_printer", "_bios_serialcom", "_bios_timeofday", "_int86", "_int86x", ]; switch (topic) { case "bioskey": topic = "_bios_keybrd"; break; case "biosequip": topic = "_bios_equiplist"; break; case "biosmemory": topic = "_bios_memsize"; break; case "bioscom": topic = "_bios_serialcom"; break; case "int86_real": case "int86": topic = "_int86"; break; case "int86x_real": case "int86x": topic = "_int86x"; break; default: break; } if (find(biosfuncs, topic).length) return rtl ~ "bios.html#" ~ topic; /**************** bitops.h *******************************/ if (topic == "_inline_bsf" || topic == "_inline_bsr") return rtl ~ "bitops.html#" ~ topic; /**************** cerror.h *******************************/ if (topic == "cerror_close" || topic == "cerror_open") return rtl ~ "cerror.html#" ~ topic; /******************** complex.h ***************************/ /******************** conio.h ***************************/ static string[] coniofuncs = [ "_kbhit", "_ungetch", "_getch", "_getche", "_putch", "_cgets", "_cprintf","_cputs", "_cscanf", ]; if (find(coniofuncs, topic).length) return rtl ~ "conio.html#" ~ topic; /**************** controlc.h *******************************/ if (topic == "controlc_close" || topic == "controlc_open") return rtl ~ "controlc.html#" ~ topic; /**************** ctype.h *******************************/ static string[] isxxxxfuncs = [ "isalnum", "isalpha", "__isascii", "iscntrl", "__iscsym", "__iscsymf", "isdigit", "isgraph", "islower", "isprint", "ispunct", "isspace", "isupper", "isxdigit", ]; if (find(isxxxxfuncs, topic).length) return rtl ~ "ctype.html#isxxxx"; static string[] toxxxxfuncs = [ "_tolower", "tolower", "_toupper", "toupper", ]; if (find(toxxxxfuncs, topic).length) return rtl ~ "ctype.html#_toxxxx"; if (topic == "__toascii") return rtl ~ "ctype.html#__toascii"; /******************** direct.h ***************************/ static string[] directfuncs = [ "_chdir", "_chdrive", "_getcwd", "_getdrive", "_mkdir", "_rmdir", "fnmerge", "fnsplit", "searchpath", ]; if (find(directfuncs, topic).length) return rtl ~ "direct.html#" ~ topic; /******************** disp.h ***************************/ static string[] dispfuncs = [ "disp_box", "disp_close", "disp_eeol", "disp_eeop", "disp_endstand", "disp_fillbox", "disp_flush", "disp_getattr", "disp_getmode", "disp_hidecursor", "disp_move", "disp_open", "disp_peekbox", "disp_peekw", "disp_pokebox", "disp_pokew", "disp_printf", "disp_putc", "disp_puts", "disp_reset43", "disp_scroll", "disp_set43", "disp_setattr", "disp_setcursortype", "disp_setmode", "disp_showcursor", "disp_startstand", "disp_usebios", ]; if (find(dispfuncs, topic).length) return rtl ~ "disp.html#" ~ topic; /******************** dos.h ***************************/ static string[] dosfuncs = [ "absread", "abswrite", "dos_abs_disk_read", "dos_abs_disk_write", "dos_alloc", "_dos_allocmem", "dos_calloc", "_dos_close", "_dos_commit", "dos_creat", "_dos_creat", "_dos_creatnew", "_doserrno", "_dosexterr", "_dos_findfirst", "_dos_findnext", "dos_free", "_dos_freemem", "dos_get_ctrl_break", "dos_get_verify", "_dos_getdate", "_dos_getdiskfree", "dos_getdiskfreespace", "_dos_getdrive", "_dos_getfileattr", "_dos_getftime", "_dos_gettime", "_dos_getvect", "_dos_keep", "_dos_lock", "_dos_open", "dos_open", "_dos_read", "_dos_seek", "_dos_setblock", "dos_setblock", "dos_set_ctrl_break", "_dos_setdate", "_dos_setdrive", "_dos_setfileattr", "_dos_setftime", "_dos_settime", "_dos_setvect", "dos_set_verify", "_dos_write", "_x386_coreleft", "_x386_free_protected_ptr", "_x386_get_abs_address", "_x386_map_physical_address", "_x386_memlock", "_x386_memunlock", "_x386_mk_protected_ptr", ]; switch (topic) { case "_getdiskfree": topic = "_dos_getdiskfree"; break; default: break; } if (find(dosfuncs, topic).length) return rtl ~ "dos.html#" ~ topic; /******************** dos2.h ***************************/ static string[] dos2funcs = [ "_bdos", "_chain_intr", "_disable", "_enable", "_FP", "_getdcwd", "_hard", "_inp", "_intdos", "_intdosx", "_MK_FP", "_osversion", "_outp", "_segread", "allocmem", "bdosptr", "bdosx", "farcalloc", "farcoreleft", "farfree", "farmalloc", "farrealloc", "findfirst", "findnext", "freemem", "geninterrupt", "getcbrk", "getcurdir", "getdate", "getdisk", "getdta", "getfat", "getfatd", "getpsp", "gettime", "getverify", "parsfnm", "peek", "peekb", "poke", "pokeb", "response_expand", "setblock", "setcbrk", "setdisk", "setdta", "setverify", ]; switch (topic) { case "_hardresume": case "_hardretn": topic = "_harderr"; break; case "_inpw": case "_inpl": topic = "_inp"; break; case "_outpw": case "_outpl": topic = "_outp"; break; default: break; } if (find(dos2funcs, topic).length) return rtl ~ "dos2.html#" ~ topic; /******************** emm.h ***************************/ static string[] emmfuncs = [ "emm_allocpages", "emm_deallocpages", "emm_gethandlecount", "emm_gethandlespages", "emm_getpagemap", "emm_getpagemapsize", "emm_getsetpagemap", "emm_gettotal", "emm_getunalloc", "emm_getversion", "emm_init", "emm_maphandle", "emm_physpage", "emm_restorepagemap", "emm_savepagemap", "emm_setpagemap", "emm_term", ]; if (find(emmfuncs, topic).length) return rtl ~ "emm.html#" ~ topic; /******************** fenv.h ***************************/ static string[] fenvfuncs = [ "roundingmodes", "precisionmodes", "feclearexcept", "fegetexceptflag", "feraiseexcept", "fesetexceptflag", "fetestexcept", "fegetprec", "fesetprec", "fegetround", "fesetround", "fegetenv", "feholdexcept", "fesetenv", "feupdateenv", ]; if (find(fenvfuncs, topic).length) return rtl ~ "fenv.html#" ~ topic; /******************** float.h ***************************/ static string[] floatfuncs = [ "_8087", "_clear87", "_control87", "_fpreset", "_status87", ]; if (find(floatfuncs, topic).length) return rtl ~ "float.html#" ~ topic; /******************** fltpnt.h ***************************/ static string[] fltpntfuncs = [ "copysign", "nearbyint", "nextafter", "remainder", "remquo", "rint", "rndtol", "round", "scalb", "trunc", ]; if (find(fltpntfuncs, topic).length) return rtl ~ "fltpnt.html#" ~ topic; /******************** handle.h ***************************/ static string[] handlefuncs = [ "handle_calloc", "handle_free", "handle_ishandle", "handle_malloc", "handle_realloc", "handle_strdup", ]; if (find(handlefuncs, topic).length) return rtl ~ "handle.html#" ~ topic; /******************** int.h ***************************/ static string[] intfuncs = [ "int_gen", "int_getvector", "int_intercept", "int_on", "int_on", "int_prev", "int_restore", "int_setvector", ]; if (find(intfuncs, topic).length) return rtl ~ "int.html#" ~ topic; /******************** io.h ***************************/ static string[] iofuncs = [ "_access", "_chmod", "_chsize", "_close", "_commit", "_creat", "_dup", "_dup2", "_eof", "_filelength", "_isatty", "_locking", "_lseek", "_mktemp", "_open", "_read", "_setmode", "_sopen", "_tell", "_write", "_umask", "_unlink", "filesize", "getDS", "getftime", "lock", "remove", "rename", "setftime", "unlock", ]; if (find(iofuncs, topic).length) return rtl ~ "io.html#" ~ topic; /******************** iostream ***************************/ if (topic == "iostream") return rtl ~ "iostream.html"; /******************** locale.h ***************************/ if (topic == "localeconv" || topic == "setlocale") return rtl ~ "locale.html#" ~ topic; /******************** math.h ***************************/ static string[] mathfuncs = [ "fpclassify", "isfinite", "signbit", "acos", "asin", "atan", "atan2", "ceil", "cos", "cosh", "cbrt", "exp", "exp2", "expm1", "fabs", "floor", "fmod", "frexp", "hypot", "ilogb", "ldexp", "log", "log2", "logb", "log10", "log1p", "matherr", "modf", "nextafter", "poly", "pow", "sin", "sinh", "sqrt", "tan", "tanh", "_cabs", ]; switch (topic) { case "isinf": case "isnan": case "isnormal": topic = "isinfinite"; break; case "log1pf": topic = "log1p"; break; case "_matherrl": topic = "matherr"; break; default: break; } if (find(mathfuncs, topic).length) return rtl ~ "math.html#" ~ topic; /******************** msmouse.h ***************************/ static string[] msmousefuncs = [ "msm_condoff", "msm_getpress", "msm_getrelease", "msm_getstatus", "msm_hidecursor", "msm_init", "msm_lightpen", "msm_lightpen", "msm_readcounters", "msm_setarea", "msm_setarea", "msm_setcurpos", "msm_setgraphcur", "msm_setratio", "msm_settextcur", "msm_setthreshhold", "msm_showcursor", "msm_signal", "msm_term", ]; if (find(msmousefuncs, topic).length) return rtl ~ "msmouse.html#" ~ topic; /******************** new ***************************/ if (topic == "_set_new_handler") return rtl ~ "new.html#_set_new_handler"; /******************** oldcomplex.h ***************************/ /******************** page.h ***************************/ static string[] pagefuncs = [ "page_calloc", "page_free", "page_initialize", "page_malloc", "page_maxfree", "page_realloc", "page_size", "page_toptr", ]; if (find(pagefuncs, topic).length) return rtl ~ "page.html#" ~ topic; /******************** process.h ***************************/ static string[] processfuncs = [ "_beginthread", "_c_exit", "_exec", "_endthread", "_getpid", "_spawn", ]; switch (topic) { case "_cexit": topic = "_c_exit"; break; case "_execl": case "_execle": case "_execlp": case "_execlpe": case "_execv": case "_execve": case "_execvp": case "_execvpe": topic = "_exec"; break; case "_spawnl": case "_spawnle": case "_spawnlp": case "_spawnlpe": case "_spawnv": case "_spawnve": case "_spawnvp": case "_spawnvpe": topic = "_spawn"; break; default: break; } if (find(processfuncs, topic).length) return rtl ~ "process.html#" ~ topic; /******************** regexp.h ***************************/ /******************** search.h ***************************/ if (topic == "_lfind" || topic == "_lsearch") return rtl ~ "search.html#" ~ topic; /******************** setjmp.h ***************************/ if (topic == "setjmp" || topic == "longjmp") return rtl ~ "setjmp.html#" ~ topic; /******************** signal.h ***************************/ if (topic == "raise" || topic == "signal") return rtl ~ "signal.html#" ~ topic; /******************** sound.h ***************************/ if (topic == "sound_beep" || topic == "sound_click" || topic == "sound_tone") return rtl ~ "sound.html#" ~ topic; /******************** stdarg.h ***************************/ if (topic == "va_arg" || topic == "va_end" || topic == "va_start") return rtl ~ "stdarg.html#va_arg"; /******************** stddef.h ***************************/ if (topic == "__threadid") return rtl ~ "stddef.html#_threadid"; /******************** stdio.h ***************************/ static string[] stdiofuncs = [ "_fcloseall", "_fdopen", "_fgetchar", "_fileno", "_flushall", "_fputchar", "_fsopen", "_getw", "_okbigbuf", "_putw", "_rmtmp", "_stdaux", "_stdprn", "_tempnam", "clearerr", "fclose", "feof", "ferror", "fflush", "fgetc", "fgetpos", "fgets", "fopen", "printf", "fputc", "fputs", "fread", "freopen", "scanf", "fseek", "fsetpos", "ftell", "fwrite", "getc", "getchar", "gets", "putc", "putchar", "puts", "rewind", "setbuf", "setvbuf", "stderr", "stdin", "stdout", "tmpfile", "tmpnam", "ungetc", "vprintf", ]; switch (topic) { case "fprintf": case "sprintf": case "_snprintf": topic = "printf"; break; case "fscanf": case "sscanf": topic = "scanf"; break; default: break; } if (find(stdiofuncs, topic).length) return rtl ~ "stdio.html#" ~ topic; /******************* stdlib.h ****************************/ static string[] stdlibfuncs = [ "__max", "__min", "_alloca", "_atold", "_chkstack", "_cpumode", "_ecvt", "_environ", "_exit", "_fcvt", "_fileinfo", "_fmode", "_onexit", "_freect", "_fullpath", "_gcvt", "_halloc", "_hfree", "_itoa", "_lrotl", "_ltoa", "_makepath", "_memavl", "_memmax", "_msize", "_osmajor", "_osminor", "_osmode", "_osver", "_pgmptr", "_psp", "_putenv", "_rotl", "_searchenv", "_splitpath", "_stackavail", "_ultoa", "_winmajor", "_winminor", "_winver", "exit", "exit_pushstate", "abort", "abs", "atexit", "atof", "atoi", "atol", "bsearch", "calloc", "coreleft", "errno", "expand", "free", "getenv", "ldiv", "malloc", "mblen", "mbstowcs", "mbtowc", "_memmax", "perror", "qsort", "rand", "random", "randomize", "realloc", "srand", "strtof", "strtol", "strtold", "system", "_tolower", "wcstombs", "wctomb", ]; switch (topic) { case "_fmbstowcs": case "_fmbtowc": case "_fonexit": case "_fwcstombs": case "_fwctomb": case "_fatexit": case "_fmblen": case "_fcalloc": case "_ncalloc": case "_fmalloc": case "_nmalloc": case "_frealloc": case "_nrealloc": case "_fmsize": case "_nmsize": topic = topic[2..$]; break; case "_lrotr": topic = "_lrotl"; break; case "_rotr": topic = "_rotl"; break; case "div": topic = "ldiv"; break; case "exit_popstate": topic = "exit_pushstate"; break; case "strtod": topic = "strtof"; break; case "strtoul": topic = "strtol"; break; default: break; } if (find(stdlibfuncs, topic).length) return rtl ~ "stdlib.html#" ~ topic; /******************* string.h ****************************/ static string[] stringfuncs = [ "memchr", "memcmp", "_memccpy", "memcpy", "_memicmp", "memmove", "memset", "_movedata", "movmem", "_strdup", "_stricmp", "_strlwr", "strncmpi", "_strnset", "_strrev", "_strset", "_strtime", "_strupr", "_swab", "stpcpy", "strcat", "strchr", "strcmp", "strcoll", "strcpy", "strcspn", "strerror", "strlen", "strncat", "strncmp", "strncmpi", "strncpy", "strpbrk", "strrchr", "strspn", "strstr", "strtok", "strxfrm", "_sys_errlist", "_sys_nerr", ]; switch (topic) { case "_fmemccpy": topic = "_memccpy"; break; case "_fmemicmp": topic = "_memicmp"; break; case "_fmemmove": topic = "_memmove"; break; case "setmem": case "_fmemset": topic = "memset"; break; case "_fstrdup": topic = "_strdup"; break; case "_fstricmp": topic = "_stricmp"; break; case "_fstrlwr": topic = "_strlwr"; break; case "_strnicmp": case "_fstrnicmp": case "strncmpl": topic = "strncmpi"; break; case "_fstrnset": topic = "_strnset"; break; case "_fstrrev": topic = "_strrev"; break; case "_fstrset": topic = "_strset"; break; case "_fstrupr": topic = "_strupr"; break; case "_fmemchr": case "_fmemcmp": case "_fmemcpy": case "_fstrcat": case "_fstrchr": case "_fstrcpy": case "_fstrcspn": case "_fstrlen": case "_fstrncat": case "_fstrncmp": case "_fstrncpy": case "_fstrpbrk": case "_fstrrchr": case "_fstrspn": case "_fstrstr": case "_fstrtok": topic = topic[2..$]; break; default: break; } if (find(stringfuncs, topic).length) return rtl ~ "string.html#" ~ topic; /******************** swap.h ***************************/ static string[] swapfuncs = [ "swap_clearkeyboard", "swap_freeparagraphs", "swap_freeparagraph", "swap_is", "swap_onoff", "swap_pipe", "swap_pipeonoff", "swap_tempcheck", "swap_trapcbreak", "swap_window", "swap_windowonoff", ]; switch (topic) { case "swap_clearkeyboardoff": case "swap_clearkeyboardon": topic = "swap_clearkeyboard"; break; case "swap_freeparagraphson": case "swap_freeparagraphsoff": topic = "swap_freeparagraph"; break; case "swap_isclearkeyboardon": case "swap_isfreeparagraphson": case "swap_ison": case "swap_ispipeon": case "swap_istempcheckon": case "swap_istrapcbreakon": case "swap_iswindowon": topic = "swap_is"; break; case "swap_on": case "swap_off": topic = "swap_onoff"; break; case "swap_pipeon": case "swap_pipeoff": topic = "swap_pipeonoff"; break; case "swap_tempcheckon": case "swap_tempcheckoff": topic = "swap_tempcheck"; break; case "swap_trapcbreakon": case "swap_trapcbreakoff": topic = "swap_trapcbreak"; break; case "swap_windowon": case "swap_windowoff": topic = "swap_windowonoff"; break; default: break; } if (find(swapfuncs, topic).length) return rtl ~ "swap.html#" ~ topic; /******************** sys-stat.h ***************************/ if (topic == "_fstat" || topic == "_stat") return rtl ~ "sys-stat.html#" ~ topic; /******************** tabsize.h ***************************/ if (topic == "tab_sizeget" || topic == "tab_sizegetenv" || topic == "tab_sizeputenv" || topic == "tab_sizeset") return rtl ~ "tabsize.html#" ~ topic; /******************** time.h ***************************/ static string[] timefuncs = [ "_daylight", "difftime", "_ftime", "_strdate", "_timezone", "_tzname", "_tzset", "_utime", "asctime", "clock", "ctime", "gmtime", "localtime", "mktime", "msleep", "sleep", "strftime", "time", "usleep", ]; if (find(timefuncs, topic).length) return rtl ~ "time.html#" ~ topic; /******************** tsr.h ***************************/ if (topic == "tsr_install" || topic == "tsr_service" || topic == "tsr_uninstall") return rtl ~ "tsr.html#" ~ topic; /******************** unmangle.h ***************************/ if (topic == "unmangle_ident") return rtl ~ "unmangle.html#unmangle_ident"; /******************** util.h ***************************/ if (topic == "file_append" || topic == "file_read" || topic == "file_write") return rtl ~ "util.html#" ~ topic; /******************** winio.h ***************************/ static string[] winiofuncs = [ "ungets", "winio_about", "winio_bufsize", "winio_clear", "winio_close", "winio_closeall", "winio_current", "winio_defwindowsize", "winio_end", "winio_getinfo", "winio_hmenufile", "winio_hmenuhelp", "winio_hmenumain", "winio_home", "winio_init", "winio_onclose", "winio_onpaintentry", "winio_onpaintexit", "winio_openwindows", "winio_resetbusy", "winio_setbufsize", "winio_setbusy", "winio_setcurrent", "winio_setecho", "winio_setfont", "winio_setlinefn", "winio_setmenufunc", "winio_setpaint", "winio_settitle", "winio_warn", "winio_window", "wmhandler_create", "wmhandler_destroy", "wmhandler_get", "wmhandler_hwnd", "wmhandler_set", ]; if (find(winiofuncs, topic).length) return rtl ~ "winio.html#" ~ topic; /***********************************************/ return null; } string Misc(string topic) { string[string] misc = [ "D1": "http://www.digitalmars.com/d/1.0/", "D2": "http://dlang.org/", "faq": "http://dlang.org/faq.html", ]; auto purl = topic in misc; if (purl) return *purl; return null; }