青春时代是一个短暂的美梦,当你醒来时,它早已消失得无影无踪了。
 
昨日:篇  今日:篇   总帖:篇   会员:
今日:0
文章:44
今日:0
文章:20
今日:0
文章:42
今日:0
文章:45
今日:0
文章:1
今日:0
文章:7
今日:0    总帖:184
admin
670
原文地址:http://database.51cto.com/art/201708/548354.htm作者:古的白人生大起大落落落落落落,实在是太刺激了,下面这真是一个悲伤的故事。那年公司 ERP 系统刚进行升级。因为公司陆续上了 MES 和 PDM 系统。为了加快整个公司信息化平台的统一,请了个第三方公司来做中间接口。然后故事开始了。某一个晚上,第三方人员问我要 ERP 的 SA 密码。我很警惕:“你要干嘛?”“我测试一下中间表。”“有没有写表的操作?”“没有,只有读表的操作。”于是我放心的给了 SA 密码。给了 VPN 权限通道。放她进来了。十分钟后…..她带着哭腔打电话来(是的,对方做测试的是个 93 年的萌妹子。)“吴哥哥,服务器中毒了。。。。”我当时还在逛果壳呢,一听她说我服务器中毒了,我表示无比淡定。还以大哥的经验教训了一顿她。“叫你不要往我服务器传插件嘛,这次帮你解决一下,下次不准了哟。”我认为是小 case 呢,不就中毒了嘛,系统往回滚一天就好了。然后悲剧的事情就出现了,远程进不去,于是我就去机房本地登录,居然也进不去。我不死心,强制重启,居然还是进不去。我的服务器系统就这样崩了。。。好在那几天在做开发,系统没有启用,于是我和我的老板汇报了这个情况:“老大,我们服务器系统崩了。”“哦,那就搞好它让它别崩。” 果然是霸道总裁啊。当时数据和应用服务器我都是分开跑的,所以应用服务器奔溃了,我觉得也没多大事,就重新做系统吧。于是我重新做了个系统,然后喊萌妹子上来搭平台。“小刘啊,你可害惨我了,一个下午给你重做服务器系统了,我基础环境都配置好了,你上来搭平台吧。”萌妹子那是无比的歉意啊,又是答应请我吃饭又是答应请我看电影的。我都想系统再崩溃一次了。按理说这样应该是没问题了,就在我走出机房,在外面抽了根烟,45 度仰望了一下天空,联想了一下和萌妹子点个 9 分熟的牛排,在喝一口二锅头这样浪漫的晚餐的时候。电话来了。来电话的是萌妹子的老板。“小吴,我想找一下 information.db 和 mfmedia.db 这两个总表没找到,你给我找一下。”我都蒙了,从来没人问过我这样的问题,难道她老板不是 IT 行业的。“数据库文件都在目录树里啊,自己去找啊。”“没有。”于是我登上服务器一看,我傻了。所有的表都空了,所有的表都静静的躺在那,但是里面都空了。。。不可能啊,我数据库是放在另外一台服务器上的,怎么可能会没有了。于是我问萌妹子:“XXX,你到底做了什么操作啊,为毛我数据库都没了。”萌妹子说:“我啥也没干啊,只是按照步骤一路点 YES。”我才想起来,在第一次配置基础环境的时候,建账套会提示是否初始环境,如果点是了,数据库就会被初始化,然后这位萌妹子傻傻的点了是。“你知道不知道你干了什么,公司 06 年到现在所有的数据,财务的,供应链的,进销存的全部都在这台服务器里,200 多个 G 数据,因为你一个是,全没了。”萌妹子也吓蒙了,话都说不出来了。没办法,我再给我老板打电话。“老板,有个好消息,有个坏消息。”“直接说坏的。” 我就喜欢我们老板这么直接。“恩。。恩。。那个。。就是那个。ERP 的数据没了。”“哦,那就找回来。” 老板还是那么的霸气。我特么都要爱上他了。“老板,我想你没明白这个的严重性。ERP 数据没了,从 06 年开始的都没了,这意味着就算找回来,整理所有的表,排错也需要 3 天左右时间,到时候所有的生产都要暂时停止。如果找不回来,我们可能就要倒闭了。”我忽然有种掌握天下苍生的感觉。。。对面沉默了 5 秒后,爆吼了一句:“吴 XX,你给我滚到我办公室来!!”中间和老板手握手谈心,被老板亲切慰问的细节跳过不表。当时公司高层对数据安全还没有那么重视,之前预算做的项目,我已经做了备份的计划书,一直没被审批下来,现在估计悔得肠子都清了。于是我开始漫长的数据恢复之旅。我之前已经做了个本地备份的计划,每天晚上会备份一次。我把希望都放在了它身上。等我把备份的数据库附件上去,发现时间居然都是两个星期之前的。而且还有一些新表都没有,我联系对方,对方告知研发人员两个星期前做测试的时候把备份计划关了。。。我心里万头草泥马奔腾而过。最后没有办法,把老服务器又翻了出来,翻出之前的老数据,开始转换。期间老板给我短信:“数据恢复进行的怎么样了呢。”“报告,正在稳步进行中,按照目前的状况,可恢复的可能性超过 90%。” 别问我 90% 怎么算出来的,我就是哄他才这样说的。“唉,真是心急呀,睡都睡不着。小吴呀,当初要是听你的,上了备份该多好呀。” 现在知道后悔了,哼哼。“老大别担心,我会搞定的。” 是的,作为一位负责的员工,我就是这么让老大心安。“恩,那就交给你了哦,熬夜少抽点烟哦。” 哎呀,瞬间觉得我老大萌萌哒有没有。这里花了我一个晚上加一个白天。数据转换好了,还有一些时间差的数据没法找到。于是通知各个部门,找单据,开始往里面补单子,一条一条的按照业务流程补进去。为了协同更方便,在会议室加设了几十台电脑集体办公。。。在大家一片怨声载道中,三天时间,终于把数据恢复了过来。三天内我没离开机房超过 10 米,吃喝拉撒都在机房,不对,拉撒不在。这件事情造成的后果:1. 大部分员工放假三天,我加班三天三夜。2. 本来很爱我的大部分员工因为单据事件,集体转为黑我恨我了。3. 公司立马批了我的计划,冷备,热备,异地容灾,全部上全了。4.我挥刀自宫,自己罚了自己,扣除了自己一个月工资。5.老板到现在还是在怀疑请的那家公司已经被我们竞争对手收买,是故意来破坏我们的。6.萌妹子拉黑了我。
维护 16 0 267天前
admin
184
原文转自:http://bbs.51cto.com/thread-1082542-1.html作者:imcxz时间快到了下午五点半,我盖好笔帽,浏览了一遍当天的笔记,打卡锁电脑,准备下班……来到公司已有将近三年的时间,当时我是处于公司IT人手不够情况下应聘进来的,第一年公司着手搬家,领导带着我参与了新机房建设、新办公区网络规划、机房搬迁等相关工作,我因此学到了很多知识。第一年下半部和第二年,我参与了多项完善、测试及上线工作,例如下一代防火墙、无线网络、oracle存储、ESXI升级、专线部署、备份、软硬件资产管理、相关文档的起草和撰写等。那是充满忙碌和激情的两年时间,我不断学习、进步、丰富自我的专业知识,虽然经常加班,虽然很累,但是乐在其中不知疲倦。经过了将近两年时间的忙碌和完善,公司的IT系统趋于巩固。由于各方面的原因吧,我们进入了一个平缓期,项目没有了,测试也没有了,每日局限于查看日志,小修小改,就像从顶楼一下滑落到了地下室,及其不适应,浑身发痒的感觉也越来越强烈。我不可避免的也开始了迷茫,一下不知道自己该做些什么,每日重复的工作让我毫无乐趣,虽然都是一些机械化的操作,但是脑子却变得越来越迟钝,越来于迷糊了。这样的情况持续了将近半年的时间,大家逐渐趋向于安逸的节奏,上班无非浏览新闻,广播网购打折信息,QQ打屁YY之类的无聊之事,逐渐的开始有了员工的离职,而让我顿悟的是几个老员工的离职,给了我警示——不能再这样下去了。我开始反省,才发现自己掌握的知识实在是少的可怜,涉及公司技术的方面,例如AD、exchange、lync、邮件网关、虚拟化、存储、防火墙等只是有了一个概面的了解,尤其对于自己主要负责的网络方面,基础理论的掌握实在是差的厉害,总结出来就是——我知道要这么做,但是不知道为什么要这么做。这让我失落、但立即想到的是行动。我开始重新复习原来了解的知识方面,从最基础的开始。按照自己的习惯,我延续了在学校的方法,一遍复习一遍做笔记,到目前为止,我重新学习了一遍lync、exchange、ESXI基础架构、CCNA、CCNP网络。重新学习的过程是枯燥无味的,但效果就是你能和现有的生产环境结合起来,触通旁类!例如acl方面,除了常规的配置,你可以了解基于时间的acl、自反acl等等。在学习的过程中,你会有经常性的顿悟,那样的感觉不可言表。我的一个同学嘲笑我沉迷于无前途的技术,我无法反驳,我只想做自己喜欢的事情,或者我可以跳槽、转行,而且有可能在其他领域能够赚取更多的金钱,但我觉得那还没有到时候,我从最初连LYNC都没听过的小菜鸟,到现在能够负责公司网络部分的转变;从最初的杂乱不精自以为是,到现在的系统分析冷静判断;这都是端正心态、不断积累的结果。(这只是个人态度,大家看看即可,不要因此放弃难得的机遇)我想起曾读过多遍的一部小说里面的话:“生命的精彩、幸福的喜悦不在于人努力后得到的结果,而在于创造结果的过程!”不要看不上Helpdesk,照样可以做的精彩;不要觉得微软傻瓜化,要精通非常困难;不要以为虚拟化缥缈,基础掌握并不复杂;不要把程序猿屌丝化,搞个后门让你瞪眼;不要把攻城狮当民工,键盘一敲让你网络全挂。学到的看到的越多,才发现自己知识的匮乏,处于一个安逸的时期,暂时的迷茫是正常的,最主要的还是要及时发现自己的问题,不断的去研究、学习、请教,丰富自我。因此我认为——暂时的安逸,是为将来的激情做准备!——谨以此文献给所有感觉自己安逸的午饭们!————2013年11月12日晚
休闲 1 0 267天前
admin
526
原文地址:http://weibo.com/ttarticle/p/show?id=2309351002704146441940550858&u=1668632407&m=4146441712461037&cu=1668632407写在前面前两天和几位技术大牛聊天,大家突然发现那些身边的优秀的技术人中,有很多人都拥有相同的路径和很多共同点。简单的说,技术大牛虽然凤毛麟角,但其实成为技术大牛也没有那么困难,就是“有技巧无捷径”。“有技巧”是说,任何一个领域的专家,只要精通该领域的已有知识就可以,只要你的学习能力够强、能够掌握一些经验技巧就一定能够办得到,不像很多岗位对于“创新”的要求,需要用已有的知识创造出未知的产品。“无捷径”是说水到渠成,你把该做的事情一件一件琢磨好,在每一件事情上多下点功夫,自然而然就会有“渠”。除了技术类岗位,很多岗位的要求也都一样,胜任力或者发展轨迹很清晰,看似不难,难得是有人可以沉得下心来细细打磨。就来说说技术大牛们通常不同阶段的注意力都在哪,也可以说是需要你沉下心来好好打磨的四个层次——第一个层次,专业领域内的技术精通。要作为一名技术领域的强人,必须要确保在某个技术方向上非常精通,技术的根基要扎得非常深,稳扎稳打,这是你的技术招牌。前两天朋友圈有人问:“面试时候是否会问设计模式相关的问题。”很多大牛表示很少问道,因为越是优秀的技术人员,注意力越是在一线技术上,越是关注在表面花哨的东西,越写不出牛逼的代码。所以第一个层次,需要沉得下心,深钻技术,细细打磨。第二个层次,有一定的技术广度。技术的深度和广度本来就是一个相辅相成的协同,有时候其实没有办法分出个先后。你会发现,很多技术大牛非常非常的博学,他们似乎都精力无限、兴趣广泛?没错,广度这个事情指的就是信息量,而信息量的获取往往跟精力和兴趣相关。 很多人会询问技术的深度和广度那个更重要,我觉得“吃透一样才是立身之本”,所以广度应该有,但是更多的时候“广度”要辅助“深度”。即时很多事情你并没有做过,但一定要清楚个二三,需要的时候可以立即钻进去。所以第二个层次,需要的是走出去的心境。第三个层次,潜入到行业中了解业务和流程。做得越多,你越会发现没有技术独立存在的场景,技术的存在是为了更好的服务于应用场景,不潜入到一个行业当中,不知晓行业的应用环境、组织流程、商业价值,就难以做出和业务无痕交融的产品。技术是把商业需求转换成产品的一个关键角色,因此第三个层次,需要的是了解技术以外的东西。第四个层次,了解社会心理学。做得更多,你会发现,你会从对技术的研究,变为对行业的研究,再变为对人性的研究。产品最终是为了满足人的需要才有价值,而产品研发本身也需要多人协作。社会心理学主要是研究人际关系。当然了,我觉得这个还是非常难的,一般做到二三层次就已经可以是技术大牛了。对CEO的要求可以这么苛刻。
休闲 6 0 269天前
admin
544
比尔·盖茨31岁,就成为世界首富。很多人好奇,作为世界第一大PC系统的创始人,抛弃世界首富的头衔,单单从程序员角度来讨论,比尔盖茨的代码水平如何?其实,比尔·盖茨对写代码有一种狂热的喜好。上高中的时候,为了获得源代码,比尔·盖茨曾经去翻垃圾桶。据了解,在1978年的Microsoft BASIC源代码6502中,比尔·盖茨实现了FOR和GOSUB的所有BASIC语句,函数,运算符,表达式评估,堆栈管理,内存管理器,数组和字符串库。昨日,编程网站w3cschool报道,在未经微软或比尔盖茨同意的情况下,某人公开了1978年的Microsoft BASIC for 6502源代码,以及原始评论、文档和彩蛋,这是目前公开的比尔·盖茨写的最古老程序。除了比尔盖茨外,很多互联网大佬都是程序员出身,比如马化腾、比如雷军等人。TITLE BASIC M6502 8K VER 1.1 BY MICRO-SOFT SEARCH M6502 SALL RADIX 10 ;THROUGHOUT ALL BUT MATH-PAK. $Z:: ;STARTING POINT FOR M6502 SIMULATOR ORG 0 ;START OFF AT LOCATION ZERO. SUBTTL SWITCHES,MACROS. REALIO=4 ;5=STM ;4=APPLE. ;3=COMMODORE. ;2=OSI ;1=MOS TECH,KIM ;0=PDP-10 SIMULATING 6502 INTPRC==1 ;INTEGER ARRAYS. ADDPRC==1 ;FOR ADDITIONAL PRECISION. LNGERR==0 ;LONG ERROR MESSAGES. TIME== 0 ;CAPABILITY TO SET AND READ A CLK. EXTIO== 0 ;EXTERNAL I/O. DISKO== 0 ;SAVE AND LOAD COMMANDS NULCMD==1 ;FOR THE "NULL" COMMAND GETCMD==1 RORSW==1 ROMSW==1 ;TELLS IF THIS IS ON ROM. CLMWID==14 LONGI==1 ;LONG INITIALIZATION SWITCH. STKEND=511 BUFPAG==0 LINLEN==72 ;TERMINAL LINE LENGTH. BUFLEN==72 ;INPUT BUFFER SIZE. ROMLOC= ^O20000 ;ADDRESS OF START OF PURE SEGMENT. KIMROM=1 IFE ROMSW,<KIMROM==0> IFN REALIO-1,<KIMROM==0> IFN ROMSW,< RAMLOC= ^O40000 ;USED ONLY IF ROMSW=1 IFE REALIO,<ROMLOC= ^O20000 ;START AT 8K. RAMLOC=^O1400>> IFE REALIO-3,< DISKO==1 RAMLOC==^O2000 ROMLOC=^O140000 NULCMD==0 GETCMD==1 linlen==40 BUFLEN==81 CQOPEN=^O177700 CQCLOS=^O177703 CQOIN= ^O177706 ;OPEN CHANNEL FOR INPUT CQOOUT=^O177711 ;FILL FOR COMMO. CQCCHN=^O177714 CQINCH=^O177717 ;INCHR'S CALL TO GET A CHARACTER OUTCH= ^O177722 CQLOAD=^O177725 CQSAVE=^O177730 CQVERF=^O177733 CQSYS= ^O177736 ISCNTC=^O177741 CZGETL=^O177744 ;CALL POINT FOR "GET" CQCALL=^O177747 ;CLOSE ALL CHANNELS CQTIMR=^O215 BUFPAG==2 BUF==256BUFPAG STKEND==507 CQSTAT=^O226 CQHTIM=^O164104 EXTIO==1 TIME==1 GETCMD==1 CLMWID==10 PI=255 ;VALUE OF PI CHARACTER FOR COMMODORE. ROMSW==1 RORSW==1 TRMPOS=^O306> IFE REALIO-1,<GETCMD==1 DISKO==1 OUTCH=^O17240 ;1EA0 ROMLOC==^O20000 RORSW==0 CZGETL=^O17132> IFE REALIO-2,< RORSW==0 RAMLOC==^O1000 IFN ROMSW,< RORSW==0 RAMLOC==^O100000> OUTCH==^O177013> IFE REALIO-4,< RORSW==1 NULCMD==0 GETCMD==1 CQINLN==^O176547 CQPRMP==^O63 CQINCH==^O176414 CQCOUT==^O177315 CQCSIN==^O177375 BUFPAG==2 BUF=BUFPAG256 ROMLOC=^O4000 RAMLOC=^O25000 ;PAGE 2A OUTCH=^O176755 CZGETL=^O176414 LINLEN==40 BUFLEN==240 RORSW==1 STKEND=507> IFE RORSW,< DEFINE ROR (WD),< LDAI 0 BCC .+4 LDAI ^O200 LSR WD ORA WD STA WD>> DEFINE ACRLF,< 13 10> DEFINE SYNCHK (Q),< LDAI <Q> JSR SYNCHR> DEFINE DT(Q),< IRPC Q,<IFDIF <Q><">,<EXP "Q">>> DEFINE LDWD (WD),< LDA WD LDY <WD>+1> DEFINE LDWDI (WD),< LDAI <<WD>&^O377> LDYI <<WD>/^O400>> DEFINE LDWX (WD),< LDA WD LDX <WD>+1> DEFINE LDWXI (WD),< LDAI <<WD>&^O377> LDXI <<WD>/^O400>> DEFINE LDXY (WD),< LDX WD LDY <WD>+1> DEFINE LDXYI (WD),< LDXI <<WD>&^O377> LDYI <<WD>/^O400>> DEFINE STWD (WD),< STA WD STY <WD>+1> DEFINE STWX (WD),< STA WD STX <WD>+1> DEFINE STXY (WD),< STX WD STY <WD>+1> DEFINE CLR (WD),< LDAI 0 STA WD> DEFINE COM (WD),< LDA WD EORI ^O377 STA WD> DEFINE PULWD (WD),< PLA STA WD PLA STA <WD>+1> DEFINE PSHWD (WD),< LDA <WD>+1 PHA LDA WD PHA> DEFINE JEQ (WD),< BNE .+5 JMP WD> DEFINE JNE (WD),< BEQ .+5 JMP WD> DEFINE BCCA(Q),< BCC Q> ;BRANCHES THAT ALWAYS BRANCH DEFINE BCSA(Q),< BCS Q> ;THESE ARE USED ON THE 6502 BECAUSE DEFINE BEQA(Q),< BEQ Q> ;THERE IS NO UNCONDITIONAL BRANCH DEFINE BNEA(Q),< BNE Q> DEFINE BMIA(Q),< BMI Q> DEFINE BPLA(Q),< BPL Q> DEFINE BVCA(Q),< BVC Q> DEFINE BVSA(Q),< BVS Q> DEFINE INCW(R),< INC R BNE %Q INC R+1 %Q:> DEFINE SKIP1, <XWD ^O1000,^O044> ;BIT ZERO PAGE TRICK. DEFINE SKIP2, <XWD ^O1000,^O054> ;BIT ABS TRICK. IF1,< IFE REALIO,<PRINTX/SIMULATE/> IFE REALIO-1,<PRINTX KIM> IFE REALIO-2,<PRINTX OSI> IFE REALIO-3,<PRINTX COMMODORE> IFE REALIO-4,<PRINTX APPLE> IFE REALIO-5,<PRINTX STM> IFN ADDPRC,<PRINTX ADDITIONAL PRECISION> IFN INTPRC,<PRINTX INTEGER ARRAYS> IFN LNGERR,<PRINTX LONG ERRORS> IFN DISKO,<PRINTX SAVE AND LOAD> IFE ROMSW,<PRINTX RAM> IFN ROMSW,<PRINTX ROM> IFE RORSW,<PRINTX NO ROR> IFN RORSW,<PRINTX ROR ASSUMED>> PAGE SUBTTL INTRODUCTION AND COMPILATION PARAMETERS. COMMENT --------- ---- -- --------- COPYRIGHT 1976 BY MICROSOFT --------- ---- -- --------- 7/27/78 FIXED BUG WHERE FOR VARIABLE AT BYTE FF MATCHED RETURN SEARCHING FOR GOSUB ENTRY ON STACK IN FNDFOR CALL BY CHANGING STA FORPNT TO STA FORPNT+1. THIS IS A SERIOUS BUG IN ALL VERSIONS. 7/27/78 FIXED BUG AT NEWSTT UNDER IFN BUFPAG WHEN CHECK OF CURLIN WAS DONE BEFORE CURLIN SET UP SO INPUT RETRIES OF FIRST STATEMENT WAS GIVING SYNTAX ERROR INSTEAD OF REDO FROM START (CODE WAS 12/1/77 FIX) 7/1/78 SAVED A FEW BYTES IN INIT FOR COMMODORE (14) 7/1/78 FIXED BUG WHERE REPLACING A LINE OVERFLOWING MEMORY LEFT LINKS IN A BAD STATE. (CODE AT NODEL AND FINI) BUG#4 7/1/78 FIXED BUG WHERE GARBAGE COLLECTION NEVER(!) COLLECTS TEMPS (STY GRBPNT AT FNDVAR, LDA GRBPNT ORA GRBPNT+1 AT GRBPAS) THIS WAS COMMODORE BUG #2 7/1/78 FIXED BUG WHERE DELETE/INSERT OF LINE COULD CAUSE A GARBAGE COLLECTION WITH BAD VARTAB IF OUT OF MEMORY (LDWD MEMSIZ STWD FRETOP=JSR RUNC CLC ALSO AT NODEL) 3/9/78 EDIT TO FIX COMMO TRMPOS AND CHANGE LEFT$ AND RIGHT$ TO ALLOW A SECOND ARGUMENT OF 0 AND RETURN A NULL STRING 2/25/78 FIXED BUG THAT INPFLG WAS SET WRONG WHEN BUFPAG.NE.0 INCREASED NUMLEV FROM 19 TO 23 2/11/78 DISALLOWED SPACES IN RESERVED WORDS. PUT IN SPECIAL CHECK FOR "GO TO" 2/11/78 FIXED BUG WHERE ROUNDING OF THE FAC BEFORE PUSHING COULD CAUSE A STRING POINTER IN THE FAC TO BE INCREMENTED 1/24/78 fixed problem where user defined function undefined check fix was smashing error number in [x] 12/1/77 FIXED PROBLEM WHERE PEEK WAS SMASHING (POKER) CAUSING POKE OF PEEK TO FAIL 12/1/77 FIXED PROBLEM WHERE PROBLEM WITH VARTXT=LINNUM=BUF-2 CAUSING BUF-1 COMMA TO DISAPPEAR 12/1/77 FIXED BUFPAG.NE.0 PROBLEM AT NEWSTT AND STOP : CODE WAS STILL ASSUMING TXTPTR+1.EQ.0 IFF STATEMENT WAS DIRECT NUMLEV==23 ;NUMBER OF STACK LEVELS RESERVED ;BY AN EXPLICIT CALL TO "GETSTK". STRSIZ==3 ;# OF LOCS PER STRING DESCRIPTOR. NUMTMP==3 ;NUMBER OF STRING TEMPORARIES. CONTW==15 ;CHARACTER TO SUPPRESS OUTPUT. PAGE SUBTTL SOME EXPLANATION. COMMENT M6502 BASIC CONFIGURES BASIC AS FOLLOWS LOW LOCATIONS PAGE ZERO STARTUP: INITIALLY A JMP TO INITIALIZATION CODE BUT CHANGED TO A JMP TO "READY". RESTARTING THE MACHINE AT LOC 0 DURING PROGRAM EXECUTION CAN LEAVE THINGS MESSED UP. LOC OF FAC TO INTEGER AND INTEGER TO FAC ROUTINES. "DIRECT" MEMORY: THESE ARE THE MOST COMMONLY USED LOCATIONS. THEY HOLD BOOKKEEPING INFO AND ALL OTHER FREQUENTLY USED INFORMATION. ALL TEMPORARIES, FLAGS, POINTERS, THE BUFFER AREA, THE FLOATING ACCUMULATOR, AND ANYTHING ELSE THAT IS USED TO STORE A CHANGING VALUE SHOULD BE LOCATED IN THIS AREA. CARE MUST BE MADE IN MOVING LOCATIONS IN THIS AREA SINCE THE JUXTAPOSITION OF TWO LOCATIONS IS OFTEN DEPENDED UPON. STILL IN RAM WE HAVE THE BEGINNING OF THE "CHRGET" SUBROUTINE. IT IS HERE SO [TXTPTR] CAN BE THE EXTENDED ADDRESS OF A LOAD INSTRUCTION. THIS SAVES HAVING TO BOTHER ANY REGISTERS. PAGE ONE THE STACK. STORAGE PAGE TWO AND ON IN RAM VERSIONS THESE DATA STRUCTURES COME AT THE END OF BASIC. IN ROM VERSON THEY ARE AT RAMLOC WHICH CAN EITHER BE ABOVE OR BELOW ROMLOC, WHICH IS WHERE BASIC ITSELF RESIDES. A ZERO. [TXTTAB] POINTER TO NEXT LINE'S POINTER. LINE # OF THIS LINE (2 BYTES). CHARACTERS ON THIS LINE. ZERO. POINTER AT NEXT LINE'S POINTER (POINTED TO BY THE ABOVE POINTER). ... REPEATS ... LAST LINE: POINTER AT ZERO POINTER. LINE # OF THIS LINE. CHARACTERS ON THIS LINE. ZERO. DOUBLE ZERO (POINTED TO BY THE ABOVE POINTER). [VARTAB] SIMPLE VARIABLES. 6 BYTES PER VALUE. 2 BYTES GIVE THE NAME, 4 BYTES THE VALUE. ... REPEATS ... [ARYTAB] ARRAY VARIABLES. 2 BYTES NAME, 2 BYTE LENGTH, NUMBER OF DIMENSIONS , EXTENT OF EACH DIMENSION (2BYTES/), VALUES ... REPEATS ... [STREND] FREE SPACE. ... REPEATS ... [FRETOP] STRING SPACE IN USE. ... REPEATS ... [MEMSIZ] HIGHEST MACHINE LOCATION. UNUSED EXCEPT BY THE VAL FUNCTION. ROM -- CONSTANTS AND CODE. FUNCTION DISPATCH ADDRESSES (AT ROMLOC) "FUNDSP" CONTAINS THE ADDRESSES OF THE FUNCTION ROUTINES IN THE ORDER OF THE FUNCTION NAMES IN THE CRUNCH LIST. THE FUNCTIONS THAT TAKE MORE THAN ONE ARGUMENT ARE AT THE END. SEE THE EXPLANATION AT "ISFUN". THE OPERATOR LIST THE "OPTAB" LIST CONTAINS AN OPERATOR'S PRECEDENCE FOLLOWED BY THE ADDRESS OF THE ROUTINE TO PERFORM THE OPERATION. THE INDEX INTO THE OPERATOR LIST IS MADE BY SUBTRACTING OFF THE CRUNCH VALUE OF THE LOWEST NUMBERED OPERATOR. THE ORDER OF OPERATORS IN THE CRUNCH LIST AND IN "OPTAB" IS IDENTICAL. THE PRECEDENCES ARE ARBITRARY EXCEPT FOR THEIR COMPARATIVE SIZES. NOTE THAT THE PRECEDENCE FOR UNARY OPERATORS SUCH AS "NOT" AND NEGATION ARE SETUP SPECIALLY WITHOUT USING THE LIST. THE RESERVED WORD OR CRUNCH LIST WHEN A COMMAND OR PROGRAM LINE IS TYPED IN IT IS STORED IN "BUF". AS SOON AS THE WHOLE LINE HAS BEEN TYPED IN ("INLIN" RETURNS) "CRUNCH" IS CALLED TO CONVERT ALL RESERVED WORDS TO THEIR CRUNCHED VALUES. THIS REDUCES THE SIZE OF THE PROGRAM AND SPEEDS UP EXECUTION BY ALLOWING LIST DISPATCHES TO PERFORM FUNCTIONS, STATEMENTS, AND OPERATIONS. THIS IS BECAUSE ALL THE STATEMENT NAMES ARE STORED CONSECUTIVELY IN THE CRUNCH LIST. WHEN A MATCH IS FOUND BETWEEN A STRING OF CHARACTERS AND A WORD IN THE CRUNCH LIST THE ENTIRE TEXT OF THE MATCHED WORD IS TAKEN OUT OF THE INPUT LINE AND A RESERVED WORD TOKEN IS PUT IN ITS PLACE. A RESERVED WORD TOKEN IS ALWAYS EQUAL TO OCTAL 200 PLUS THE POSITION OF THE MATCHED WORD IN THE CRUNCH LIST. STATEMENT DISPATCH ADDRESSES WHEN A STATEMENT IS TO BE EXECUTED, THE FIRST CHARACTER OF THE STATEMENT IS EXAMINED TO SEE IF IT IS LESS THAN THE RESERVED WORD TOKEN FOR THE LOWEST NUMBERED STATEMENT NAME. IF SO, THE "LET" CODE IS CALLED TO TREAT THE STATEMENT AS AN ASSIGNMENT STATEMENT. OTHERWISE A CHECK IS MADE TO MAKE SURE THE RESERVED WORD NUMBER IS NOT TOO LARGE TO BE A STATEMENT TYPE NUMBER. IF NOT THE ADDRESS TO DISPATCH TO IS FETCHED FROM "STMDSP" (THE STATEMENT DISPATCH LIST) USING THE RESERVED WORD NUMBER FOR THE STATEMENT TO CALCULATE AN INDEX INTO THE LIST. ERROR MESSAGES WHEN AN ERROR CONDITION IS DETECTED, [ACCX] MUST BE SET UP TO INDICATE WHICH ERROR MESSAGE IS APPROPRIATE AND A BRANCH MUST BE MADE TO "ERROR". THE STACK WILL BE RESET AND ALL PROGRAM CONTEXT WILL BE LOST. VARIABLES VALUES AND THE ACTUAL PROGRAM REMAIN INTACT. ONLY THE VALUE OF [ACCX] IS IMPORTANT WHEN THE BRANCH IS MADE TO ERROR. [ACCX] IS USED AS AN INDEX INTO "ERRTAB" WHICH GIVES THE TWO CHARACTER ERROR MESSAGE THAT WILL BE PRINTED ON THE USER'S TERMINAL. TEXTUAL MESSAGES CONSTANT MESSAGES ARE STORED HERE. UNLESS THE CODE TO CHECK IF A STRING MUST BE COPIED IS CHANGED THESE STRINGS MUST BE STORED ABOVE PAGE ZERO, OR ELSE THEY WILL BE COPIED BEFORE THEY ARE PRINTED. FNDFOR MOST SMALL ROUTINES ARE FAIRLY SIMPLE AND ARE DOCUMENTED IN PLACE. "FNDFOR" IS USED FOR FINDING "FOR" ENTRIES ON THE STACK. WHENEVER A "FOR" IS EXECUTED, A 16-BYTE ENTRY IS PUSHED ONTO THE STACK. BEFORE THIS IS DONE, HOWEVER, A CHECK MUST BE MADE TO SEE IF THERE ARE ANY "FOR" ENTRIES ALREADY ON THE STACK FOR THE SAME LOOP VARIABLE. IF SO, THAT "FOR" ENTRY AND ALL OTHER "FOR" ENTRIES THAT WERE MADE AFTER IT ARE ELIMINATED FROM THE STACK. THIS IS SO A PROGRAM THAT JUMPS OUT OF THE MIDDLE OF A "FOR" LOOP AND THEN RESTARTS THE LOOP AGAIN AND AGAIN WON'T USE UP 18 BYTES OF STACK SPACE EVERY TIME. THE "NEXT" CODE ALSO CALLS "FNDFOR" TO SEARCH FOR A "FOR" ENTRY WITH THE LOOP VARIABLE IN THE "NEXT". AT WHATEVER POINT A MATCH IS FOUND THE STACK IS RESET. IF NO MATCH IS FOUND A "NEXT WITHOUT FOR" ERROR OCCURS. GOSUB EXECUTION ALSO PUTS A 5-BYTE ENTRY ON STACK. WHEN A RETURN IS EXECUTED "FNDFOR" IS CALLED WITH A VARIABLE POINTER THAT CAN'T BE MATCHED. WHEN "FNDFOR" HAS RUN THROUGH ALL THE "FOR" ENTRIES ON THE STACK IT RETURNS AND THE RETURN CODE MAKES SURE THE ENTRY THAT WAS STOPPED ON IS A GOSUB ENTRY. THIS ASSURES THAT IF YOU GOSUB TO A SECTION OF CODE IN WHICH A FOR LOOP IS ENTERED BUT NEVER EXITED THE RETURN WILL STILL BE ABLE TO FIND THE MOST RECENT GOSUB ENTRY. THE "RETURN" CODE ELIMINATES THE "GOSUB" ENTRY AND ALL "FOR" ENTRIES MADE AFTER THE GOSUB ENTRY. NON-RUNTIME STUFF THE CODE TO INPUT A LINE, CRUNCH IT, GIVE ERRORS, FIND A SPECIFIC LINE IN THE PROGRAM, PERFORM A "NEW", "CLEAR", AND "LIST" ARE ALL IN THIS AREA. GIVEN THE EXPLANATION OF PROGRAM STORAGE SET FORTH ABOVE, THESE ARE ALL STRAIGHTFORWARD. NEWSTT WHENEVER A STATEMENT FINISHES EXECUTION IT DOES A "RTS" WHICH TAKES EXECUTION BACK TO "NEWSTT". STATEMENTS THAT CREATE OR LOOK AT SEMI-PERMANENT STACK ENTRIES MUST GET RID OF THE RETURN ADDRESS OF "NEWSTT" AND JMP TO "NEWSTT" WHEN DONE. "NEWSTT" ALWAYS CHRGETS THE FIRST CHARACTER AFTER THE STATEMENT NAME BEFORE DISPATCHING. WHEN RETURNING BACK TO "NEWSTT" THE ONLY THING THAT MUST BE SET UP IS THE TEXT POINTER IN "TXTPTR". "NEWSTT" WILL CHECK TO MAKE SURE "TXTPTR" IS POINTING TO A STATEMENT TERMINATOR. IF A STATEMENT SHOULDN'T BE PERFORMED UNLESS IT IS PROPERLY FORMATTED (I.E. "NEW") IT CAN SIMPLY DO A RETURN AFTER READING ALL OF ITS ARGUMENTS. SINCE THE ZERO FLAG BEING OFF INDICATES THERE IS NOT A STATEMENT TERMINATOR "NEWSTT" WILL DO THE JMP TO THE "SYNTAX ERROR" ROUTINE. IF A STATEMENT SHOULD BE STARTED OVER IT CAN DO LDWD OLDTXT, STWD TXTPTR RTS SINCE THE TEXT PNTR AT "NEWSTT" IS ALWAYS STORED IN "OLDTXT". THE ^C CODE STORES [CURLIN] (THE CURRENT LINE NUMBER) IN "OLDLIN" SINCE THE ^C CHECK IS MADE BEFORE THE STATEMENT POINTED TO IS EXECUTED. "STOP" AND "END" STORE THE TEXT POINTER FROM "TXTPTR", WHICH POINTS AT THEIR TERMINATING CHARACTER, IN "OLDTXT". STATEMENT CODE THE INDIVIDUAL STATEMENT CODE COMES NEXT. THE APPROACH USED IN EXECUTING EACH STATEMENT IS DOCUMENTED IN THE STATEMENT CODE ITSELF. FRMEVL, THE FORMULA EVALUATOR GIVEN A TEXT POINTER POINTING TO THE STARTING CHARACTER OF A FORMULA, "FRMEVL" EVALUATES THE FORMULA AND LEAVES THE VALUE IN THE FLOATING ACCUMULATOR (FAC). "TXTPTR" IS RETURNED POINTING TO THE FIRST CHARACTER THAT COULD NOT BE INTERPRETED AS PART OF THE FORMULA. THE ALGORITHM USES THE STACK TO STORE TEMPORARY RESULTS: 0. PUT A DUMMY PRECEDENCE OF ZERO ON THE STACK. 1. READ LEXEME (CONSTANT,FUNCTION, VARIABLE,FORMULA IN PARENS) AND TAKE THE LAST PRECEDENCE VALUE OFF THE STACK. 2. SEE IF THE NEXT CHARACTER IS AN OPERATOR. IF NOT, CHECK PREVIOUS ONE. THIS MAY CAUSE OPERATOR APPLICATION OR AN ACTUAL RETURN FROM "FRMEVL". 3. IF IT IS, SEE WHAT PRECEDENCE IT HAS AND COMPARE IT TO THE PRECEDENCE OF THE LAST OPERATOR ON THE STACK. 4. IF = OR LESS REMEMBER THE OPERATOR POINTER OF THIS OPERATOR AND BRANCH TO "QCHNUM" TO CAUSE APPLICATION OF THE LAST OPERATOR. EVENTUALLY RETURN TO STEP 2 BY RETURNING TO JUST AFTER "DOPREC". 5. IF GREATER PUT THE LAST PRECEDENCE BACK ON, SAVE THE OPERATOR ADDRESS, CURRENT TEMPORARY RESULT, AND PRECEDENCE AND RETURN TO STEP 1. RELATIONAL OPERATORS ARE ALL HANDLED THROUGH A COMMON ROUTINE. SPECIAL CARE IS TAKEN TO DETECT TYPE MISMATCHES SUCH AS 3+"F". EVAL -- THE ROUTINE TO READ A LEXEME "EVAL" CHECKS FOR THE DIFFERENT TYPES OF ENTITIES IT IS SUPPOSED TO DETECT. LEADING PLUSES ARE IGNORED, DIGITS AND "." CAUSE "FIN" (FLOATING INPUT) TO BE CALLED. FUNCTION NAMES CAUSE THE FORMULA INSIDE THE PARENTHESES TO BE EVALUATED AND THE FUNCTION ROUTINE TO BE CALLED. VARIABLE NAMES CAUSE "PTRGET" TO BE CALLED TO GET A POINTER TO THE VALUE, AND THEN THE VALUE IS PUT INTO THE FAC. AN OPEN PARENTHESIS CAUSES "FRMEVL" TO BE CALLED (RECURSIVELY), AND THE ")" TO BE CHECKED FOR. UNARY OPERATORS (NOT AND NEGATION) PUT THEIR PRECEDENCE ON THE STACK AND ENTER FORMULA EVALUATION AT STEP 1, SO THAT EVERYTHING UP TO AN OPERATOR GREATER THAN THEIR PRECEDENCE OR THE END OF THE FORMULA WILL BE EVALUATED. DIMENSION AND VARIABLE SEARCHING SPACE IS ALLOCATED FOR VARIABLES AS THEY ARE ENCOUNTERED. THUS "DIM" STATEMENTS MUST BE EXECUTED TO HAVE EFFECT. 6 BYTES ARE ALLOCATED FOR EACH SIMPLE VARIABLE, WHETHER IT IS A STRING, NUMBER OR USER DEFINED FUNCTION. THE FIRST TWO BYTES GIVE THE NAME OF THE VARIABLE AND THE LAST FOUR GIVE ITS VALUE. [VARTAB] GIVES THE FIRST LOCATION WHERE A SIMPLE VARIABLE NAME IS FOUND AND [ARYTAB] GIVES THE LOCATION TO STOP SEARCHING FOR SIMPLE VARIABLES. A "FOR" ENTRY HAS A TEXT POINTER AND A POINTER TO A VARIABLE VALUE SO NEITHER THE PROGRAM OR THE SIMPLE VARIABLES CAN BE MOVED WHILE THERE ARE ACTIVE "FOR" ENTRIES ON THE STACK. USER DEFINED FUNCTION VALUES ALSO CONTAIN POINTERS INTO SIMPLE VARIABLE SPACE SO NO USER-DEFINED FUNCTION VALUES CAN BE RETAINED IF SIMPLE VARIABLES ARE MOVED. ADDING A SIMPLE VARIABLE IS JUST ADDING SIX TO [ARYTAB] AND [STREND], BLOCK TRANSFERING THE ARRAY VARIABLES UP BY SIX AND MAKING SURE THE NEW [STREND] IS NOT TOO CLOSE TO THE STRINGS. THIS MOVEMENT OF ARRAY VARIABLES MEANS THAT NO POINTER TO AN ARRAY WILL STAY VALID WHEN NEW SIMPLE VARIABLES CAN BE ENCOUNTERED. THIS IS WHY ARRAY VARIABLES ARE NOT ALLOWED FOR "FOR" LOOP VARIABLES. SETTING UP A NEW ARRAY VARIABLE MERELY INVOLVES BUILDING THE DESCRIPTOR, UPDATING [STREND], AND MAKING SURE THERE IS STILL ENOUGH ROOM BETWEEN [STREND] AND STRING SPACE. "PTRGET", THE ROUTINE WHICH RETURNS A POINTER TO A VARIABLE VALUE, HAS TWO IMPORTANT FLAGS. ONE IS "DIMFLG" WHICH INDICATES WHETHER "DIM" CALLED "PTRGET" OR NOT. IF SO, NO PRIOR ENTRY FOR THE VARIABLE IN QUESTION SHOULD BE FOUND, AND THE INDEX INDICATES HOW MUCH SPACE TO SET ASIDE. SIMPLE VARIABLES CAN BE "DIMENSIONED", BUT THE ONLY EFFECT WILL BE TO SET ASIDE SPACE FOR THE VARIABLE IF IT HASN'T BEEN ENCOUNTERED YET. THE OTHER IMPORTANT FLAG IS "SUBFLG" WHICH INDICATES WHETHER A SUBSCRIPTED VARIABLE SHOULD BE ALLOWED IN THE CURRENT CONTEXT. IF [SUBFLG] IS NON-ZERO THE OPEN PARENTHESIS FOR A SUBSCRIPTED VARIABLE WILL NOT BE SCANNED BY "PTRGET", AND "PTRGET" WILL RETURN WITH A TEXT POINTER POINTING TO THE "(", IF THERE WAS ONE. STRINGS IN THE VARIABLE TABLES STRINGS ARE STORED JUST LIKE NUMERIC VARIABLES. SIMPLE STRINGS HAVE THREE VALUE BYTES WHICH ARE INITIALIZED TO ALL ZEROS (WHICH REPRESENTS THE NULL STRING). THE ONLY DIFFERENCE IN HANDLING IS THAT WHEN "PTRGET" SEES A "$" AFTER THE NAME OF A VARIABLE, "PTRGET" SETS [VALTYP] TO NEGATIVE ONE AND TURNS ON THE MSB (MOST-SIGNIFIGANT-BIT) OF THE VALUE OF THE FIRST CHARACTER OF THE VARIABLE NAME. HAVING THIS BIT ON IN THE NAME OF THE VARIABLE ENSURES THAT THE SEARCH ROUTINE WILL NOT MATCH 'A' WITH 'A$' OR 'A$' WITH 'A'. THE MEANING OF THE THREE VALUE BYTES ARE: LOW LENGTH OF THE STRING LOW 8 BITS HIGH 8 BITS OF THE ADDRESS OF THE CHARACTERS IN THE STRING IF LENGTH.NE.0. MEANINGLESS OTHERWISE. HIGH THE VALUE OF A STRING VARIABLE (THESE 3 BYTES) IS CALLED THE STRING DESCRIPTOR TO DISTINGUISH IT FROM THE ACTUAL STRING DATA. WHENEVER A STRING CONSTANT IS ENCOUNTERED IN A FORMULA OR AS PART OF AN INPUT STRING, OR AS PART OF DATA, "STRLIT" IS CALLED, CAUSING A DESCRIPTOR TO BE BUILT FOR THE STRING. WHEN ASSIGNMENT IS MADE TO A STRING POINTING INTO "BUF" THE VALUE IS COPIED INTO STRING SPACE SINCE [BUF] IS ALWAYS CHANGING. STRING FUNCTIONS AND THE ONE STRING OPERATOR "+" ALWAYS RETURN THEIR VALUES IN STRING SPACE. ASSIGNING A STRING A CONSTANT VALUE IN A PROGRAM THROUGH A "READ" OR ASSIGNMENT STATEMENT WILL NOT USE ANY STRING SPACE SINCE THE STRING DESCRIPTOR WILL POINT INTO THE PROGRAM ITSELF. IN GENERAL, COPYING IS DONE WHEN A STRING VALUE IS IN "BUF", OR IT IS IN STRING SPACE AND THERE IS AN ACTIVE POINTER TO IT. THUS F$=G$ WILL CAUSE COPYING IF G$ HAS ITS STRING DATA IN STRING SPACE. F$=CHR$(7) WILL USE ONE BYTE OF STRING SPACE TO STORE THE NEW ONE CHARACTER STRING CREATED BY "CHR$", BUT THE ASSIGNMENT ITSELF WILL CAUSE NO COPYING SINCE THE ONLY POINTER AT THE NEW STRING IS A TEMPORARY DESCRIPTOR CREATED BY "FRMEVL" WHICH WILL GO AWAY AS SOON AS THE ASSIGNMENT IS DONE. IT IS THE NATURE OF GARBAGE COLLECTION THAT DISALLOWS HAVING TWO STRING DESCRIPTORS POINT TO THE SAME AREA IN STRING SPACE. STRING FUNCTIONS AND OPERATORS MUST PROCEED AS FOLLOWS: 1) FIGURE OUT THE LENGTH OF THEIR RESULT. 2) CALL "GETSPA" TO FIND SPACE FOR THEIR RESULT. THE ARGUMENTS TO THE FUNCTION OR OPERATOR MAY CHANGE SINCE GARBAGE COLLECTION MAY BE INVOKED. THE ONLY THING THAT CAN BE SAVED DURING THE CALL TO "GETSPA" IS A POINTER TO THE DESCRIPTORS OF THE ARGUMENTS. 3) CONSTRUCT THE RESULT DESCRIPTOR IN "DSCTMP". "GETSPA" RETURNS THE LOCATION OF THE AVAILABLE SPACE. 4) CREATE THE NEW VALUE BY COPYING PARTS OF THE ARGUMENTS OR WHATEVER. 5) FREE UP THE ARGUMENTS BY CALLING "FRETMP". 6) JUMP TO "PUTNEW" TO GET THE DESCRIPTOR IN "DSCTMP" TRANSFERRED INTO A NEW STRING TEMPORARY. THE REASON FOR STRING TEMPORARIES IS THAT GARBAGE COLLECTION HAS TO KNOW ABOUT ALL ACTIVE STRING DESCRIPTORS SO IT KNOWS WHAT IS AND ISN'T IN USE. STRING TEMPORARIES ARE USED TO STORE THE DESCRIPTORS OF STRING EXPRESSIONS. INSTEAD OF HAVING AN ACTUAL VALUE STORED IN THE FAC, AND HAVING THE VALUE OF A TEMPORARY RESULT BEING SAVED ON THE STACK, AS HAPPENS WITH NUMERIC VARIABLES, STRINGS HAVE THE POINTER TO A STRING DESCRIPTOR STORED IN THE FAC, AND IT IS THIS POINTER THAT GETS SAVED ON THE STACK BY FORMULA EVALUATION. STRING FUNCTIONS CANNOT FREE THEIR ARGUMENTS UP RIGHT AWAY SINCE "GETSPA" MAY FORCE GARBAGE COLLECTION AND THE ARGUMENT STRINGS MAY BE OVER-WRITTEN SINCE GARBAGE COLLECTION WILL NOT BE ABLE TO FIND AN ACTIVE POINTER TO THEM. FUNCTION AND OPERATOR RESULTS ARE BUILT IN "DSCTMP" SINCE STRING TEMPORARIES ARE ALLOCATED (PUTNEW) AND DEALLOCATED (FRETMP) IN A FIFO ORDERING (I.E. A STACK) SO THE NEW TEMPORARY CANNOT BE SET UP UNTIL THE OLD ONE(S) ARE FREED. TRYING TO BUILD A RESULT IN A TEMPORARY AFTER FREEING UP THE ARGUMENT TEMPORARIES COULD RESULT IN ONE OF THE ARGUMENT TEMPORARIES BEING OVERWRITTEN TOO SOON BY THE NEW RESULT. STRING SPACE IS ALLOCATED AT THE VERY TOP OF MEMORY. "MEMSIZ" POINTS BEYOND THE LAST LOCATION OF STRING SPACE. STRINGS ARE STORED IN HIGH LOCATIONS FIRST. WHENEVER STRING SPACE IS ALLOCATED (GETSPA). [FRETOP], WHICH IS INITIALIZED TO [MEMSIZ], IS UPDATED TO GIVE THE HIGHEST LOCATION IN STRING SPACE THAT IS NOT IN USE. THE RESULT IS THAT [FRETOP] GETS SMALLER AND SMALLER, UNTIL SOME ALLOCATION WOULD MAKE [FRETOP] LESS THAN OR EQUAL TO [STREND]. THIS MEANS STRING SPACE HAS RUN INTO THE THE ARRAYS AND THAT GARBAGE COLLECTION MUST BE CALLED. GARBAGE COLLECTION: 0. [MINPTR]=[STREND] [FRETOP]=[MEMSIZ] 1. [REMMIN]=0 2. FOR EACH STRING DESCRIPTOR (TEMPORARIES, SIMPLE STRINGS, STRING ARRAYS) IF THE STRING IS NOT NULL AND ITS POINTER IS .GT.MINPTR AND .LT.FRETOP, [MINPTR]=THIS STRING DESCRIPTOR'S POINTER, [REMMIN]=POINTER AT THIS STRING DESCRIPTOR. END. 3. IF REMMIN.NE.0 (WE FOUND AN UNCOLLECTED STRING), BLOCK TRANSFER THE STRING DATA POINTED TO IN THE STRING DESCRIPTOR POINTED TO BY "REMMIN" SO THAT THE LAST BYTE OF STRING DATA IS AT [FRETOP]. UPDATE [FRETOP] SO THAT IT POINTS TO THE LOCATION JUST BELOW THE ONE THE STRING DATA WAS MOVED INTO. UPDATE THE POINTER IN THE DESCRIPTOR SO IT POINTS TO THE NEW LOCATION OF THE STRING DATA. GO TO STEP 1. AFTER CALLING GARBAGE COLLECTION "GETSPA" AGAIN CHECKS TO SEE IF [ACCA] CHARACTERS ARE AVAILABLE BETWEEN [STREND] AND [FRETOP]; IF NOT, AN "OUT OF STRING" ERROR IS INVOKED. MATH PACKAGE THE MATH PACKAGE CONTAINS FLOATING INPUT (FIN), FLOATING OUTPUT (FOUT), FLOATING COMPARE (FCOMP) ... AND ALL THE NUMERIC OPERATORS AND FUNCTIONS. THE FORMATS, CONVENTIONS AND ENTRY POINTS ARE ALL DESCRIBED IN THE MATH PACKAGE ITSELF. INIT -- THE INITIALIZATION ROUTINE THE AMOUNT OF MEMORY, TERMINAL WIDTH, AND WHICH FUNCTIONS TO BE RETAINED ARE ASCERTAINED FROM THE USER. A ZERO IS PUT DOWN AT THE FIRST LOCATION NOT USED BY THE MATH-PACKAGE AND [TXTTAB] IS SET UP TO POINT AT THE NEXT LOCATION. THIS DETERMINES WHERE PROGRAM STORAGE WILL START. SPECIAL CHECKS ARE MADE TO MAKE SURE ALL QUESTIONS IN "INIT" ARE ANSWERED REASONABLY, SINCE ONCE "INIT" FINISHES, THE LOCATIONS IT USES ARE USED FOR PROGRAM STORAGE. THE LAST THING "INIT" DOES IS CHANGE LOCATION ZERO TO BE A JUMP TO "READY" INSTEAD OF "INIT". ONCE THIS IS DONE THERE IS NO WAY TO RESTART "INIT". HIGH LOCATIONS PAGE SUBTTL PAGE ZERO. IFN REALIO-3,< START: JMP INIT ;INITIALIZE - SETUP CERTAIN LOCATIONS ;AND DELETE FUNCTIONS IF NOT NEEDED, ;AND CHANGE THIS TO "JMP READY" ;IN CASE USER RESTARTS AT LOC ZERO. RDYJSR: JMP INIT ;CHANGED TO "JMP STROUT" BY "INIT" ;TO HANDLE ERRORS. ADRAYI: ADR(AYINT) ;STORE HERE THE ADDR OF THE ;ROUTINE TO TURN THE FAC INTO A ;TWO BYTE SIGNED INTEGER IN [Y,A] ADRGAY: ADR(GIVAYF)> ;STORE HERE THE ADDR OF THE ;ROUTINE TO CONVERT [Y,A] TO A FLOATING ;POINT NUMBER IN THE FAC. IFN ROMSW,< USRPOK: JMP FCERR> ;SET UP ORIG BY INIT. ; ; THIS IS THE "VOLATILE" STORAGE AREA AND NONE OF IT ; CAN BE KEPT IN ROM. ANY CONSTANTS IN THIS AREA CANNOT ; BE KEPT IN A ROM, BUT MUST BE LOADED IN BY THE ; PROGRAM INSTRUCTIONS IN ROM. ; ; --- GENERAL RAM ---: CHARAC: BLOCK 1 ;A DELIMITING CHARACTER. INTEGR= CHARAC ;A ONE-BYTE INTEGER FROM "QINT". ENDCHR: BLOCK 1 ;THE OTHER DELIMITING CHARACTER. COUNT: BLOCK 1 ;A GENERAL COUNTER. ; --- FLAGS ---: DIMFLG: BLOCK 1 ;IN GETTING A POINTER TO A VARIABLE ;IT IS IMPORTANT TO REMEMBER WHETHER IT ;IS BEING DONE FOR "DIM" OR NOT. ;DIMFLG AND VALTYP MUST BE ;CONSECUTIVE LOCATIONS. KIMY= DIMFLG ;PLACE TO PRESERVE Y DURING OUT. VALTYP: BLOCK 1 ;THE TYPE INDICATOR. ;0=NUMERIC 1=STRING. IFN INTPRC,< INTFLG: BLOCK 1> ;TELLS IF INTEGER. DORES: BLOCK 1 ;WHETHER CAN OR CAN'T CRUNCH RES'D WORDS. ;TURNED ON WHEN "DATA" ;BEING SCANNED BY CRUNCH SO UNQUOTED ;STRINGS WON'T BE CRUNCHED. GARBFL= DORES ;WHETHER TO DO GARBAGE COLLECTION. SUBFLG: BLOCK 1 ;FLAG WHETHER SUB'D VARIABLE ALLOWED. ;"FOR" AND USER-DEFINED FUNCTION ;POINTER FETCHING TURN ;THIS ON BEFORE CALLING "PTRGET" ;SO ARRAYS WON'T BE DETECTED. ;"STKINI" AND "PTRGET" CLEAR IT. ;ALSO DISALLOWS INTEGERS THERE. INPFLG: BLOCK 1 ;FLAGS WHETHER WE ARE DOING "INPUT" ;OR "READ". TANSGN: BLOCK 1 ;USED IN DETERMINING SIGN OF TANGENT. IFN REALIO,< CNTWFL: BLOCK 1> ;SUPPRESS OUTPUT FLAG. ;NON-ZERO MEANS SUPPRESS. ;RESET BY "INPUT", READY AND ERRORS. ;COMPLEMENTED BY INPUT OF ^O. IFE REALIO-4,<ORG 80> ;ROOM FOR APPLE PAGE 0 STUFF. ; --- RAM DEALING WITH TERMINAL HANDLING ---: IFN EXTIO,< CHANNL: BLOCK 1> ;HOLDS CHANNEL NUMBER. IFN NULCMD,< NULCNT: 0> ;NUMBER OF NULLS TO PRINT. IFN REALIO-3,< TRMPOS: BLOCK 1> ;POSITION OF TERMINAL CARRIAGE. LINWID: LINLEN ;LENGTH OF LINE (WIDTH). NCMWID: NCMPOS ;POSITION BEYOND WHICH THERE ARE ;NO MORE FIELDS. LINNUM: 0 ;LOCATION TO STORE LINE NUMBER BEFORE BUF ;SO THAT "BLTUC" CAN STORE IT ALL AWAY AT ONCE. 44 ;A COMMA (PRELOAD OR FROM ROM) ;USED BY INPUT STATEMENT SINCE THE ;DATA POINTER ALWAYS STARTS ON A ;COMMA OR TERMINATOR. IFE BUFPAG,< BUF: BLOCK BUFLEN> ;TYPE IN STORED HERE. ;DIRECT STATEMENTS EXECUTE OUT OF ;HERE. REMEMBER "INPUT" SMASHES BUF. ;MUST BE ON PAGE ZERO ;OR ASSIGNMENT OF STRING ;VALUES IN DIRECT STATEMENTS WON'T COPY ;INTO STRING SPACE -- WHICH IT MUST. ;N.B. TWO NONZERO BYTES MUST PRECEDE "BUFLNM". ; --- STORAGE FOR TEMPORARY THINGS ---: TEMPPT: BLOCK 1 ;POINTER AT FIRST FREE TEMP DESCRIPTOR. ;INITIALIZED TO POINT TO TEMPST. LASTPT: BLOCK 2 ;POINTER TO LAST-USED STRING TEMPORARY. TEMPST: BLOCK STRSIZNUMTMP ;STORAGE FOR NUMTMP TEMP DESCRIPTORS. INDEX1: BLOCK 2 ;INDEXES. INDEX= INDEX1 INDEX2: BLOCK 2 RESHO: BLOCK 1 ;RESULT OF MULTIPLIER AND DIVIDER. IFN ADDPRC,< RESMOH: BLOCK 1> ;ONE MORE BYTE. RESMO: BLOCK 1 RESLO: BLOCK 1 ADDEND= RESMO ;TEMPORARY USED BY "UMULT". 0 ;OVERFLOW FOR RES. ; --- POINTERS INTO DYNAMIC DATA STRUCTURES ---; TXTTAB: BLOCK 2 ;POINTER TO BEGINNING OF TEXT. ;DOESN'T CHANGE AFTER BEING ;SETUP BY "INIT". VARTAB: BLOCK 2 ;POINTER TO START OF SIMPLE ;VARIABLE SPACE. ;UPDATED WHENEVER THE SIZE OF THE ;PROGRAM CHANGES, SET TO [TXTTAB] ;BY "SCRATCH" ("NEW"). ARYTAB: BLOCK 2 ;POINTER TO BEGINNING OF ARRAY ;TABLE. ;INCREMENTED BY 6 WHENEVER ;A NEW SIMPLE VARIABLE IS FOUND, AND ;SET TO [VARTAB] BY "CLEARC". STREND: BLOCK 2 ;END OF STORAGE IN USE. ;INCREASED WHENEVER A NEW ARRAY ;OR SIMPLE VARIABLE IS ENCOUNTERED. ;SET TO [VARTAB] BY "CLEARC". FRETOP: BLOCK 2 ;TOP OF STRING FREE SPACE. FRESPC: BLOCK 2 ;POINTER TO NEW STRING. MEMSIZ: BLOCK 2 ;HIGHEST LOCATION IN MEMORY. ; --- LINE NUMBERS AND TEXTUAL POINTERS ---: CURLIN: BLOCK 2 ;CURRENT LINE #. ;SET TO 0,255 FOR DIRECT STATEMENTS. OLDLIN: BLOCK 2 ;OLD LINE NUMBER (SETUP BY ^C,"STOP" ;OR "END" IN A PROGRAM). POKER= LINNUM ;SET UP LOCATION USED BY POKE. ;TEMPORARY FOR INPUT AND READ CODE OLDTXT: BLOCK 2 ;OLD TEXT POINTER. ;POINTS AT STATEMENT TO BE EXEC'D NEXT. DATLIN: BLOCK 2 ;DATA LINE # -- REMEMBER FOR ERRORS. DATPTR: BLOCK 2 ;POINTER TO DATA. INITIALIZED TO POINT ;AT THE ZERO IN FRONT OF [TXTTAB] ;BY "RESTORE" WHICH IS CALLED BY "CLEARC". ;UPDATED BY EXECUTION OF A "READ". INPPTR: BLOCK 2 ;THIS REMEMBERS WHERE INPUT IS COMING FROM. ; --- STUFF USED IN EVALUATIONS ---: VARNAM: BLOCK 2 ;VARIABLE'S NAME IS STORED HERE. VARPNT: BLOCK 2 ;POINTER TO VARIABLE IN MEMORY. FDECPT= VARPNT ;POINTER INTO POWER OF TENS OF "FOUT". FORPNT: BLOCK 2 ;A VARIABLE'S POINTER FOR "FOR" LOOPS ;AND "LET" STATEMENTS. LSTPNT= FORPNT ;PNTR TO LIST STRING. ANDMSK= FORPNT ;THE MASK USED BY WAIT FOR ANDING. EORMSK= FORPNT+1 ;THE MASK FOR EORING IN WAIT. OPPTR: BLOCK 2 ;POINTER TO CURRENT OP'S ENTRY IN "OPTAB". VARTXT= OPPTR ;POINTER INTO LIST OF VARIABLES. OPMASK: BLOCK 1 ;MASK CREATED BY CURRENT OPERATOR. DOMASK=TANSGN ;MASK IN USE BY RELATION OPERATIONS. DEFPNT: BLOCK 2 ;POINTER USED IN FUNCTION DEFINITION. GRBPNT= DEFPNT ;ANOTHER USED IN GARBAGE COLLECTION. DSCPNT: BLOCK 2 ;POINTER TO A STRING DESCRIPTOR. IFN ADDPRC,<BLOCK 1> ;FOR TEMPF3. FOUR6: EXP STRSIZ ;VARIABLE CONSTANT USED BY GARB COLLECT. ; --- ET CETERA ---: JMPER: JMP 60000 SIZE= JMPER+1 OLDOV= JMPER+2 ;THE OLD OVERFLOW. TEMPF3= DEFPNT ;A THIRD FAC TEMPORARY (4 BYTES). TEMPF1: IFN ADDPRC,<0> ;FOR TEMPF1S EXTRA BYTE. HIGHDS: BLOCK 2 ;DESINATION OF HIGHEST ELEMENT IN BLT. HIGHTR: BLOCK 2 ;SOURCE OF HIGHEST ELEMENT TO MOVE. TEMPF2: IFN ADDPRC,<0> ;FOR TEMPF2S EXTRA BYTE. LOWDS: BLOCK 2 ;LOCATION OF LAST BYTE TRANSFERRED INTO. LOWTR: BLOCK 2 ;LAST THING TO MOVE IN BLT. ARYPNT= HIGHDS ;A POINTER USED IN ARRAY BUILDING. GRBTOP= LOWTR ;A POINTER USED IN GARBAGE COLLECTION. DECCNT= LOWDS ;NUMBER OF PLACES BEFORE DECIMAL POINT. TENEXP= LOWDS+1 ;HAS A DPT BEEN INPUT? DPTFLG= LOWTR ;BASE TEN EXPONENT. EXPSGN= LOWTR+1 ;SIGN OF BASE TEN EXPONENT. ; --- THE FLOATING ACCUMULATOR ---: FAC: FACEXP: 0 FACHO: 0 ;MOST SIGNIFICANT BYTE OF MANTISSA. IFN ADDPRC,< FACMOH: 0> ;ONE MORE. FACMO: 0 ;MIDDLE ORDER OF MANTISSA. FACLO: 0 ;LEAST SIG BYTE OF MANTISSA. FACSGN: 0 ;SIGN OF FAC (0 OR -1) WHEN UNPACKED. SGNFLG: 0 ;SIGN OF FAC IS PRESERVED BERE BY "FIN". DEGREE= SGNFLG ;A COUNT USED BY POLYNOMIALS. DSCTMP= FAC ;THIS IS WHERE TEMP DESCS ARE BUILT. INDICE= FACMO ;INDICE IS SET UP HERE BY "QINT". BITS: 0 ;SOMETHING FOR "SHIFTR" TO USE. ; --- THE FLOATING ARGUMENT (UNPACKED) ---: ARGEXP: 0 ARGHO: 0 IFN ADDPRC,<ARGMOH: 0> ARGMO: 0 ARGLO: 0 ARGSGN: 0 ARISGN: 0 ;A SIGN REFLECTING THE RESULT. FACOV: 0 ;OVERFLOW BYTE OF THE FAC. STRNG1= ARISGN ;POINTER TO A STRING OR DESCRIPTOR. FBUFPT: BLOCK 2 ;POINTER INTO FBUFFR USED BY FOUT. BUFPTR= FBUFPT ;POINTER TO BUF USED BY "CRUNCH". STRNG2= FBUFPT ;POINTER TO STRING OR DESC. POLYPT= FBUFPT ;POINTER INTO POLYNOMIAL COEFFICIENTS. CURTOL= FBUFPT ;ABSOLUTE LINEAR INDEX IS FORMED HERE. PAGE SUBTTL RAM CODE. ; THIS CODE GETS CHANGED THROUGHOUT EXECUTION. ; IT IS MADE TO BE FAST THIS WAY. ; ALSO, [X] AND [Y] ARE NOT DISTURBED ; ; "CHRGET" USING [TXTPTR] AS THE CURRENT TEXT PNTR ; FETCHES A NEW CHARACTER INTO ACCA AFTER INCREMENTING [TXTPTR] ; AND SETS CONDITION CODES ACCORDING TO WHAT'S IN ACCA. ; NOT C= NUMERIC ("0" THRU "9") ; Z= ":" OR END-OF-LINE (A NULL) ; ; [ACCA] = NEW CHAR. ; [TXTPTR]=[TXTPTR]+1 ; ; THE FOLLOWING EXISTS IN ROM IF ROM EXISTS AND IS LOADED ; DOWN HERE BY INIT. OTHERWISE IT IS JUST LOADED INTO THIS ; RAM LIKE ALL THE REST OF RAM IS LOADED. ; CHRGET: INC CHRGET+7 ;INCREMENT THE WHOLE TXTPTR. BNE CHRGOT INC CHRGET+8 CHRGOT: LDA 60000 ;A LOAD WITH AN EXT ADDR. TXTPTR= CHRGOT+1 CMPI " " ;SKIP SPACES. BEQ CHRGET QNUM: CMPI ":" ;IS IT A ":"? BCS CHRRTS ;IT IS .GE. ":" SEC SBCI "0" ;ALL CHARS .GT. "9" HAVE RET'D SO SEC SBCI 256-"0" ;SEE IF NUMERIC. ;TURN CARRY ON IF NUMERIC. ;ALSO, SETZ IF NULL. CHRRTS: RTS ;RETURN TO CALLER. RNDX: 128 ;LOADED OR FROM ROM. 79 ;THE INITIAL RANDOM NUMBER. 199 82 IFN ADDPRC,<89> ;ONE MORE BYTE. ORG 255 ;PAGE 1 STUFF COMING UP. LOFBUF: BLOCK 1 ;THE LOW FAC BUFFER. COPYABLE. ;--- PAGE ZERO/ONE BOUNDARY ---. ;MUST HAVE 13 CONTIGUOUS BYTES. FBUFFR: BLOCK 3ADDPRC+13 ;BUFFER FOR "FOUT". ;ON PAGE 1 SO THAT STRING IS NOT COPIED. ;STACK IS LOCATED HERE. IE FROM THE END OF FBUFFR TO STKEND. PAGE SUBTTL DISPATCH TABLES, RESERVED WORDS, AND ERROR TEXTS. ORG ROMLOC STMDSP: ADR(END-1) ADR(FOR-1) ADR(NEXT-1) ADR(DATA-1) IFN EXTIO,< ADR(INPUTN-1)> ADR(INPUT-1) ADR(DIM-1) ADR(READ-1) ADR(LET-1) ADR(GOTO-1) ADR(RUN-1) ADR(IF-1) ADR(RESTORE-1) ADR(GOSUB-1) ADR(RETURN-1) ADR(REM-1) ADR(STOP-1) ADR(ONGOTO-1) IFN NULCMD,< ADR(NULL-1)> ADR(FNWAIT-1) IFN DISKO,< IFE REALIO-3,< ADR(CQLOAD-1) ADR(CQSAVE-1) ADR(CQVERF-1)> IFN REALIO,< IFN REALIO-2,< IFN REALIO-3,< IFN REALIO-5,< ADR(LOAD-1) ADR(SAVE-1)>>>> IFN REALIO-1,< IFN REALIO-3,< IFN REALIO-4,< ADR(511) ;ADDRESS OF LOAD ADR(511)>>>> ;ADDRESS OF SAVE ADR(DEF-1) ADR(POKE-1) IFN EXTIO,< ADR(PRINTN-1)> ADR(PRINT-1) ADR(CONT-1) IFE REALIO,< ADR(DDT-1)> ADR(LIST-1) ADR(CLEAR-1) IFN EXTIO,< ADR(CMD-1) ADR(CQSYS-1) ADR(CQOPEN-1) ADR(CQCLOS-1)> IFN GETCMD,< ADR(GET-1)> ;FILL W/ GET ADDR. ADR(SCRATH-1) FUNDSP: ADR(SGN) ADR(INT) ADR(ABS) IFE ROMSW,< USRLOC: ADR(FCERR)> ;INITIALLY NO USER ROUTINE. IFN ROMSW,< USRLOC: ADR(USRPOK)> ADR(FRE) ADR(POS) ADR(SQR) ADR(RND) ADR(LOG) ADR(EXP) IFN KIMROM,< REPEAT 4,< ADR(FCERR)>> IFE KIMROM,< COSFIX: ADR(COS) SINFIX: ADR(SIN) TANFIX: ADR(TAN) ATNFIX: ADR(ATN)> ADR(PEEK) ADR(LEN) ADR(STR) ADR(VAL) ADR(ASC) ADR(CHR) ADR(LEFT) ADR(RIGHT) ADR(MID) OPTAB: 121 ADR(FADDT-1) 121 ADR(FSUBT-1) 123 ADR(FMULTT-1) 123 ADR(FDIVT-1) 127 ADR(FPWRT-1) 80 ADR(ANDOP-1) 70 ADR(OROP-1) NEGTAB: 125 ADR(NEGOP-1) NOTTAB: 90 ADR(NOTOP-1) PTDORL: 100 ;PRECEDENCE. ADR (DOREL-1) ;OPERATOR ADDRESS. ; ; TOKENS FOR RESERVED WORDS ALWAYS HAVE THE MOST ; SIGNIFICANT BIT ON. ; THE LIST OF RESERVED WORDS: ; Q=128-1 DEFINE DCI(A),<Q=Q+1 DC(A)> RESLST: DCI"END" ENDTK==Q DCI"FOR" FORTK==Q DCI"NEXT" DCI"DATA" DATATK==Q IFN EXTIO,< DCI"INPUT#"> DCI"INPUT" DCI"DIM" DCI"READ" DCI"LET" DCI"GOTO" GOTOTK==Q DCI"RUN" DCI"IF" DCI"RESTORE" DCI"GOSUB" GOSUTK=Q DCI"RETURN" DCI"REM" REMTK=Q DCI"STOP" DCI"ON" IFN NULCMD,< DCI"NULL"> DCI"WAIT" IFN DISKO,< DCI"LOAD" DCI"SAVE" IFE REALIO-3,< DCI"VERIFY">> DCI"DEF" DCI"POKE" IFN EXTIO,< DCI"PRINT#"> DCI"PRINT" PRINTK==Q DCI"CONT" IFE REALIO,< DCI"DDT"> DCI"LIST" IFN REALIO-3,< DCI"CLEAR"> IFE REALIO-3,< DCI"CLR"> IFN EXTIO,< DCI"CMD" DCI"SYS" DCI"OPEN" DCI"CLOSE"> IFN GETCMD,< DCI"GET"> DCI"NEW" SCRATK=Q ; END OF COMMAND LIST. "T" "A" "B" "("+128 Q=Q+1 TABTK=Q DCI"TO" TOTK==Q DCI"FN" FNTK==Q "S" "P" "C" "("+128 ;MACRO DOESNT LIKE ('S IN ARGUMENTS. Q=Q+1 SPCTK==Q DCI"THEN" THENTK=Q DCI"NOT" NOTTK==Q DCI"STEP" STEPTK=Q DCI"+" PLUSTK=Q DCI"-" MINUTK=Q DCI"" DCI"/" DCI"^" DCI"AND" DCI"OR" 190 ;A GREATER THAN SIGN Q=Q+1 GREATK=Q DCI"=" EQULTK=Q 188 Q=Q+1 ;A LESS THAN SIGN LESSTK=Q ; ; NOTE DANGER OF ONE RESERVED WORD BEING A PART ; OF ANOTHER: ; IE . . IF 2 GREATER THAN F OR T=5 THEN... ; WILL NOT WORK!!! SINCE "FOR" WILL BE CRUNCHED!! ; IN ANY CASE MAKE SURE THE SMALLER WORD APPEARS ; SECOND IN THE RESERVED WORD TABLE ("INP" AND "INPUT") ; ANOTHER EXAMPLE: IF T OR Q THEN ... "TO" IS CRUNCHED ; DCI"SGN" ONEFUN=Q DCI"INT" DCI"ABS" DCI"USR" DCI"FRE" DCI"POS" DCI"SQR" DCI"RND" DCI"LOG" DCI"EXP" DCI"COS" DCI"SIN" DCI"TAN" DCI"ATN" DCI"PEEK" DCI"LEN" DCI"STR$" DCI"VAL" DCI"ASC" DCI"CHR$" LASNUM==Q ;NUMBER OF LAST FUNCTION ;THAT TAKES ONE ARG DCI"LEFT$" DCI"RIGHT$" DCI"MID$" DCI"GO" GOTK==Q 0 ;MARKS END OF RESERVED WORD LIST IFE LNGERR,< Q=0-2 DEFINE DCE(X),<Q=Q+2 DC(X)> ERRTAB: DCE"NF" ERRNF==Q ;NEXT WITHOUT FOR. DCE"SN" ERRSN==Q ;SYNTAX DCE"RG" ERRRG==Q ;RETURN WITHOUT GOSUB. DCE"OD" ERROD==Q ;OUT OF DATA. DCE"FC" ERRFC==Q ;ILLEGAL QUANTITY. DCE"OV" ERROV==Q ;OVERFLOW. DCE"OM" ERROM==Q ;OUT OF MEMORY. DCE"US" ERRUS==Q ;UNDEFINED STATEMENT. DCE"BS" ERRBS==Q ;BAD SUBSCRIPT. DCE"DD" ERRDD==Q ;REDIMENSIONED ARRAY. DCE"/0" ERRDV0==Q ;DIVISION BY ZERO. DCE"ID" ERRID==Q ;ILLEGAL DIRECT. DCE"TM" ERRTM==Q ;TYPE MISMATCH. DCE"LS" ERRLS==Q ;STRING TOO LONG. IFN EXTIO,< DCE"FD" ;FILE DATA. ERRBD==Q> DCE"ST" ERRST==Q ;STRING FORMULA TOO COMPLEX. DCE"CN" ERRCN==Q ;CAN'T CONTINUE. DCE"UF" ERRUF==Q> ;UNDEFINED FUNCTION. IFN LNGERR,< Q=0 ; NOTE: THIS ERROR COUNT TECHNIQUE WILL NOT WORK IF THERE ARE MORE ; THAN 256 CHARACTERS OF ERROR MESSAGES ERRTAB: DC"NEXT WITHOUT FOR" ERRNF==Q Q=Q+16 DC"SYNTAX" ERRSN==Q Q=Q+6 DC"RETURN WITHOUT GOSUB" ERRRG==Q Q=Q+20 DC"OUT OF DATA" ERROD==Q Q=Q+11 DC"ILLEGAL QUANTITY" ERRFC==Q Q=Q+16 DC"OVERFLOW" ERROV==Q Q=Q+8 DC"OUT OF MEMORY" ERROM==Q Q=Q+13 DC"UNDEF'D STATEMENT" ERRUS==Q Q=Q+17 DC"BAD SUBSCRIPT" ERRBS==Q Q=Q+13 DC"REDIM'D ARRAY" ERRDD==Q Q=Q+13 DC"DIVISION BY ZERO" ERRDV0==Q Q=Q+16 DC"ILLEGAL DIRECT" ERRID==Q Q=Q+14 DC"TYPE MISMATCH" ERRTM==Q Q=Q+13 DC"STRING TOO LONG" ERRLS==Q Q=Q+15 IFN EXTIO,< DC"FILE DATA" ERRBD==Q Q=Q+9> DC"FORMULA TOO COMPLEX" ERRST==Q Q=Q+19 DC"CAN'T CONTINUE" ERRCN==Q Q=Q+14 DC"UNDEF'D FUNCTION" ERRUF==Q> ; ; NEEDED FOR MESSAGES IN ALL VERSIONS. ; ERR: DT" ERROR" 0 INTXT: DT" IN " 0 REDDY: ACRLF IFE REALIO-3,< DT"READY."> IFN REALIO-3,< DT"OK"> ACRLF 0 BRKTXT: ACRLF DT"BREAK" 0 PAGE SUBTTL GENERAL STORAGE MANAGEMENT ROUTINES. ; ; FIND A "FOR" ENTRY ON THE STACK VIA "VARPNT". ; FORSIZ==2ADDPRC+16 FNDFOR: TSX ;LOAD XREG WITH STK PNTR. REPEAT 4,<INX> ;IGNORE ADR(NEWSTT) AND RTS ADDR. FFLOOP: LDA 257,X ;GET STACK ENTRY. CMPI FORTK ;IS IT A "FOR" TOKEN? BNE FFRTS ;NO, NO "FOR" LOOPS WITH THIS PNTR. LDA FORPNT+1 ;GET HIGH. BNE CMPFOR LDA 258,X ;PNTR IS ZERO, SO ASSUME THIS ONE. STA FORPNT LDA 259,X STA FORPNT+1 CMPFOR: CMP 259,X BNE ADDFRS ;NOT THIS ONE. LDA FORPNT ;GET DOWN. CMP 258,X BEQ FFRTS ;WE GOT IT! WE GOT IT! ADDFRS: TXA CLC ;ADD 16 TO X. ADCI FORSIZ TAX ;RESULT BACK INTO X. BNE FFLOOP FFRTS: RTS ;RETURN TO CALLER. ; ; THIS IS THE BLOCK TRANSFER ROUTINE. ; IT MAKES SPACE BY SHOVING EVERYTHING FORWARD. ; ; ON ENTRY: ; [Y,A]=[HIGHDS] (FOR REASON). ; [HIGHDS]= DESTINATION OF [HIGH ADDRESS]. ; [LOWTR]= LOWEST ADDR TO BE TRANSFERRED. ; [HIGHTR]= HIGHEST ADDR TO BE TRANSFERRED. ; ; A CHECK IS MADE TO ASCERTAIN THAT A REASONABLE ; AMOUNT OF SPACE REMAINS BETWEEN THE BOTTOM ; OF THE STRINGS AND THE HIGHEST LOCATION TRANSFERRED INTO. ; ; ON EXIT: ; [LOWTR] ARE UNCHANGED. ; [HIGHTR]=[LOWTR]-200 OCTAL. ; [HIGHDS]=LOWEST ADDR TRANSFERRED INTO MINUS 200 OCTAL. ; BLTU: JSR REASON ;ASCERTAIN THAT STRING SPACE WON'T ;BE OVERRUN. STWD STREND BLTUC: SEC ;PREPARE TO SUBTRACT. LDA HIGHTR SBC LOWTR ;COMPUTE NUMBER OF THINGS TO MOVE. STA INDEX ;SAVE FOR LATER. TAY LDA HIGHTR+1 SBC LOWTR+1 TAX ;PUT IT IN A COUNTER REGISTER. INX ;SO THAT COUNTER ALGORITHM WORKS. TYA ;SEE IF LOW PART OF COUNT IS ZERO. BEQ DECBLT ;YES, GO START MOVING BLOCKS. LDA HIGHTR ;NO, MUST MODIFY BASE ADDR. SEC SBC INDEX ;BORROW IS OFF SINCE [HIGHTR].GT.[LOWTR]. STA HIGHTR ;SAVE MODIFIED BASE ADDR. BCS BLT1 ;IF NO BORROW, GO SHOVE IT. DEC HIGHTR+1 ;BORROW IMPLIES SUB 1 FROM HIGH ORDER. SEC BLT1: LDA HIGHDS ;MOD BASE OF DEST ADDR. SBC INDEX STA HIGHDS BCS MOREN1 ;NO BORROW. DEC HIGHDS+1 ;DECREMENT HIGH ORDER BYTE. BCC MOREN1 ;ALWAYS SKIP. BLTLP: LDADY HIGHTR ;FETCH BYTE TO MOVE STADY HIGHDS ;MOVE IT IN, MOVE IT OUT. MOREN1: DEY BNE BLTLP LDADY HIGHTR ;MOVE LAST OF THE BLOCK. STADY HIGHDS DECBLT: DEC HIGHTR+1 DEC HIGHDS+1 ;START ON NEW BLOCKS. DEX BNE MOREN1 RTS ;RETURN TO CALLER. ; ; THIS ROUTINE IS USED TO ASCERTAIN THAT A GIVEN ; NUMBER OF LOCS REMAIN AVAILABLE FOR THE STACK. ; THE CALL IS: ; LDAI NUMBER OF 2-BYTE ENTRIES NEEDED. ; JSR GETSTK ; ; THIS ROUTINE MUST BE CALLED BY ANY ROUTINE WHICH PUTS ; AN ARBITRARY AMOUNT OF STUFF ON THE STACK, ; I.E., ANY RECURSIVE ROUTINE LIKE "FRMEVL". ; IT IS ALSO CALLED BY ROUTINES SUCH AS "GOSUB" AND "FOR" ; WHICH MAKE PERMANENT ENTRIES ON THE STACK. ; ; ROUTINES WHICH MERELY USE AND FREE UP THE GUARANTEED ; NUMLEV LOCATIONS NEED NOT CALL THIS. ; ; ; ON EXIT: ; [A] AND [X] HAVE BEEN MODIFIED. ; GETSTK: ASL A, ;MULT [A] BY 2. NB, CLEARS C BIT. ADCI 2NUMLEV+<3ADDPRC>+13 ;MAKE SURE 2NUMLEV+13 LOCS ;(13 BECAUSE OF FBUFFR) BCS OMERR ;WILL REMAIN IN STACK. STA INDEX TSX ;GET STACKED. CPX INDEX ;COMPARE. BCC OMERR ;IF STACK.LE.INDEX1, OM. RTS ; ; [Y,A] IS A CERTAIN ADDRESS. "REASON" MAKES SURE ; IT IS LESS THAN [FRETOP]. ; REASON: CPY FRETOP+1 BCC REARTS BNE TRYMOR ;GO GARB COLLECT. CMP FRETOP BCC REARTS TRYMOR: PHA LDXI 8+ADDPRC ;IF TEMPF2 HAS ZERO IN BETWEEN. TYA REASAV: PHA LDA HIGHDS-1,X ;SAVE HIGHDS ON STACK. DEX BPL REASAV ;PUT 8 OF THEM ON STK. JSR GARBA2 ;GO GARB COLLECT. LDXI 256-8-ADDPRC REASTO: PLA STA HIGHDS+8+ADDPRC,X ;RESTORE AFTER GARB COLLECT. INX BMI REASTO PLA TAY PLA ;RESTORE A AND Y. CPY FRETOP+1 ;COMPARE HIGHS BCC REARTS BNE OMERR ;HIGHER IS BAD. CMP FRETOP ;AND THE LOWS. BCS OMERR REARTS: RTS PAGE SUBTTL ERROR HANDLER, READY, TERMINAL INPUT, COMPACTIFY, NEW, REINIT. OMERR: LDXI ERROM ERROR: IFN REALIO,< LSR CNTWFL> ;FORCE OUTPUT. IFN EXTIO,< LDA CHANNL ;CLOSE NON-TERMINAL CHANNEL. BEQ ERRCRD JSR CQCCHN ;CLOSE IT. LDAI 0 STA CHANNL> ERRCRD: JSR CRDO ;OUTPUT CRLF. JSR OUTQST ;PRINT A QUESTION MARK IFE LNGERR,< LDA ERRTAB,X, ;GET FIRST CHR OF ERR MSG. JSR OUTDO ;OUTPUT IT. LDA ERRTAB+1,X, ;GET SECOND CHR. JSR OUTDO> ;OUTPUT IT. IFN LNGERR,< GETERR: LDA ERRTAB,X PHA ANDI 127 ;GET RID OF HIGH BIT. JSR OUTDO ;OUTPUT IT. INX PLA ;LAST CHAR OF MESSAGE? BPL GETERR> ;NO. GO GET NEXT AND OUTPUT IT. TYPERR: JSR STKINI ;RESET THE STACK AND FLAGS. LDWDI ERR ;GET PNTR TO " ERROR". ERRFIN: JSR STROUT ;OUTPUT IT. LDY CURLIN+1 INY ;WAS NUMBER 64000? BEQ READY ;YES, DON'T TYPE LINE NUMBER. JSR INPRT READY: IFN REALIO,< LSR CNTWFL> ;TURN OUTPUT BACK ON IF SUPRESSED LDWDI REDDY ;SAY "OK". IFN REALIO-3,< JSR RDYJSR> ;OR GO TO INIT IF INIT ERROR. IFE REALIO-3,< JSR STROUT> ;NO INIT ERRORS POSSIBLE. MAIN: JSR INLIN ;GET A LINE FROM TERMINAL. STXY TXTPTR JSR CHRGET TAX ;SET ZERO FLAG BASED ON [A] ;THIS DISTINGUISHES ":" AND 0 BEQ MAIN ;IF BLANK LINE, GET ANOTHER. LDXI 255 ;SET DIRECT LINE NUMBER. STX CURLIN+1 BCC MAIN1 ;IS A LINE NUMBER. NOT DIRECT. JSR CRUNCH ;COMPACTIFY. JMP GONE ;EXECUTE IT. MAIN1: JSR LINGET ;READ LINE NUMBER INTO "LINNUM". JSR CRUNCH STY COUNT ;RETAIN CHARACTER COUNT. JSR FNDLIN BCC NODEL ;NO MATCH, SO DON'T DELETE. LDYI 1 LDADY LOWTR STA INDEX1+1 LDA VARTAB STA INDEX1 LDA LOWTR+1 ;SET TRANSFER TO. STA INDEX2+1 LDA LOWTR DEY SBCDY LOWTR ;COMPUTE NEGATIVE LENGTH. CLC ADC VARTAB ;COMPUTE NEW VARTAB. STA VARTAB STA INDEX2 ;SET LOW OF TRANS TO. LDA VARTAB+1 ADCI 255 STA VARTAB+1 ;COMPUTE HIGH OF VARTAB. SBC LOWTR+1 ;COMPUTE NUMBER OF BLOCKS TO MOVE. TAX SEC LDA LOWTR SBC VARTAB ;COMPUTE OFFSET. TAY BCS QDECT1 ;IF VARTAB.LE.LOWTR, INX ;DECR DUE TO CARRY, AND DEC INDEX2+1 ;DECREMENT STORE SO CARRY WORKS. QDECT1: CLC ADC INDEX1 BCC MLOOP DEC INDEX1+1 CLC ;FOR LATER ADCQ MLOOP: LDADY INDEX1 STADY INDEX2 INY BNE MLOOP ;BLOCK DONE? INC INDEX1+1 INC INDEX2+1 DEX BNE MLOOP ;DO ANOTHER BLOCK. ALWAYS. NODEL: JSR RUNC ;RESET ALL VARIABLE INFO SO GARBAGE ;COLLECTION CAUSED BY REASON WILL WORK JSR LNKPRG ;FIX UP THE LINKS LDA BUF ;SEE IF ANYTHNG THERE BEQ MAIN CLC LDA VARTAB STA HIGHTR ;SETUP HIGHTR. ADC COUNT ;ADD LENGTH OF LINE TO INSERT. STA HIGHDS ;THIS GIVES DEST ADDR. LDY VARTAB+1 STY HIGHTR+1 ;SAME FOR HIGH ORDERS. BCC NODELC INY NODELC: STY HIGHDS+1 JSR BLTU IFN BUFPAG,< LDWD LINNUM ;POSITION THE BINARY LINE NUMBER STWD BUF-2> ;IN FRONT OF BUF LDWD STREND STWD VARTAB LDY COUNT DEY STOLOP: LDA BUF-4,Y STADY LOWTR DEY BPL STOLOP FINI: JSR RUNC ;DO CLEAR & SET UP STACK. ;AND SET [TXTPTR] TO [TXTTAB]-1. JSR LNKPRG ;FIX UP PROGRAM LINKS JMP MAIN LNKPRG: LDWD TXTTAB ;SET [INDEX] TO [TXTTAB]. STWD INDEX CLC ; ; CHEAD GOES THROUGH PROGRAM STORAGE AND FIXES ; UP ALL THE LINKS. THE END OF EACH LINE IS FOUND ; BY SEARCHING FOR THE ZERO AT THE END. ; THE DOUBLE ZERO LINK IS USED TO DETECT THE END OF THE PROGRAM. ; CHEAD: LDYI 1 LDADY INDEX ;ARRIVED AT DOUBLE ZEROES? BEQ LNKRTS LDYI 4 CZLOOP: INY ;THERE IS AT LEAST ONE BYTE. LDADY INDEX BNE CZLOOP ;NO, CONTINUE SEARCHING. INY ;GO ONE BEYOND. TYA ADC INDEX TAX LDYI 0 STADY INDEX LDA INDEX+1 ADCI 0 INY STADY INDEX STX INDEX STA INDEX+1 BCCA CHEAD ;ALWAYS BRANCHES. LNKRTS: RTS ; ; THIS IS THE LINE INPUT ROUTINE. ; IT READS CHARACTERS INTO BUF USING BACKARROW (UNDERSCORE, OR ; SHIFT O) AS THE DELETE CHARACTER AND @ AS THE ; LINE DELETE CHARACTER. IF MORE THAN BUFLEN CHARACTERS ; ARE TYPED, NO ECHOING IS DONE UNTIL A BACKARROW OR @ OR CR ; IS TYPED. CONTROL-G WILL BE TYPED FOR EACH EXTRA CHARACTER. ; THE ROUTINE IS ENTERED AT INLIN. ; IFE REALIO-4,< INLIN: LDXI 128 ;NO PROMPT CHARACTER STX CQPRMP JSR CQINLN ;GET A LINE ONTO PAGE 2 CPXI BUFLEN-1 BCS GDBUFS ;NOT TOO MANY CHARACTERS LDXI BUFLEN-1 GDBUFS: LDAI 0 ;PUT A ZERO AT THE END STA BUF,X TXA BEQ NOCHR LOPBHT: LDA BUF-1,X ANDI 127 STA BUF-1,X DEX BNE LOPBHT NOCHR: LDAI 0 LDXYI <BUF-1> ;POINT AT THE BEGINNING RTS> IFN REALIO-4,< IFN REALIO-3,< LINLIN: IFE REALIO-2,< JSR OUTDO> ;ECHO IT. DEX ;BACKARROW SO BACKUP PNTR AND BPL INLINC ;GET ANOTHER IF COUNT IS POSITIVE. INLINN: IFE REALIO-2,< JSR OUTDO> ;PRINT THE @ OR A SECOND BACKARROW ;IF THERE WERE TOO MANY. JSR CRDO> INLIN: LDXI 0 INLINC: JSR INCHR ;GET A CHARACTER. IFN REALIO-3,< CMPI 7 ;IS IT BOB ALBRECHT RINGING THE BELL ;FOR SCHOOL KIDS? BEQ GOODCH> CMPI 13 ;CARRIAGE RETURN? BEQ FININ1 ;YES, FINISH UP. IFN REALIO-3,< CMPI 32 ;CHECK FOR FUNNY CHARACTERS. BCC INLINC CMPI 125 ;IS IT TILDA OR DELETE? BCS INLINC ;BIG BAD ONES TOO. CMPI "@" ;LINE DELETE? BEQ INLINN ;YES. CMPI "_" ;CHARACTER DELETE? BEQ LINLIN> ;YES. GOODCH: IFN REALIO-3,< CPXI BUFLEN-1 ;LEAVE ROOM FOR NULL. ;COMMO ASSURES US NEVER MORE THAN BUFLEN. BCS OUTBEL> STA BUF,X INX IFE REALIO-2,<SKIP2> IFN REALIO-2,<BNE INLINC> IFN REALIO-3,< OUTBEL: LDAI 7 IFN REALIO,< JSR OUTDO> ;ECHO IT. BNE INLINC> ;CYCLE ALWAYS. FININ1: JMP FININL> ;GO TO FININL FAR, FAR AWAY. INCHR: IFE REALIO-3,< JSR CQINCH> ;FOR COMMODORE. IFE REALIO-2,< INCHRL: LDA ^O176000 REPEAT 4,<NOP> LSR A, BCC INCHRL LDA ^O176001 ;GET THE CHARACTER. REPEAT 4,<NOP> ANDI 127> IFE REALIO-1,< JSR ^O17132> ;1E5A FOR MOS TECH. IFE REALIO-4,< JSR CQINCH ;FD0C FOR APPLE COMPUTER. ANDI 127> IFE REALIO,< TJSR INSIM##> ;GET A CHARACTER FROM SIMULATOR IFN REALIO,< IFN EXTIO,< LDY CHANNL ;CNT-O HAS NO EFFECT IF NOT FROM TERM. BNE INCRTS> CMPI CONTW ;SUPPRESS OUTPUT CHARACTER (^W). BNE INCRTS ;NO, RETURN. PHA COM CNTWFL ;COMPLEMENT ITS STATE. PLA> INCRTS: RTS ;END OF INCHR. ; ; ALL "RESERVED" WORDS ARE TRANSLATED INTO SINGLE ; BYTES WITH THE MSB ON. THIS SAVES SPACE AND TIME ; BY ALLOWING FOR TABLE DISPATCH DURING EXECUTION. ; THEREFORE ALL STATEMENTS APPEAR TOGETHER IN THE ; RESERVED WORD LIST IN THE SAME ORDER THEY ; APPEAR IN STMDSP. ; BUFOFS=0 ;THE AMOUNT TO OFFSET THE LOW BYTE ;OF THE TEXT POINTER TO GET TO BUF ;AFTER TXTPTR HAS BEE
休闲 6 0 269天前
admin
473
原文:http://tieba.baidu.com/p/3150844258随着刀剑二的完结 有种莫名的感动。有一种坚持,叫黑白共舞。有一种守护,叫刀剑神域。有一种挚爱,叫心的温度。刀剑两年,有些东西已经根深蒂固无法改变。那些片段总是若有若无的闪现,提醒着不能复刻的感动。两年里,最悲壮的一次死亡,在第一层,迪亚布尔为了让大家能够攻略,独自一人牺牲从那以后再也没有这样一位骑士,无愧王者之名。两年里,最昂贵的一份礼物,在圣诞夜里,桐人收到幸的留言水晶,致使了桐人感到了十分后悔两年里,最伟大的一种友谊,在月夜黑猫团里,即使并不强大,但大家都为了同一个目标奋斗着两年里,最勇敢的同归于尽,雷根为了桐人能够攻略世界树寻找亚斯娜,而使用了自爆招数,即使胆小但也有以图大局。两年里,最痛惜的一次离别,桐人答应好药保护好幸,但最后当他发现只是陷阱时已经晚了,最后两人也就真正的告别了。两年里,最豁达的一次选择,桐人为了亚斯娜而接受了茅场晶彦的挑战,但为了能与亚斯娜在一起,他不得不这么做。两年里,最心酸的一次亲情,桐人由于知道了自己的身份后,对直叶一直很冷清,但最后发现自己的冷淡太过分后,决定好好对待妹妹两年里,最逼真的一场戏剧,黄金苹果的两位成员为了调查事情的真相,而利用一些招数。使其发生了圈内事件。两年里,最遗憾的一场爱情,铁匠师莉兹贝特喜欢上了桐人,但发现桐人真正爱的人是亚斯娜后。也只好无奈得祝福她们,两年里,最旷世的一份大爱无疆,桐人为了自己的爱人,而奋不顾身地保护好她,此所谓大爱无疆。一定要说为什么的话,大概这些,就是我爱刀剑的理由。那些活灵活现的人物们,红色头发的宅男,黑发的剑士少年,健壮的光头大叔,栗色头发的副队闪光,为了自己的梦想的游戏执照者,祝福自己所爱的粉色头发铁匠师,有只宠物陪伴的小萝莉。很多时候只要说出一两个相关的词,就能想到是谁,能在脑海里勾勒出是一个怎么样的人,有着怎么样感动人心的事迹。有一句话我很喜欢,是说,从现在开始我将为你而活,亚斯娜。我觉得那些说着刀剑变了的人真的很不负责任啊,怎么就变了?你在看着它的每一集都在变,它哪里变了?它不让你感动了?以前为了桐人的执着会感动,现在也会为了那些逝去的人而感动。难道你们看着的迪亚布尔离开都不会感动吗?曾经那么固执的一个骑士,不相信任何人,却在最后选择了相信桐人。在桐人高兴的以为每个人都可以活下来的时候你们哭了吗?茅场这个傻子,这世上怎么可能有这样方式?可是这样残忍的离别,它用深入骨髓的刻画给我们的是什么?是感动,还有更多的深思和缅怀。我一直觉得,有些事情是没办法去衡量和比较的。就算它衰败到只是两三个人守着,可世界上总有那么一些人,会为之疯狂。所谓的刀剑迷,大概就是这样的吧。真正的刀剑迷,应该是不会被任何事物所击败的。我做事情,从不半途而废!懂得刀剑神域的刀剑迷就该明白,既然坚持了一件自己所认可的事情,就一定要相信下去。我一直相信着,刀剑没有变。感动不离开,他们一直在。那些日日夜夜里对着自己说话微笑的人们,不会被丢弃。我相信总有一天所有人都会把过去甩进记忆的最角落,不经天雷地火再也不会复燃。但总有一天它会彻彻底底的燃烧我们,彻底复苏。那些是不能复刻的感动回忆,边刃暗藏锋利,全是一点一点的片段,却携着两年的岁月呼啸而来。如果还记得最初的感动,如果还能在第一时间叫出那些人的名字,如果时隔多年想起那些画面仍然眼眶泛红。记住,我们的名字,刀剑迷,永远的刀剑迷。川原,请让我真心的说一句,一直以来,谢谢你了
动漫频道 5 0 272天前
admin
451
原文转载自:https://www.zhihu.com/question/27971703   作者:pezy根据 Appending Binary Files Using the COPY Command 可粗略的认为,就是以二进制的方式合并两个文件到一个新文件中。举例说明:echo Hello > 1.txt echo World > 2.txt copy /b 1.txt+2.txt 3.txt 那么此刻 3.txt 中应该是Hello World 如果仅仅实现上述例子中的基本功能,使用几个系统的 API 就可以搞定。代码如下:#include <windows.h> #include <stdio.h> void main() { HANDLE hFile; HANDLE hAppend; DWORD dwBytesRead, dwBytesWritten, dwPos; BYTE buff[4096]; // Copy the existing file. BOOL bCopy = CopyFile(TEXT("1.txt"), TEXT("3.txt"), TRUE); if (!bCopy) { printf("Could not copy 1.txt to 3.txt."); return; } // Open the existing file. hFile = CreateFile(TEXT("2.txt"), // open 2.txt GENERIC_READ, // open for reading 0, // do not share NULL, // no security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if (hFile == INVALID_HANDLE_VALUE) { printf("Could not open 2.txt."); return; } // Open the existing file, or if the file does not exist, // create a new file. hAppend = CreateFile(TEXT("3.txt"), // open 3.txt FILE_APPEND_DATA, // open for writing FILE_SHARE_READ, // allow multiple readers NULL, // no security OPEN_ALWAYS, // open or create FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if (hAppend == INVALID_HANDLE_VALUE) { printf("Could not open 3.txt."); return; } // Append the first file to the end of the second file. // Lock the second file to prevent another process from // accessing it while writing to it. Unlock the // file when writing is complete. while (ReadFile(hFile, buff, sizeof(buff), &dwBytesRead, NULL) && dwBytesRead > 0) { dwPos = SetFilePointer(hAppend, 0, NULL, FILE_END); LockFile(hAppend, dwPos, 0, dwBytesRead, 0); WriteFile(hAppend, buff, dwBytesRead, &dwBytesWritten, NULL); UnlockFile(hAppend, dwPos, 0, dwBytesRead, 0); } // Close both files. CloseHandle(hFile); CloseHandle(hAppend); } 将代码中的 1.txt, 2.txt, 3.txt 改为任何别的文件,是一样的。如题主补充的要求,做如下替换即可:1.txt -> a.jpg2.txt -> b.txt3.txt -> c.txt (文本),c.jpg(更改后缀,成为图片)诸如 jpg 之类的格式,依然是二进制文件,经过渲染,表现为图片而已。
开发 5 0 276天前
admin
584
本篇内容,用编程思想自制空调,包括完整的软件开发阶段,同时针对此设计进行总结与优化。开发背景——停电了,不能编程,空调也不能用。这……不能编程可以,不吹空调简直不能忍啊,怎么处理?需求分析——使用现有的工具,以及技术完成小型空调的设计,要能够制冷。框架:使用某宝的小风扇(JDK源代码),以及制冷核心物品:冰块(JDK工厂函数)。开发工具:螺丝刀套件(eclipse),生产冰块的工具(工厂模式)开发平台:桌子(Java)多线程:在设计小空调的同时,首先使用别的开发工具(冰箱)冻冰块。疑问:空调还需要冰块,冰块还得去冰箱冻,不是更浪费资源么?并非如此,即使冻冰块使用电量,小空调运作需要电量,但是加起来也远不止真正的空调运行需要的电量。所以,此物十足就是小型空调啊,只是内部机理不同。软件设计和编码1.首先准备材料,风扇,载体,剪刀,胶带,螺丝刀……2.首先要继承“小风扇”这个类,只需要找出其中的方法进行重写,方法使用。3.将空调外壳(显示层)和内核层之间做做个接口。4.接口做好了,但是最简单的接口,必须进行修改才能使用。5.修改接口,加固衔接部分。6.使用重写的方法进行交互,使用方法实现类中成员属性螺丝拧上去。7.核心电机做好了,进行显示层包装,对显示层进行修改,让冷风能够按要求吹出去。8.进行简单的修改以后发现前端松松垮垮,不会按照我们的需求输出内容,所以给输出口加个CSS样式。软件测试加好CSS样式以后,放入冰块进行测试:结果发现:电机漏风严重!马上追加补丁修复漏洞。nice!完成总结于展望总结:使用工具类进行程序设计,基本功能已经完成。虽然还是多余的使用冰块,但是最终用的电量还是比空调少,自然能力也比空调弱,就是小的空调。展望:风力不够,需要修改硬件。系统的耦合度太高,不便于维护,今后的开发一定要控制好耦合度!!
开发 5 0 283天前
admin
532
  对于ps怎么抠公章,也是很多photoshop用户询问的一个问题。ps抠公章通常会使用色彩范围或者通道来抠公章。下面截图,左边是扫描稿里面一份合同里面加盖的公章。我们使用photoshop将公章抠取出来,然后调色稍微修补之后的效果,如右边所示。由于不是实际使用,只是做教程演示,因此细节部分没有做精细处理,旨在介绍其方法。下面是具体的ps抠公章操作步骤。1.在photoshop打开需要抠公章的图像文件。2.按下CTRL+J,复制背景图层,得到图层1.3.执行“选择——色彩范围”,用吸管单击红色公章部分,如果第一次选取红色不够,再次单击右边的“+”吸管,再增加红色范围,边吸取边看中间的预览,直到合适为止。 附:色彩范围的详细使用方法教程:http://www.ittribalwo.com/article/1760.html4.按下CTRL+J,将选区内的图像,复制到新图层,得到图层2。5.单击图层1,新建一个图层,得到图层3,填充白色。放在图层1和2中间。 公章大概轮廓抠取出来了,还需要进一步处理颜色和修补公章右下方的圆形。6.现在PS抠出来的公章,很淡,因此使用一个小技巧,单击图层2,反复按下CTRL+J,复制图层2,得到N个图层。最后将这些图层合并,使用让公章轮廓更加清晰。前后对比如下: 7.新建色相饱和度调整图层,选择红色,进行如下图调整。此时,公章的色彩得到了校正。 8.最后的细节,将一些杂色或者公章缺少细节的地方,使用仿制图章或者修补类工具进行修补。ps抠公章步骤到此就结束了。如果对仿制图章工具使用不了解,可以参考之前视频教程:http://www.ittribalwo.com/article/2080.html如果觉得此文对自己有所启发,可以收藏或者分享给遇到:ps怎么抠公章问题的朋友。学习中有疑问,也可以加入我们的Photoshop学习群。题外话,网络上的教程再好也是死的,本文件介绍的PS抠公章也只是针对本文的公章图像而言。如果换一幅图像,可能方法又有所不同。因此,不同的图像会有不同的方法来处理。在IT部落窝开发的中级视频教程里面配合案例介绍各类图像的抠图方法,具体请到官网淘宝店了解: http://itblw.taobao.com附:如何用ps做公章的方法和步骤截图
其他 5 0 291天前
admin
469
转载自:http://www.cnblogs.com/leadzen/archive/2008/09/06/1285764.html你知道世界上有多少种浏览器吗?除了我们熟知的IE, Firefox, Opera, Safari四大浏览器之外,世界上还有近百种浏览器。       几天前,浏览器家族有刚诞生了一位小王子,就是Google推出的Chrome浏览器。由于Chrome出生名门,尽管他还是个小家伙,没有人敢小看他。以后,咱们常说浏览器的“四大才子”就得改称为“五朵金花”了。       在网站前端开发中,浏览器兼容性问题本已让我们手忙脚乱,Chrome的出世不知道又要给我们添多少乱子。浏览器兼容性是前端开发框架要解决的第一个问题,要解决兼容性问题就得首先准确判断出浏览器的类型及其版本。       JavaScript是前端开发的主要语言,我们可以通过编写JavaScript程序来判断浏览器的类型及版本。JavaScript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性来分辨,另一种是通过分析浏览器的userAgent属性来判断的。在许多情况下,值判断出浏览器类型之后,还需判断浏览器版本才能处理兼容性问题,而判断浏览器的版本一般只能通过分析浏览器的userAgent才能知道。       我们先来分析一下各种浏览器的特征及其userAgent。       IE      只有IE支持创建ActiveX控件,因此她有一个其他浏览器没有的东西,就是ActiveXObject函数。只要判断window对象存在ActiveXObject函数,就可以明确判断出当前浏览器是IE。而IE各个版本典型的userAgent如下:         Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)        Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)        Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)        Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)      其中,版本号是MSIE之后的数字。       Firefox       Firefox中的DOM元素都有一个getBoxObjectFor函数,用来获取该DOM元素的位置和大小(IE对应的中是getBoundingClientRect函数)。这是Firefox独有的,判断它即可知道是当前浏览器是Firefox。Firefox几个版本的userAgent大致如下:        Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1        Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3        Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12      其中,版本号是Firefox之后的数字。       Opera       Opera提供了专门的浏览器标志,就是window.opera属性。Opera典型的userAgent如下:         Opera/9.27 (Windows NT 5.2; U; zh-cn)        Opera/8.0 (Macintosh; PPC Mac OS X; U; en)        Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0      其中,版本号是靠近Opera的数字。       Safari       Safari浏览器中有一个其他浏览器没有的openDatabase函数,可做为判断Safari的标志。Safari典型的userAgent如下:        Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13        Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3       其版本号是Version之后的数字。      Chrome      Chrome有一个MessageEvent函数,但Firefox也有。不过,好在Chrome并没有Firefox的getBoxObjectFor函数,根据这个条件还是可以准确判断出Chrome浏览器的。目前,Chrome的userAgent是:         Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13      其中,版本号在Chrome只后的数字。      有趣的是,Chrome的userAgent还包含了Safari的特征,也许这就是Chrome可以运行所有Apple浏览器应用的基础吧。      只要了解了以上信息,我们就可以根基这些特征来判断浏览器类型及其版本了。我们会将判断的结果保存在Sys名字空间中,成为前端框架的基本标志信息,供今后的程序来读取。如果判断出谋种浏览器,Sys名字空间将有一个该浏览器名称的属性,其值为该浏览器的版本号。例如,如果判断出IE 7.0,则Sys.ie的值为7.0;如果判断出Firefox 3.0,则Sys.firefox的值为3.0。下面是判断浏览器的代码:<script type="text/javascript"> var Sys = {}; var ua = navigator.userAgent.toLowerCase(); if (window.ActiveXObject) Sys.ie = ua.match(/msie ([\d.]+)/)[1] else if (document.getBoxObjectFor) Sys.firefox = ua.match(/firefox\/([\d.]+)/)[1] else if (window.MessageEvent && !document.getBoxObjectFor) Sys.chrome = ua.match(/chrome\/([\d.]+)/)[1] else if (window.opera) Sys.opera = ua.match(/opera.([\d.]+)/)[1] else if (window.openDatabase) Sys.safari = ua.match(/version\/([\d.]+)/)[1]; //以下进行测试 if(Sys.ie) document.write('IE: '+Sys.ie); if(Sys.firefox) document.write('Firefox: '+Sys.firefox); if(Sys.chrome) document.write('Chrome: '+Sys.chrome); if(Sys.opera) document.write('Opera: '+Sys.opera); if(Sys.safari) document.write('Safari: '+Sys.safari); </script>      我们把对IE的判断放在第一,因为IE的用户最多,其次是判断Firefox。按使用者多少的顺序来判断浏览器类型,可以提高判断效率,少做无用功。之所以将Chrome放在第三判断,是因为我们预测Chrome很快会成为市场占有率第三的浏览器。其中,在分析浏览器版本时,用到了正则表达式来析取其中的版本信息。      如果你的JavaScript玩得很高,你还可以将前面的判断代码写成这样:<script type="text/javascript"> var Sys = {}; var ua = navigator.userAgent.toLowerCase(); window.ActiveXObject ? Sys.ie = ua.match(/msie ([\d.]+)/)[1] : document.getBoxObjectFor ? Sys.firefox = ua.match(/firefox\/([\d.]+)/)[1] : window.MessageEvent && !document.getBoxObjectFor ? Sys.chrome = ua.match(/chrome\/([\d.]+)/)[1] : window.opera ? Sys.opera = ua.match(/opera.([\d.]+)/)[1] : window.openDatabase ? Sys.safari = ua.match(/version\/([\d.]+)/)[1] : 0; //以下进行测试 if(Sys.ie) document.write('IE: '+Sys.ie); if(Sys.firefox) document.write('Firefox: '+Sys.firefox); if(Sys.chrome) document.write('Chrome: '+Sys.chrome); if(Sys.opera) document.write('Opera: '+Sys.opera); if(Sys.safari) document.write('Safari: '+Sys.safari); </script>      这样可以使JavaScript代码更精简些。当然,可读性稍差一些,就看你是重视效率还是重视可维护性了。      使用不同特征来判断浏览器的方法,虽然在速度上比用正则表达式分析userAgent要来的快,不过这些特征可能会随浏览器版本而变化。比如,一种浏览器本来独有的特性取得了市场上的成功,其他浏览器也就可能跟着加入该特性,从而使该浏览器的独有特征消失,导致我们的判断失败。因此,相对比较保险的做法是通过解析userAgent中的特征来判断浏览器类型。何况,反正判断版本信息也需要解析浏览器的userAgent的。      通过分析各类浏览器的userAgent信息,不难得出分辨各类浏览器及其版本的正则表达式。而且,对浏览器类型的判断和版本的判断完全可以合为一体地进行。于是,我们可以写出下面的代码:<script type="text/javascript"> var Sys = {}; var ua = navigator.userAgent.toLowerCase(); var s; (s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] : (s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] : (s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] : (s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] : (s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0; //以下进行测试 if (Sys.ie) document.write('IE: ' + Sys.ie); if (Sys.firefox) document.write('Firefox: ' + Sys.firefox); if (Sys.chrome) document.write('Chrome: ' + Sys.chrome); if (Sys.opera) document.write('Opera: ' + Sys.opera); if (Sys.safari) document.write('Safari: ' + Sys.safari); </script>      其中,采用了“... ? ... : ...”这样的判断表达式来精简代码。判断条件是一条赋值语句,既完成正则表达式的匹配及结果复制,又直接作为条件判断。而随后的版本信息只需从前面的匹配结果中提取即可,这是非常高效的代码。       以上的代码都是为了打造前端框架所做的预研,并在五大浏览器上测试通过。今后,判断某种浏览器只需用if(Sys.ie)或if(Sys.firefox)等形式,而判断浏览器版本只需用if(Sys.ie == '8.0')或if(Sys.firefox == '3.0')等形式,表达起来还是非常优雅的。      前端框架项目已经启动,一切就看过程和结果了...IE11(转载自:http://keenwon.com/851.html) : $(function () { var Sys = {}; var ua = navigator.userAgent.toLowerCase(); var s; (s = ua.match(/rv:([\d.]+)\) like gecko/)) ? Sys.ie = s[1] : (s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] : (s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] : (s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] : (s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] : (s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0; if (Sys.ie) $('span').text('IE: ' + Sys.ie); if (Sys.firefox) $('span').text('Firefox: ' + Sys.firefox); if (Sys.chrome) $('span').text('Chrome: ' + Sys.chrome); if (Sys.opera) $('span').text('Opera: ' + Sys.opera); if (Sys.safari) $('span').text('Safari: ' + Sys.safari); }); 在线演示:http://keenwon.com/demo/201402/js-check-browser.html
开发 5 0 299天前
admin
446
转载:http://pcedu.pconline.com.cn/966/9669884.html  【PConline 杂谈】SSD已经日渐流行,现在买电脑不挑带SSD的,都不好意思说自己真懂用户体验。和传统HDD相比,SSD由闪存构成,闪存低延迟的特性,令SSD在随机读写性能方面大幅超越HDD,这也是SSD能带来流畅操作体验的关键。但是,SSD又不仅仅只是闪存的简单组装,仅仅把闪存堆砌起来,并不能称作是SSD。调用闪存的软件算法,同样对SSD的寿命、稳定性、性能等方方面面起着重大作用。SSD中的软件算法你都了解吗?今天,就一起来谈谈SSD中有哪些软件算法吧!SSD可不是把闪存焊在一起就能做出来的  FTL:没它SSD就无法识别  我们都知道SSD的硬件构成和HDD完全不同,因此操作系统识别HDD的很多机制,并不适用于SSD。例如,硬盘是由盘片来构成的,盘片是同心圆,把圆分成一个个小小的扇形,数据在这些扇形中储存,这些扇形就被称之为扇区。操作系统把扇区组织起来,构成FAT32、NTFS等文件系统,用户才得以访问文件/文件夹而不是一个个的扇区物理地址。基本上,操作系统建立文件系统的基础就是扇区。HDD硬盘盘片上的扇区,SSD没有这个结构  SSD由闪存构成,没有盘片,自然也没有扇区。SSD的闪存颗粒基础单位是数据容量4KB的Page(页),Page组成Block(区),Block组成Plane(平面),最后Plane组成Die(晶片),这就是闪存的硬件架构。可见SSD没有扇区,怎么办?这就得靠一些算法来进行转换了。SSD使用的是闪存,闪存结构和HDD不同,需要FTL层和文件系统对话  把SSD的架构虚拟成HDD的算法,叫做“FTL”(Flash Translation Lay)。FTL算法是由SSD主控提供的,比操作系统更加底层。FTL作为一个软件中间层,可以把SSD基于Page的硬件架构映射成HDD基于扇区的硬件架构。操作系统为SSD建立文件系统的时候,有了FTL,操作系统看到的东西和HDD没啥两样,就可以用传统的方法对SSD进行分区、格式化等操作,不需要使用专为SSD而生的文件系统。得益于FTL软件算法,SSD才能无缝接班HDD,没它SSD就无法识别。  GC垃圾回收:没它SSD就巨慢无比  闪存的机制是比较独特的,当你向闪存写入数据的时候,必须先把闪存中的数据擦除掉,才能写入。同时,闪存的最小读写单位是Page,但最小的擦除单位是Block。一个Block中包含了多个Page,SSD工作一段时间后,就没有哪个Block中的Page都是空白的了。如果要擦除某个Block,就必须先把这个Block中存在有效数据的Page复制备份到其他地方,接而进行擦除,这样一来才不会丢数据。每个Page都可以写入数据,但覆盖写入需要先擦除原先的数据,一擦除整个Block都会被擦除  有效数据的Page要复制到什么地方进行备份呢?一些比较烂的产品,会把这些Page的数据复制到缓存,待到Block擦除后,再把数据写回去,这样一来SSD的写入速度就更加悲剧了——既要写原来的数据,又要写新数据。解决这个问题的,就是SSD中的GC(Gabage Collection),也就是垃圾回收算法。  GC垃圾回收算法看着有点类似碎片整理,它可以把某个Block中的存在有效数据的Page,移动到其他Block中,从而让操作系统得以擦除这整一个Block。接着再往该Block写数据,就不需要把备份到其他地方的Page也写回去了。CG发生在FTL层,不同的SSD的GC算法是不一样的,GC算法的不同,深切影响着SSD的性能。  Trim:大大提高垃圾回收效率  Trim是一种用来增加GC垃圾回收效率的算法。没有Trim的话,会出现这样一种情况:在操作系统删除一个文件,实际上数据在物理层面上并没有被删除。于是,SSD的某个Block所有Page都会被填满,待到真正写入数据的时候,才被迫进行GC垃圾回收,主控才开始把有效数据的Page移动到其他Block上,进而擦除该Block。如此一来,速度就很慢,SSD用久了每次写入数据都得先GC,用户体验非常不好。CMD中查询“fsutil behavior QUERY DisableDeleteNotify”,如图显示就是开启了Trim  Trim就可以大大缓解这种情况。操作系统删除数据后,Trim会告诉SSD主控哪些Page的数据对应着删除的数据,这些Page会被标记成为无效Page。接着,在闲暇时段,SSD主控就会主动进行CG,把有效数据的Page移走,然后擦除这些Block的数据,提前为操作系统的数据写入准备好足够多的Block。如此一来,就算是长期使用,只要SSD不是装得太满,性能都不会有太过明显的下滑,大大提升了用户体验。Trim算法是由操作系统提供的,Win7、Android 4.3以后的操作系统都支持Trim。  磨损平衡:保证闪存寿命被均匀消耗  我们知道闪存是有擦写寿命的,例如MLC闪存只能够擦写数千次,TLC闪存只能够擦写数百次等等。其实以现在的SSD容量,总擦写数据量是非常惊人的,例如256G的SSD,寿命是500次擦写(P/E)的话,那么就需要写入125TB的数据,闪存才寿终正寝——就算你每天写入10G数据,也需要用三十多年才能把闪存给写挂,更何况很少人每天往SSD中写10G数据。TLC的擦写次数不尽如人意,但正常使用其实也很难挂掉  但是很多朋友仍不信任SSD的寿命,理由是SSD的这个寿命,是根据全盘容量来估算的。有的朋友认为,平时读写数据,会集中读写SSD的其中一部分闪存,这部分的闪存寿命就会损耗得特别快。一旦这部分闪存挂了,那么整块SSD也就挂了。然而事实真的是这样吗?  事实当然并非如此。实际上,SSD拥有磨损平衡(Wear Leveling)算法,令所有闪存磨损度尽可能保持一致。SSD的磨损平衡算法大致分为动态和静态两种。动态的算法就是当写入新数据的时候,会自动往比较新的Block中去写,老的闪存就放在一旁歇歇;而静态的算法就更加先进,就算没有数据写入,SSD监测到某些闪存Block比较老,会自动进行数据分配,让比较老的闪存Block承担不需要写数据的储存任务,同时让较新的闪存Block腾出空间,平日的数据读写就在比较新的Block中进行——如此一来,各个Block的寿命损耗,就都差不多了。  总结  SSD绝不是把闪存堆在一起就能做成的,要让SSD稳定、快速地运行,还有赖于种种软件算法。在选用SSD的时候,可以多关注一下该SSD所使用的主控方案,关注该主控的算法是否靠谱;在使用SSD时,要选择适合的操作系统,并及时更新SSD的固件和驱动。如此一来,才会得到更好的体验。
维护 5 0 299天前
桂公网安备 45010302000666号 桂ICP备14001770-3号
您的IP:54.224.151.24,2018-05-27 05:10:17,Processed in 1.14062 second(s).
免责声明: 本网不承担任何由内容提供商提供的信息所引起的争议和法律责任。
Powered by HadSky 5.5.2